fluid_midishare.c
上传用户:tjmskj2
上传日期:2020-08-17
资源大小:577k
文件大小:12k
- /* FluidSynth - A Software Synthesizer
- *
- * Copyright (C) 2003 Peter Hanappe and others.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public License
- * as published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
- /* fluid_midishare.c
- *
- * Author: Stephane Letz (letz@grame.fr) Grame
- *
- * Interface to Grame's MidiShare drivers (www.grame.fr/MidiShare)
- * 21/12/01 : Add a compilation flag (MIDISHARE_DRIVER) for driver or application mode
- * 29/01/02 : Compilation on MacOSX, use a task for typeNote management
- * 03/06/03 : Adapdation for FluidSynth API
- * 18/03/04 : In appplication mode, connect MidiShare to the fluidsynth client (fluid_midishare_open_appl)
- */
- #include "config.h"
- #if MIDISHARE_SUPPORT
- #include "fluid_midi.h"
- #include "fluid_mdriver.h"
- #include <MidiShare.h>
- /* constants definitions */
- #define MidiShareDrvRef 127
- #if defined(MACINTOSH) && defined(MACOS9)
- #define MSHSlotName "pfluidsynth"
- #define MSHDriverName "pfluidsynth"
- #else
- #define MSHSlotName "fluidsynth"
- #define MSHDriverName "fluidsynth"
- #endif
- typedef struct {
- fluid_midi_driver_t driver;
- int status;
- short refnum;
- MidiFilterPtr filter;
- #if defined(MACINTOSH) && defined(MACOS9)
- UPPRcvAlarmPtr upp_alarm_ptr;
- UPPDriverPtr upp_wakeup_ptr;
- UPPDriverPtr upp_sleep_ptr;
- UPPTaskPtr upp_task_ptr;
- #endif
- SlotRefNum slotRef;
- unsigned char sysexbuf[FLUID_MIDI_PARSER_MAX_DATA_SIZE];
- } fluid_midishare_midi_driver_t;
- fluid_midi_driver_t* new_fluid_midishare_midi_driver(fluid_settings_t* settings,
- handle_midi_event_func_t handler,
- void* data);
- int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p);
- int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p);
- static void fluid_midishare_midi_driver_receive(short ref);
- #if defined(MIDISHARE_DRIVER)
- static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev);
- static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev);
- #else
- static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev);
- static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev);
- #endif
- /*
- * new_fluid_midishare_midi_driver
- */
- fluid_midi_driver_t*
- new_fluid_midishare_midi_driver(fluid_settings_t* settings,
- handle_midi_event_func_t handler,
- void* data)
- {
- fluid_midishare_midi_driver_t* dev;
- int i;
- /* not much use doing anything */
- if (handler == NULL) {
- FLUID_LOG(FLUID_ERR, "Invalid argument");
- return NULL;
- }
- /* allocate the device */
- dev = FLUID_NEW(fluid_midishare_midi_driver_t);
- if (dev == NULL) {
- FLUID_LOG(FLUID_ERR, "Out of memory");
- return NULL;
- }
- FLUID_MEMSET(dev, 0, sizeof(fluid_midishare_midi_driver_t));
- dev->driver.handler = handler;
- dev->driver.data = data;
- /* register to MidiShare as Application or Driver */
- #if defined(MIDISHARE_DRIVER)
- if (!fluid_midishare_open_driver(dev)) goto error_recovery;
- #else
- if (!fluid_midishare_open_appl(dev)) goto error_recovery;
- #endif
- /*MidiSetInfo(dev->refnum, dev->router->synth); */
- MidiSetInfo(dev->refnum, dev);
- dev->filter = MidiNewFilter();
- if (dev->filter == 0) {
- FLUID_LOG(FLUID_ERR, "Can not allocate MidiShare filter");
- goto error_recovery;
- }
- for (i = 0 ; i < 256; i++) {
- MidiAcceptPort(dev->filter, i, 1); /* accept all ports */
- MidiAcceptType(dev->filter, i, 0); /* reject all types */
- }
- for (i = 0 ; i < 16; i++) {
- MidiAcceptChan(dev->filter, i, 1); /* accept all chan */
- }
- /* accept only the following types */
- MidiAcceptType(dev->filter, typeNote, 1);
- MidiAcceptType(dev->filter, typeKeyOn, 1);
- MidiAcceptType(dev->filter, typeKeyOff, 1);
- MidiAcceptType(dev->filter, typeCtrlChange, 1);
- MidiAcceptType(dev->filter, typeProgChange, 1);
- MidiAcceptType(dev->filter, typePitchWheel, 1);
- MidiAcceptType(dev->filter, typeSysEx, 1);
- /* set the filter */
- MidiSetFilter(dev->refnum, dev->filter);
- dev->status = FLUID_MIDI_READY;
- return (fluid_midi_driver_t*) dev;
- error_recovery:
- delete_fluid_midishare_midi_driver((fluid_midi_driver_t*) dev);
- return NULL;
- }
- /*
- * delete_fluid_midishare_midi_driver
- */
- int delete_fluid_midishare_midi_driver(fluid_midi_driver_t* p)
- {
- fluid_midishare_midi_driver_t* dev;
- dev = (fluid_midishare_midi_driver_t*) p;
- if (dev == NULL) {
- return FLUID_OK;
- }
- if (dev->filter) MidiFreeFilter(dev->filter);
- #if defined(MIDISHARE_DRIVER)
- fluid_midishare_close_driver(dev);
- #else
- fluid_midishare_close_appl(dev);
- #endif
- #if defined(MACINTOSH) && defined(MACOS9)
- DisposeRoutineDescriptor(dev->upp_alarm_ptr);
- DisposeRoutineDescriptor(dev->upp_wakeup_ptr);
- DisposeRoutineDescriptor(dev->upp_sleep_ptr);
- DisposeRoutineDescriptor(dev->upp_task_ptr);
- #endif
- dev->status = FLUID_MIDI_DONE;
- FLUID_FREE(dev);
- return FLUID_OK;
- }
- /*
- * fluid_midishare_midi_driver_status
- */
- int fluid_midishare_midi_driver_status(fluid_midi_driver_t* p)
- {
- fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*) p;
- return dev->status;
- }
- /*
- * fluid_midishare_keyoff_task
- */
- static void fluid_midishare_keyoff_task (long date, short ref, long a1, long a2, long a3)
- {
- fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
- fluid_midi_event_t new_event;
- MidiEvPtr e =(MidiEvPtr)a1;
- fluid_midi_event_set_type(&new_event, NOTE_OFF);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_pitch(&new_event, Pitch(e));
- fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */
- /* and send it on its way to the router */
- (*dev->driver.handler)(dev->driver.data, &new_event);
- MidiFreeEv(e);
- }
- /*
- * fluid_midishare_midi_driver_receive
- */
- static void fluid_midishare_midi_driver_receive(short ref)
- {
- fluid_midishare_midi_driver_t* dev = (fluid_midishare_midi_driver_t*)MidiGetInfo(ref);
- fluid_midi_event_t new_event;
- MidiEvPtr e;
- int count, i;
- while ((e = MidiGetEv (ref)))
- {
- switch (EvType (e))
- {
- case typeNote:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, NOTE_ON);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_pitch(&new_event, Pitch(e));
- fluid_midi_event_set_velocity(&new_event, Vel(e));
- /* and send it on its way to the router */
- (*dev->driver.handler)(dev->driver.data, &new_event);
- #if defined(MACINTOSH) && defined(MACOS9)
- MidiTask(dev->upp_task_ptr, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
- #else
- MidiTask(fluid_midishare_keyoff_task, MidiGetTime()+Dur(e), ref, (long)e, 0, 0);
- #endif
- /* e gets freed in fluid_midishare_keyoff_task */
- continue;
- case typeKeyOn:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, NOTE_ON);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_pitch(&new_event, Pitch(e));
- fluid_midi_event_set_velocity(&new_event, Vel(e));
- break;
- case typeKeyOff:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, NOTE_OFF);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_pitch(&new_event, Pitch(e));
- fluid_midi_event_set_velocity(&new_event, Vel(e)); /* release vel */
- break;
- case typeCtrlChange:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, CONTROL_CHANGE);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_control(&new_event, MidiGetField(e,0));
- fluid_midi_event_set_value(&new_event, MidiGetField(e,1));
- break;
- case typeProgChange:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, PROGRAM_CHANGE);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_program(&new_event, MidiGetField(e,0));
- break;
- case typePitchWheel:
- /* Copy the data to fluid_midi_event_t */
- fluid_midi_event_set_type(&new_event, PITCH_BEND);
- fluid_midi_event_set_channel(&new_event, Chan(e));
- fluid_midi_event_set_value(&new_event, ((MidiGetField(e,0)
- + (MidiGetField(e,1) << 7))
- - 8192));
- break;
- case typeSysEx:
- count = MidiCountFields (e);
- /* Discard empty or too large SYSEX messages */
- if (count == 0 || count > FLUID_MIDI_PARSER_MAX_DATA_SIZE)
- {
- MidiFreeEv (e);
- continue;
- }
- /* Copy SYSEX data, one byte at a time */
- for (i = 0; i < count; i++)
- dev->sysexbuf[i] = MidiGetField (e, i);
- fluid_midi_event_set_sysex (&new_event, dev->sysexbuf, count, FALSE);
- break;
- default:
- MidiFreeEv (e);
- continue;
- }
- MidiFreeEv (e);
- /* Send the MIDI event */
- (*dev->driver.handler)(dev->driver.data, &new_event);
- }
- }
- #if defined(MIDISHARE_DRIVER)
- /*
- * fluid_midishare_wakeup
- */
- static void fluid_midishare_wakeup (short r)
- {
- MidiConnect (MidiShareDrvRef, r, true);
- MidiConnect (r, MidiShareDrvRef, true);
- }
- /*
- * fluid_midishare_sleep
- */
- static void fluid_midishare_sleep (short r){}
- /*
- * fluid_midishare_open_driver
- */
- static int fluid_midishare_open_driver (fluid_midishare_midi_driver_t* dev)
- {
- /* gcc wanted me to use {0,0} to initialize the reserved[2] fields */
- TDriverInfos infos = { MSHDriverName, 100, 0, { 0, 0 } };
- TDriverOperation op = { fluid_midishare_wakeup, fluid_midishare_sleep, { 0, 0, 0 } };
- /* register to MidiShare */
- #if defined(MACINTOSH) && defined(MACOS9)
- dev->upp_wakeup_ptr = NewDriverPtr(fluid_midishare_wakeup);
- dev->upp_sleep_ptr = NewDriverPtr(fluid_midishare_sleep);
- op.wakeup = (WakeupPtr)dev->upp_wakeup_ptr;
- op.sleep = (SleepPtr)dev->upp_sleep_ptr;
- dev->refnum = MidiRegisterDriver(&infos, &op);
- if (dev->refnum < 0) {
- FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client");
- return 0;
- }
- dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot);
- dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive);
- dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task);
- MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr);
- #else
- dev->refnum = MidiRegisterDriver(&infos, &op);
- if (dev->refnum < 0) {
- FLUID_LOG(FLUID_ERR, "Can not open MidiShare Application client");
- return 0;
- }
- dev->slotRef = MidiAddSlot (dev->refnum, MSHSlotName, MidiOutputSlot);
- MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive);
- #endif
- return 1;
- }
- /*
- * fluid_midishare_close_driver
- */
- static void fluid_midishare_close_driver (fluid_midishare_midi_driver_t* dev)
- {
- if (dev->refnum > 0) MidiUnregisterDriver(dev->refnum);
- }
- #else /* #if defined(MIDISHARE_DRIVER) */
- /*
- * fluid_midishare_open_appl
- */
- static int fluid_midishare_open_appl (fluid_midishare_midi_driver_t* dev)
- {
- /* register to MidiShare */
- #if defined(MACINTOSH) && defined(MACOS9)
- dev->refnum = MidiOpen(MSHDriverName);
- if (dev->refnum < 0) {
- FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
- return 0;
- }
- dev->upp_alarm_ptr = NewRcvAlarmPtr(fluid_midishare_midi_driver_receive);
- dev->upp_task_ptr = NewTaskPtr(fluid_midishare_keyoff_task);
- MidiSetRcvAlarm(dev->refnum, dev->upp_alarm_ptr);
- #else
- dev->refnum = MidiOpen(MSHDriverName);
- if (dev->refnum < 0) {
- FLUID_LOG(FLUID_ERR, "Can not open MidiShare Driver client");
- return 0;
- }
- MidiSetRcvAlarm(dev->refnum, fluid_midishare_midi_driver_receive);
- MidiConnect(0,dev->refnum,true);
- #endif
- return 1;
- }
- /*
- * fluid_midishare_close_appl
- */
- static void fluid_midishare_close_appl (fluid_midishare_midi_driver_t* dev)
- {
- if (dev->refnum > 0) MidiClose(dev->refnum);
- }
- #endif /* #if defined(MIDISHARE_DRIVER) */
- #endif /* MIDISHARE_SUPPORT */