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

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_coremidi.c
  21.  *
  22.  * Driver for Mac OSX native MIDI
  23.  * Pedro Lopez-Cabanillas, Jan 2009
  24.  */
  25. #include "fluidsynth_priv.h"
  26. #if COREMIDI_SUPPORT
  27. #include "fluid_midi.h"
  28. #include "fluid_mdriver.h"
  29. #include "fluid_settings.h"
  30. /* Work around for OSX 10.4 */
  31. /* enum definition in OpenTransportProviders.h defines these tokens 
  32.    which are #defined from <netinet/tcp.h> */
  33. #ifdef TCP_NODELAY
  34. #undef TCP_NODELAY
  35. #endif
  36. #ifdef TCP_MAXSEG
  37. #undef TCP_MAXSEG
  38. #endif
  39. #ifdef TCP_KEEPALIVE
  40. #undef TCP_KEEPALIVE
  41. #endif
  42. /* End work around */
  43. #include <unistd.h>
  44. #include <CoreServices/CoreServices.h>
  45. #include <CoreMIDI/MIDIServices.h>
  46. typedef struct {
  47.   fluid_midi_driver_t driver;
  48.   MIDIClientRef client;
  49.   MIDIEndpointRef endpoint;
  50.   fluid_midi_parser_t* parser;
  51. } fluid_coremidi_driver_t;
  52. fluid_midi_driver_t* new_fluid_coremidi_driver(fluid_settings_t* settings,
  53.                        handle_midi_event_func_t handler, void* data);
  54. int delete_fluid_coremidi_driver(fluid_midi_driver_t* p);
  55. void fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src);
  56. void fluid_coremidi_driver_settings(fluid_settings_t* settings)
  57. {
  58.   fluid_settings_register_str(settings, "midi.coremidi.id", "pid", 0, NULL, NULL);
  59. }
  60. /*
  61.  * new_fluid_coremidi_driver
  62.  */
  63. fluid_midi_driver_t*
  64. new_fluid_coremidi_driver(fluid_settings_t* settings, handle_midi_event_func_t handler, void* data)
  65. {
  66.   fluid_coremidi_driver_t* dev;
  67.   MIDIClientRef client;
  68.   MIDIEndpointRef endpoint;
  69.   char * portname;
  70.   char * id;
  71.   CFStringRef str_portname;
  72.   CFStringRef str_clientname;
  73.   /* not much use doing anything */
  74.   if (handler == NULL) {
  75.     FLUID_LOG(FLUID_ERR, "Invalid argument");
  76.     return NULL;
  77.   }
  78.   dev = FLUID_MALLOC(sizeof(fluid_coremidi_driver_t));
  79.   if (dev == NULL) {
  80.     FLUID_LOG(FLUID_ERR, "Out of memory");
  81.     return NULL;
  82.   }
  83.   dev->client = 0;
  84.   dev->endpoint = 0;
  85.   dev->parser = 0;
  86.   dev->driver.handler = handler;
  87.   dev->driver.data = data;
  88.   dev->parser = new_fluid_midi_parser();
  89.   if (dev->parser == NULL) {
  90.     FLUID_LOG(FLUID_ERR, "Out of memory");
  91.     goto error_recovery;
  92.   }
  93.   fluid_settings_dupstr(settings, "midi.coremidi.id", &id);     /* ++ alloc id string */
  94.   if (!id || FLUID_STRCMP(id, "pid") == 0)
  95.     str_clientname = CFStringCreateWithFormat(NULL, NULL,
  96.                                               CFSTR("FluidSynth %qi"),
  97.                                               (long long) getpid());
  98.   else
  99.     str_clientname = CFStringCreateWithFormat(NULL, NULL,
  100.                                               CFSTR("FluidSynth %s"), id);
  101.   if (id) FLUID_FREE (id);      /* -- free id string */
  102.   fluid_settings_dupstr(settings, "midi.portname", &portname);  /* ++ alloc port name */
  103.   if (!portname || strlen(portname) == 0)
  104.     str_portname = CFStringCreateWithFormat(NULL, NULL,
  105.                                             CFSTR("FluidSynth virtual port %qi"),
  106.                                             (long long) getpid());
  107.   else
  108.     str_portname = CFStringCreateWithCString(NULL, portname,
  109.                                              kCFStringEncodingASCII);
  110.   if (portname) FLUID_FREE (portname);  /* -- free port name */
  111.   OSStatus result = MIDIClientCreate( str_clientname, NULL, NULL, &client );
  112.   if ( result != noErr ) {
  113.     FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input client");
  114.     goto error_recovery;
  115.   }
  116.   dev->client = client;
  117.   result = MIDIDestinationCreate( client, str_portname,
  118.                                   fluid_coremidi_callback,
  119.                                   (void *)dev, &endpoint );
  120.   if ( result != noErr ) {
  121.     FLUID_LOG(FLUID_ERR, "Failed to create the MIDI input port. MIDI input not available.");
  122.     goto error_recovery;
  123.   }
  124.   dev->endpoint = endpoint;
  125.   return (fluid_midi_driver_t*) dev;
  126. error_recovery:
  127.   delete_fluid_coremidi_driver((fluid_midi_driver_t*) dev);
  128.   return NULL;
  129. }
  130. /*
  131.  * delete_fluid_coremidi_driver
  132.  */
  133. int
  134. delete_fluid_coremidi_driver(fluid_midi_driver_t* p)
  135. {
  136.   fluid_coremidi_driver_t* dev = (fluid_coremidi_driver_t*) p;
  137.   if (dev->client != NULL) {
  138.     MIDIClientDispose(dev->client);
  139.   }
  140.   if (dev->endpoint != NULL) {
  141.     MIDIEndpointDispose(dev->endpoint);
  142.   }
  143.   if (dev->parser != NULL) {
  144.     delete_fluid_midi_parser(dev->parser);
  145.   }
  146.   FLUID_FREE(dev);
  147.   return 0;
  148. }
  149. void
  150. fluid_coremidi_callback(const MIDIPacketList *list, void *p, void *src)
  151. {
  152.   unsigned int i, j;
  153.   fluid_midi_event_t* event;
  154.   fluid_coremidi_driver_t* dev = (fluid_coremidi_driver_t *)p;
  155.   const MIDIPacket *packet = &list->packet[0];
  156.   for ( i = 0; i < list->numPackets; ++i ) {
  157.     for ( j = 0; j < packet->length; ++j ) {
  158.       event = fluid_midi_parser_parse(dev->parser, packet->data[j]);
  159.       if (event != NULL) {
  160.         (*dev->driver.handler)(dev->driver.data, event);
  161.       }
  162.     }
  163.     packet = MIDIPacketNext(packet);
  164.   }
  165. }
  166. #endif /* COREMIDI_SUPPORT */