fluid_midishare.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:12k
源码类别:

midi

开发平台:

C/C++

  1. /* FluidSynth - A Software Synthesizer
  2.  *
  3.  * Copyright (C) 2003  Peter Hanappe and others.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public License
  7.  * as published by the Free Software Foundation; either version 2 of
  8.  * the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18.  * 02111-1307, USA
  19.  */
  20. /* fluid_midishare.c
  21.  *
  22.  * Author: Stephane Letz  (letz@grame.fr)  Grame
  23.  *
  24.  * Interface to Grame's MidiShare drivers (www.grame.fr/MidiShare)
  25.  * 21/12/01 : Add a compilation flag (MIDISHARE_DRIVER) for driver or application mode
  26.  * 29/01/02 : Compilation on MacOSX, use a task for typeNote management
  27.  * 03/06/03 : Adapdation for FluidSynth API
  28.  * 18/03/04 : In appplication mode, connect MidiShare to the fluidsynth client (fluid_midishare_open_appl)
  29.  */
  30. #include "config.h"
  31. #if MIDISHARE_SUPPORT
  32. #include "fluid_midi.h"
  33. #include "fluid_mdriver.h"
  34. #include <MidiShare.h>
  35. /* constants definitions    */
  36. #define MidiShareDrvRef 127
  37. #if defined(MACINTOSH) && defined(MACOS9)
  38. #define MSHSlotName "pfluidsynth"
  39. #define MSHDriverName "pfluidsynth"
  40. #else
  41. #define MSHSlotName "fluidsynth"
  42. #define MSHDriverName "fluidsynth"
  43. #endif
  44. typedef struct {
  45.   fluid_midi_driver_t driver;
  46.   int status;
  47.   short refnum;
  48.   MidiFilterPtr filter;
  49.   #if defined(MACINTOSH) && defined(MACOS9)
  50.    UPPRcvAlarmPtr upp_alarm_ptr;
  51.    UPPDriverPtr   upp_wakeup_ptr;
  52.    UPPDriverPtr   upp_sleep_ptr;
  53.    UPPTaskPtr     upp_task_ptr;
  54.   #endif
  55.   SlotRefNum slotRef;
  56.   unsigned char sysexbuf[FLUID_MIDI_PARSER_MAX_DATA_SIZE];
  57. } fluid_midishare_midi_driver_t;
  58. fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
  59.    handle_midi_event_func_t handler,
  60.    void* data);
  61. int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
  62. int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p);
  63. static void fluid_midishare_midi_driver_receive(short ref);
  64. #if defined(MIDISHARE_DRIVER)
  65. static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev);
  66. static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev);
  67. #else
  68. static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev);
  69. static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev);
  70. #endif
  71. /*
  72.  * new_fluid_midishare_midi_driver
  73.  */
  74. fluid_midi_driver_t*
  75. new_fluid_midishare_midi_driver(fluid_settings_t* settings,
  76. handle_midi_event_func_t handler,
  77. void* data)
  78. {
  79.   fluid_midishare_midi_driver_t* dev;
  80.   int i;
  81.   /* not much use doing anything */
  82.   if (handler == NULL) {
  83.     FLUID_LOG(FLUID_ERR, "Invalid argument");
  84.     return NULL;
  85.   }
  86.   /* allocate the device */
  87.   dev = FLUID_NEW(fluid_midishare_midi_driver_t);
  88.   if (dev == NULL) {
  89.     FLUID_LOG(FLUID_ERR, "Out of memory");
  90.     return NULL;
  91.   }
  92.   FLUID_MEMSET(dev, 0, sizeof(fluid_midishare_midi_driver_t));
  93.   dev->driver.handler = handler;
  94.   dev->driver.data = data;
  95.   /* register to MidiShare as Application or Driver */
  96.   #if defined(MIDISHARE_DRIVER)
  97.    if (!fluid_midishare_open_driver(dev)) goto error_recovery;
  98.   #else
  99.    if (!fluid_midishare_open_appl(dev)) goto error_recovery;
  100.   #endif
  101.   /*MidiSetInfo(dev->refnum, dev->router->synth); */
  102.   MidiSetInfo(dev->refnum, dev);
  103.   dev->filter = MidiNewFilter();
  104.   if (dev->filter == 0) {
  105.     FLUID_LOG(FLUID_ERR, "Can not allocate MidiShare filter");
  106.     goto error_recovery;
  107.   }
  108.   for (i = 0 ; i < 256; i++) {
  109.    MidiAcceptPort(dev->filter, i, 1); /* accept all ports */
  110.    MidiAcceptType(dev->filter, i, 0); /* reject all types */
  111.   }
  112.   for (i = 0 ; i < 16; i++) {
  113.    MidiAcceptChan(dev->filter, i, 1); /* accept all chan */
  114.   }
  115.   /* accept only the following types */
  116.   MidiAcceptType(dev->filter, typeNote, 1);
  117.   MidiAcceptType(dev->filter, typeKeyOn, 1);
  118.   MidiAcceptType(dev->filter, typeKeyOff, 1);
  119.   MidiAcceptType(dev->filter, typeCtrlChange, 1);
  120.   MidiAcceptType(dev->filter, typeProgChange, 1);
  121.   MidiAcceptType(dev->filter, typePitchWheel, 1);
  122.   MidiAcceptType(dev->filter, typeSysEx, 1);
  123.   /* set the filter */
  124.   MidiSetFilter(dev->refnum, dev->filter);
  125.   dev->status = FLUID_MIDI_READY;
  126.   return (fluid_midi_driver_t*) dev;
  127.  error_recovery:
  128.   delete_fluid_midishare_midi_driver((fluid_midi_driver_t*) dev);
  129.   return NULL;
  130. }
  131. /*
  132.  * delete_fluid_midishare_midi_driver
  133.  */
  134. int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p)
  135. {
  136.   fluid_midishare_midi_driver_t* dev;
  137.   dev = (fluid_midishare_midi_driver_t*) p;
  138.   if (dev == NULL) {
  139.     return FLUID_OK;
  140.   }
  141.   if (dev->filter) MidiFreeFilter(dev->filter);
  142.   #if defined(MIDISHARE_DRIVER)
  143.     fluid_midishare_close_driver(dev);
  144.   #else
  145.     fluid_midishare_close_appl(dev);
  146.   #endif
  147.   #if defined(MACINTOSH) && defined(MACOS9)
  148.    DisposeRoutineDescriptor(dev->upp_alarm_ptr);
  149.    DisposeRoutineDescriptor(dev->upp_wakeup_ptr);
  150.    DisposeRoutineDescriptor(dev->upp_sleep_ptr);
  151.    DisposeRoutineDescriptor(dev->upp_task_ptr);
  152.   #endif
  153.   dev->status = FLUID_MIDI_DONE;
  154.   FLUID_FREE(dev);
  155.   return FLUID_OK;
  156. }
  157. /*
  158.  * fluid_midishare_midi_driver_status
  159.  */
  160. int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p)
  161. {
  162.   fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*) p;
  163.   return dev->status;
  164. }
  165. /*
  166.  * fluid_midishare_keyoff_task
  167.  */
  168. static void fluid_midishare_keyoff_task (long date, short ref, long a1, long a2, long a3)
  169. {
  170. fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
  171. fluid_midi_event_t new_event;
  172.    MidiEvPtr e =(MidiEvPtr)a1;
  173. fluid_midi_event_set_type(&new_event, NOTE_OFF);
  174. fluid_midi_event_set_channel(&new_event, Chan(e));
  175. fluid_midi_event_set_pitch(&new_event, Pitch(e));
  176. fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */
  177. /* and send it on its way to the router */
  178. (*dev->driver.handler)(dev->driver.data, &new_event);
  179. MidiFreeEv(e);
  180. }
  181. /*
  182.  * fluid_midishare_midi_driver_receive
  183.  */
  184. static void fluid_midishare_midi_driver_receive(short ref)
  185. {
  186.   fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
  187.   fluid_midi_event_t new_event;
  188.   MidiEvPtr e;
  189.   int count, i;
  190.   while ((e = MidiGetEv (ref)))
  191.   {
  192.     switch (EvType (e))
  193.     {
  194.       case typeNote:
  195.         /* Copy the data to fluid_midi_event_t */
  196.         fluid_midi_event_set_type(&new_event, NOTE_ON);
  197.         fluid_midi_event_set_channel(&new_event, Chan(e));
  198.         fluid_midi_event_set_pitch(&new_event, Pitch(e));
  199.         fluid_midi_event_set_velocity(&new_event, Vel(e));
  200.         /* and send it on its way to the router */
  201.         (*dev->driver.handler)(dev->driver.data, &new_event);
  202. #if defined(MACINTOSH) && defined(MACOS9)
  203.         MidiTask(dev->upp_task_ptr, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
  204. #else
  205.         MidiTask(fluid_midishare_keyoff_task, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
  206. #endif
  207.         /* e gets freed in fluid_midishare_keyoff_task */
  208.         continue;
  209.       case typeKeyOn:
  210.         /* Copy the data to fluid_midi_event_t */
  211.         fluid_midi_event_set_type(&new_event, NOTE_ON);
  212.         fluid_midi_event_set_channel(&new_event, Chan(e));
  213.         fluid_midi_event_set_pitch(&new_event, Pitch(e));
  214.         fluid_midi_event_set_velocity(&new_event, Vel(e));
  215.         break;
  216.       case typeKeyOff:
  217.         /* Copy the data to fluid_midi_event_t */
  218.         fluid_midi_event_set_type(&new_event, NOTE_OFF);
  219.         fluid_midi_event_set_channel(&new_event, Chan(e));
  220.         fluid_midi_event_set_pitch(&new_event, Pitch(e));
  221.         fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */
  222.         break;
  223.       case typeCtrlChange:
  224.         /* Copy the data to fluid_midi_event_t */
  225.         fluid_midi_event_set_type(&new_event, CONTROL_CHANGE);
  226.         fluid_midi_event_set_channel(&new_event, Chan(e));
  227.         fluid_midi_event_set_control(&new_event, MidiGetField(e,0));
  228.         fluid_midi_event_set_value(&new_event, MidiGetField(e,1));
  229.         break;
  230.       case typeProgChange:
  231.         /* Copy the data to fluid_midi_event_t */
  232.         fluid_midi_event_set_type(&new_event, PROGRAM_CHANGE);
  233.         fluid_midi_event_set_channel(&new_event, Chan(e));
  234.         fluid_midi_event_set_program(&new_event, MidiGetField(e,0));
  235.         break;
  236.       case typePitchWheel:
  237.         /* Copy the data to fluid_midi_event_t */
  238.         fluid_midi_event_set_type(&new_event, PITCH_BEND);
  239.         fluid_midi_event_set_channel(&new_event, Chan(e));
  240.         fluid_midi_event_set_value(&new_event, ((MidiGetField(e,0)
  241.                                                  + (MidiGetField(e,1) << 7))
  242.                                                 - 8192));
  243.         break;
  244.       case typeSysEx:
  245.         count = MidiCountFields (e);
  246.         /* Discard empty or too large SYSEX messages */
  247.         if (count == 0 || count > FLUID_MIDI_PARSER_MAX_DATA_SIZE)
  248.         {
  249.           MidiFreeEv (e);
  250.           continue;
  251.         }
  252.         /* Copy SYSEX data, one byte at a time */
  253.         for (i = 0; i < count; i++)
  254.           dev->sysexbuf[i] = MidiGetField (e, i);
  255.         fluid_midi_event_set_sysex (&new_event, dev->sysexbuf, count, FALSE);
  256.         break;
  257.       default:
  258.         MidiFreeEv (e);
  259.         continue;
  260.     }
  261.     MidiFreeEv (e);
  262.     /* Send the MIDI event */
  263.     (*dev->driver.handler)(dev->driver.data, &new_event);
  264.   }
  265. }
  266. #if defined(MIDISHARE_DRIVER)
  267. /*
  268.  * fluid_midishare_wakeup
  269.  */
  270. static void fluid_midishare_wakeup (short r)
  271. {
  272. MidiConnect (MidiShareDrvRef, r, true);
  273. MidiConnect (r, MidiShareDrvRef, true);
  274. }
  275. /*
  276.  * fluid_midishare_sleep
  277.  */
  278. static void fluid_midishare_sleep (short r){}
  279. /*
  280.  * fluid_midishare_open_driver
  281.  */
  282. static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev)
  283. {
  284. /* gcc wanted me to use {0,0} to initialize the reserved[2] fields */
  285. TDriverInfos infos = { MSHDriverName, 100, 0, { 0, 0 } };
  286. TDriverOperation op = { fluid_midishare_wakeup, fluid_midishare_sleep, { 0, 0, 0 } };
  287. /* register to MidiShare */
  288. #if defined(MACINTOSH) && defined(MACOS9)
  289. dev->upp_wakeup_ptr = NewDriverPtr(fluid_midishare_wakeup);
  290. dev->upp_sleep_ptr = NewDriverPtr(fluid_midishare_sleep);
  291. op.wakeup = (WakeupPtr)dev->upp_wakeup_ptr;
  292. op.sleep = (SleepPtr)dev->upp_sleep_ptr;
  293. dev->refnum = MidiRegisterDriver(&infos, &op);
  294. if (dev->refnum < 0) {
  295. FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client");
  296. return 0;
  297. }
  298. dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot);
  299. dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive);
  300. dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task);
  301. MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr);
  302. #else
  303. dev->refnum = MidiRegisterDriver(&infos, &op);
  304. if (dev->refnum < 0) {
  305. FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client");
  306. return 0;
  307. }
  308. dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot);
  309. MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive);
  310. #endif
  311. return 1;
  312. }
  313. /*
  314.  * fluid_midishare_close_driver
  315.  */
  316. static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev)
  317. {
  318. if (dev->refnum > 0) MidiUnregisterDriver(dev->refnum);
  319. }
  320. #else   /* #if defined(MIDISHARE_DRIVER) */
  321. /*
  322.  * fluid_midishare_open_appl
  323.  */
  324. static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev)
  325. {
  326. /* register to MidiShare */
  327. #if defined(MACINTOSH) && defined(MACOS9)
  328. dev->refnum = MidiOpen(MSHDriverName);
  329. if (dev->refnum < 0) {
  330. FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
  331. return 0;
  332. }
  333. dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive);
  334. dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task);
  335. MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr);
  336. #else
  337. dev->refnum = MidiOpen(MSHDriverName);
  338. if (dev->refnum < 0) {
  339. FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
  340. return 0;
  341. }
  342. MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive);
  343. MidiConnect(0,dev->refnum,true);
  344. #endif
  345.    return 1;
  346. }
  347. /*
  348.  * fluid_midishare_close_appl
  349.  */
  350. static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev)
  351. {
  352. if (dev->refnum > 0) MidiClose(dev->refnum);
  353. }
  354. #endif  /* #if defined(MIDISHARE_DRIVER) */
  355. #endif /* MIDISHARE_SUPPORT */