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

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_oss.c
  21.  *
  22.  * Drivers for the Open (?) Sound System
  23.  */
  24. #include "fluid_synth.h"
  25. #include "fluid_midi.h"
  26. #include "fluid_adriver.h"
  27. #include "fluid_mdriver.h"
  28. #include "fluid_settings.h"
  29. #if OSS_SUPPORT
  30. #include <sys/soundcard.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35. #include <fcntl.h>
  36. #include <unistd.h>
  37. #include <errno.h>
  38. #include <sys/poll.h>
  39. #define BUFFER_LENGTH 512
  40. /** fluid_oss_audio_driver_t
  41.  *
  42.  * This structure should not be accessed directly. Use audio port
  43.  * functions instead.
  44.  */
  45. typedef struct {
  46.   fluid_audio_driver_t driver;
  47.   fluid_synth_t* synth;
  48.   fluid_audio_callback_t read;
  49.   void* buffer;
  50.   fluid_thread_t *thread;
  51.   int cont;
  52.   int dspfd;
  53.   int buffer_size;
  54.   int buffer_byte_size;
  55.   int bigendian;
  56.   int formats;
  57.   int format;
  58.   int caps;
  59.   fluid_audio_func_t callback;
  60.   void* data;
  61.   float* buffers[2];
  62. } fluid_oss_audio_driver_t;
  63. int delete_fluid_oss_audio_driver(fluid_audio_driver_t* p);
  64. /* local utilities */
  65. static int fluid_oss_set_queue_size(fluid_oss_audio_driver_t* dev, int ss, int ch, int qs, int bs);
  66. static void fluid_oss_audio_run(void* d);
  67. static void fluid_oss_audio_run2(void* d);
  68. typedef struct {
  69.   fluid_midi_driver_t driver;
  70.   int fd;
  71.   fluid_thread_t *thread;
  72.   int status;
  73.   unsigned char buffer[BUFFER_LENGTH];
  74.   fluid_midi_parser_t* parser;
  75. } fluid_oss_midi_driver_t;
  76. fluid_midi_driver_t*
  77. new_fluid_oss_midi_driver(fluid_settings_t* settings,
  78.  handle_midi_event_func_t handler, void* data);
  79. int delete_fluid_oss_midi_driver(fluid_midi_driver_t* p);
  80. int fluid_oss_midi_driver_status(fluid_midi_driver_t* p);
  81. static void fluid_oss_midi_run(void* d);
  82. void
  83. fluid_oss_audio_driver_settings(fluid_settings_t* settings)
  84. {
  85.   fluid_settings_register_str(settings, "audio.oss.device", "/dev/dsp", 0, NULL, NULL);
  86. }
  87. /*
  88.  * new_fluid_oss_audio_driver
  89.  */
  90. fluid_audio_driver_t*
  91. new_fluid_oss_audio_driver(fluid_settings_t* settings, fluid_synth_t* synth)
  92. {
  93.   fluid_oss_audio_driver_t* dev = NULL;
  94.   int channels, sr, sample_size = 0, oss_format;
  95.   struct stat devstat;
  96.   int queuesize;
  97.   double sample_rate;
  98.   int periods, period_size;
  99.   int realtime_prio = 0;
  100.   char* devname = NULL;
  101.   int format;
  102.   dev = FLUID_NEW(fluid_oss_audio_driver_t);
  103.   if (dev == NULL) {
  104.     FLUID_LOG(FLUID_ERR, "Out of memory");
  105.     return NULL;
  106.   }
  107.   FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t));
  108.   fluid_settings_getint(settings, "audio.periods", &periods);
  109.   fluid_settings_getint(settings, "audio.period-size", &period_size);
  110.   fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  111.   fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio);
  112.   dev->dspfd = -1;
  113.   dev->synth = synth;
  114.   dev->callback = NULL;
  115.   dev->data = NULL;
  116.   dev->cont = 1;
  117.   dev->buffer_size = (int) period_size;
  118.   queuesize = (int) (periods * period_size);
  119.   if (fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
  120.     sample_size = 16;
  121.     oss_format = AFMT_S16_LE;
  122.     dev->read = fluid_synth_write_s16;
  123.     dev->buffer_byte_size = dev->buffer_size * 4;
  124.   } else if (fluid_settings_str_equal(settings, "audio.sample-format", "float")) {
  125.     sample_size = 32;
  126.     oss_format = -1;
  127.     dev->read = fluid_synth_write_float;
  128.     dev->buffer_byte_size = dev->buffer_size * 8;
  129.   } else {
  130.     FLUID_LOG(FLUID_ERR, "Unknown sample format");
  131.     goto error_recovery;
  132.   }
  133.   dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
  134.   if (dev->buffer == NULL) {
  135.     FLUID_LOG(FLUID_ERR, "Out of memory");
  136.     goto error_recovery;
  137.   }
  138.   if (!fluid_settings_dupstr(settings, "audio.oss.device", &devname) || !devname) {         /* ++ alloc device name */
  139.     devname = FLUID_STRDUP ("/dev/dsp");
  140.     if (devname == NULL) {
  141.       FLUID_LOG(FLUID_ERR, "Out of memory");
  142.       goto error_recovery;
  143.     }
  144.   }
  145.   if (stat(devname, &devstat) == -1) {
  146.     FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
  147.     goto error_recovery;
  148.   }
  149.   if ((devstat.st_mode & S_IFCHR) != S_IFCHR) {
  150.     FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname);
  151.     goto error_recovery;
  152.   }
  153.   dev->dspfd = open(devname, O_WRONLY, 0);
  154.   if (dev->dspfd == -1) {
  155.     FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
  156.      devname, strerror(errno));
  157.     goto error_recovery;
  158.   }
  159.   if (fluid_oss_set_queue_size(dev, sample_size, 2, queuesize, period_size) < 0) {
  160.     FLUID_LOG(FLUID_ERR, "Can't set device buffer size");
  161.     goto error_recovery;
  162.   }
  163.   format = oss_format;
  164.   if (ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &oss_format) < 0) {
  165.     FLUID_LOG(FLUID_ERR, "Can't set the sample format");
  166.     goto error_recovery;
  167.   }
  168.   if (oss_format != format) {
  169.     FLUID_LOG(FLUID_ERR, "Can't set the sample format");
  170.     goto error_recovery;
  171.   }
  172.   channels = 2;
  173.   if (ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0){
  174.     FLUID_LOG(FLUID_ERR, "Can't set the number of channels");
  175.     goto error_recovery;
  176.   }
  177.   if (channels != 2) {
  178.     FLUID_LOG(FLUID_ERR, "Can't set the number of channels");
  179.     goto error_recovery;
  180.   }
  181.   sr = sample_rate;
  182.   if (ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0){
  183.     FLUID_LOG(FLUID_ERR, "Can't set the sample rate");
  184.     goto error_recovery;
  185.   }
  186.   if ((sr < 0.95 * sample_rate) ||
  187.       (sr > 1.05 * sample_rate)) {
  188.     FLUID_LOG(FLUID_ERR, "Can't set the sample rate");
  189.     goto error_recovery;
  190.   }
  191.   /* Create the audio thread */
  192.   dev->thread = new_fluid_thread (fluid_oss_audio_run, dev, realtime_prio, FALSE);
  193.   if (!dev->thread)
  194.     goto error_recovery;
  195.   if (devname) FLUID_FREE (devname);    /* -- free device name */
  196.   return (fluid_audio_driver_t*) dev;
  197. error_recovery:
  198.   if (devname) FLUID_FREE (devname);    /* -- free device name */
  199.   delete_fluid_oss_audio_driver((fluid_audio_driver_t*) dev);
  200.   return NULL;
  201. }
  202. fluid_audio_driver_t*
  203. new_fluid_oss_audio_driver2(fluid_settings_t* settings, fluid_audio_func_t func, void* data)
  204. {
  205.   fluid_oss_audio_driver_t* dev = NULL;
  206.   int channels, sr;
  207.   struct stat devstat;
  208.   int queuesize;
  209.   double sample_rate;
  210.   int periods, period_size;
  211.   char* devname = NULL;
  212.   int realtime_prio = 0;
  213.   int format;
  214.   dev = FLUID_NEW(fluid_oss_audio_driver_t);
  215.   if (dev == NULL) {
  216.     FLUID_LOG(FLUID_ERR, "Out of memory");
  217.     return NULL;
  218.   }
  219.   FLUID_MEMSET(dev, 0, sizeof(fluid_oss_audio_driver_t));
  220.   fluid_settings_getint(settings, "audio.periods", &periods);
  221.   fluid_settings_getint(settings, "audio.period-size", &period_size);
  222.   fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
  223.   fluid_settings_getint (settings, "audio.realtime-prio", &realtime_prio);
  224.   dev->dspfd = -1;
  225.   dev->synth = NULL;
  226.   dev->read = NULL;
  227.   dev->callback = func;
  228.   dev->data = data;
  229.   dev->cont = 1;
  230.   dev->buffer_size = (int) period_size;
  231.   queuesize = (int) (periods * period_size);
  232.   dev->buffer_byte_size = dev->buffer_size * 2 * 2; /* 2 channels * 16 bits audio */
  233.   if (!fluid_settings_dupstr(settings, "audio.oss.device", &devname) || !devname) {
  234.     devname = FLUID_STRDUP ("/dev/dsp");
  235.     if (!devname)
  236.     {
  237.       FLUID_LOG(FLUID_ERR, "Out of memory");
  238.       goto error_recovery;
  239.     }
  240.   }
  241.   if (stat(devname, &devstat) == -1) {
  242.     FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
  243.     goto error_recovery;
  244.   }
  245.   if ((devstat.st_mode & S_IFCHR) != S_IFCHR) {
  246.     FLUID_LOG(FLUID_ERR, "Device <%s> is not a device file", devname);
  247.     goto error_recovery;
  248.   }
  249.   dev->dspfd = open(devname, O_WRONLY, 0);
  250.   if (dev->dspfd == -1) {
  251.     FLUID_LOG(FLUID_ERR, "Device <%s> could not be opened for writing: %s",
  252.      devname, strerror(errno));
  253.     goto error_recovery;
  254.   }
  255.   if (fluid_oss_set_queue_size(dev, 16, 2, queuesize, period_size) < 0) {
  256.     FLUID_LOG(FLUID_ERR, "Can't set device buffer size");
  257.     goto error_recovery;
  258.   }
  259.   format = AFMT_S16_LE;
  260.   if (ioctl(dev->dspfd, SNDCTL_DSP_SETFMT, &format) < 0) {
  261.     FLUID_LOG(FLUID_ERR, "Can't set the sample format");
  262.     goto error_recovery;
  263.   }
  264.   if (format != AFMT_S16_LE) {
  265.     FLUID_LOG(FLUID_ERR, "Can't set the sample format");
  266.     goto error_recovery;
  267.   }
  268.   channels = 2;
  269.   if (ioctl(dev->dspfd, SOUND_PCM_WRITE_CHANNELS, &channels) < 0){
  270.     FLUID_LOG(FLUID_ERR, "Can't set the number of channels");
  271.     goto error_recovery;
  272.   }
  273.   if (channels != 2) {
  274.     FLUID_LOG(FLUID_ERR, "Can't set the number of channels");
  275.     goto error_recovery;
  276.   }
  277.   sr = sample_rate;
  278.   if (ioctl(dev->dspfd, SNDCTL_DSP_SPEED, &sr) < 0){
  279.     FLUID_LOG(FLUID_ERR, "Can't set the sample rate");
  280.     goto error_recovery;
  281.   }
  282.   if ((sr < 0.95 * sample_rate) ||
  283.       (sr > 1.05 * sample_rate)) {
  284.     FLUID_LOG(FLUID_ERR, "Can't set the sample rate");
  285.     goto error_recovery;
  286.   }
  287.   /* allocate the buffers. FIXME!!! don't use interleaved samples */
  288.   dev->buffer = FLUID_MALLOC(dev->buffer_byte_size);
  289.   dev->buffers[0] = FLUID_ARRAY(float, dev->buffer_size);
  290.   dev->buffers[1] = FLUID_ARRAY(float, dev->buffer_size);
  291.   if ((dev->buffer == NULL) || (dev->buffers[0] == NULL) || (dev->buffers[1] == NULL)) {
  292.     FLUID_LOG(FLUID_ERR, "Out of memory");
  293.     goto error_recovery;
  294.   }
  295.   /* Create the audio thread */
  296.   dev->thread = new_fluid_thread (fluid_oss_audio_run2, dev, realtime_prio, FALSE);
  297.   if (!dev->thread)
  298.     goto error_recovery;
  299.   if (devname) FLUID_FREE (devname);    /* -- free device name */
  300.   return (fluid_audio_driver_t*) dev;
  301. error_recovery:
  302.   if (devname) FLUID_FREE (devname);    /* -- free device name */
  303.   delete_fluid_oss_audio_driver((fluid_audio_driver_t*) dev);
  304.   return NULL;
  305. }
  306. /*
  307.  * delete_fluid_oss_audio_driver
  308.  */
  309. int
  310. delete_fluid_oss_audio_driver(fluid_audio_driver_t* p)
  311. {
  312.   fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) p;
  313.   if (dev == NULL) {
  314.     return FLUID_OK;
  315.   }
  316.   dev->cont = 0;
  317.   if (dev->thread)
  318.     fluid_thread_join (dev->thread);
  319.   if (dev->dspfd >= 0) {
  320.     close(dev->dspfd);
  321.   }
  322.   if (dev->buffer != NULL) {
  323.     FLUID_FREE(dev->buffer);
  324.   }
  325.   FLUID_FREE(dev);
  326.   return FLUID_OK;
  327. }
  328. /**
  329.  *  fluid_oss_set_queue_size
  330.  *
  331.  *  Set the internal buffersize of the output device.
  332.  *
  333.  *  @param ss Sample size in bits
  334.  *  @param ch Number of channels
  335.  *  @param qs The queue size in frames
  336.  *  @param bs The synthesis buffer size in frames
  337.  */
  338. int
  339. fluid_oss_set_queue_size(fluid_oss_audio_driver_t* dev, int ss, int ch, int qs, int bs)
  340. {
  341.   unsigned int fragmentSize;
  342.   unsigned int fragSizePower;
  343.   unsigned int fragments;
  344.   unsigned int fragmentsPower;
  345.   fragmentSize = (unsigned int) (bs * ch * ss / 8);
  346.   fragSizePower = 0;
  347.   while (0 < fragmentSize) {
  348.     fragmentSize = (fragmentSize >> 1);
  349.     fragSizePower++;
  350.   }
  351.   fragSizePower--;
  352.   fragments = (unsigned int) (qs / bs);
  353.   if (fragments < 2) {
  354.     fragments = 2;
  355.   }
  356.   /* make sure fragments is a power of 2 */
  357.   fragmentsPower = 0;
  358.   while (0 < fragments) {
  359.     fragments = (fragments >> 1);
  360.     fragmentsPower++;
  361.   }
  362.   fragmentsPower--;
  363.   fragments = (1 << fragmentsPower);
  364.   fragments = (fragments << 16) + fragSizePower;
  365.   return ioctl(dev->dspfd, SNDCTL_DSP_SETFRAGMENT, &fragments);
  366. }
  367. /*
  368.  * fluid_oss_audio_run
  369.  */
  370. void
  371. fluid_oss_audio_run(void* d)
  372. {
  373.   fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) d;
  374.   fluid_synth_t* synth = dev->synth;
  375.   void* buffer = dev->buffer;
  376.   int len = dev->buffer_size;
  377.   /* it's as simple as that: */
  378.   while (dev->cont)
  379.   {
  380.     dev->read (synth, len, buffer, 0, 2, buffer, 1, 2);
  381.     if (write (dev->dspfd, buffer, dev->buffer_byte_size) < 0)
  382.     {
  383.       FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s",
  384.                 g_strerror (errno));
  385.       break;
  386.     }
  387.   }
  388.   FLUID_LOG(FLUID_DBG, "Audio thread finished");
  389. }
  390. /*
  391.  * fluid_oss_audio_run
  392.  */
  393. void
  394. fluid_oss_audio_run2(void* d)
  395. {
  396.   fluid_oss_audio_driver_t* dev = (fluid_oss_audio_driver_t*) d;
  397.   short* buffer = (short*) dev->buffer;
  398.   float* left = dev->buffers[0];
  399.   float* right = dev->buffers[1];
  400.   int buffer_size = dev->buffer_size;
  401.   int dither_index = 0;
  402.   FLUID_LOG(FLUID_DBG, "Audio thread running");
  403.   /* it's as simple as that: */
  404.   while (dev->cont)
  405.   {
  406.     (*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->buffers);
  407.     fluid_synth_dither_s16 (&dither_index, buffer_size, left, right,
  408.     buffer, 0, 2, buffer, 1, 2);
  409.     if (write (dev->dspfd, buffer, dev->buffer_byte_size) < 0)
  410.     {
  411.       FLUID_LOG(FLUID_ERR, "Error writing to OSS sound device: %s",
  412.                 g_strerror (errno));
  413.       break;
  414.     }
  415.   }
  416.   FLUID_LOG(FLUID_DBG, "Audio thread finished");
  417. }
  418. void fluid_oss_midi_driver_settings(fluid_settings_t* settings)
  419. {
  420.   fluid_settings_register_str(settings, "midi.oss.device", "/dev/midi", 0, NULL, NULL);
  421. }
  422. /*
  423.  * new_fluid_oss_midi_driver
  424.  */
  425. fluid_midi_driver_t*
  426. new_fluid_oss_midi_driver(fluid_settings_t* settings,
  427.  handle_midi_event_func_t handler, void* data)
  428. {
  429.   fluid_oss_midi_driver_t* dev;
  430.   int realtime_prio = 0;
  431.   char* device = NULL;
  432.   /* not much use doing anything */
  433.   if (handler == NULL) {
  434.     FLUID_LOG(FLUID_ERR, "Invalid argument");
  435.     return NULL;
  436.   }
  437.   /* allocate the device */
  438.   dev = FLUID_NEW(fluid_oss_midi_driver_t);
  439.   if (dev == NULL) {
  440.     FLUID_LOG(FLUID_ERR, "Out of memory");
  441.     return NULL;
  442.   }
  443.   FLUID_MEMSET(dev, 0, sizeof(fluid_oss_midi_driver_t));
  444.   dev->fd = -1;
  445.   dev->driver.handler = handler;
  446.   dev->driver.data = data;
  447.   /* allocate one event to store the input data */
  448.   dev->parser = new_fluid_midi_parser();
  449.   if (dev->parser == NULL) {
  450.     FLUID_LOG(FLUID_ERR, "Out of memory");
  451.     goto error_recovery;
  452.   }
  453.   /* get the device name. if none is specified, use the default device. */
  454.   fluid_settings_dupstr(settings, "midi.oss.device", &device);  /* ++ alloc device name */
  455.   if (device == NULL) {
  456.     device = FLUID_STRDUP ("/dev/midi");
  457.     if (!device)
  458.     {
  459.       FLUID_LOG(FLUID_ERR, "Out of memory");
  460.       goto error_recovery;
  461.     }
  462.   }
  463.   fluid_settings_getint (settings, "midi.realtime-prio", &realtime_prio);
  464.   /* open the default hardware device. only use midi in. */
  465.   dev->fd = open(device, O_RDONLY, 0);
  466.   if (dev->fd < 0) {
  467.     perror(device);
  468.     goto error_recovery;
  469.   }
  470.   if (fcntl (dev->fd, F_SETFL, O_NONBLOCK) == -1)
  471.   {
  472.     FLUID_LOG(FLUID_ERR, "Failed to set OSS MIDI device to non-blocking: %s",
  473.               strerror (errno));
  474.     goto error_recovery;
  475.   }
  476.   dev->status = FLUID_MIDI_READY;
  477.   /* create MIDI thread */
  478.   dev->thread = new_fluid_thread (fluid_oss_midi_run, dev, realtime_prio, FALSE);
  479.   if (!dev->thread)
  480.     goto error_recovery;
  481.   if (device) FLUID_FREE (device);      /* ++ free device */
  482.   return (fluid_midi_driver_t*) dev;
  483.  error_recovery:
  484.   if (device) FLUID_FREE (device);      /* ++ free device */
  485.   delete_fluid_oss_midi_driver((fluid_midi_driver_t*) dev);
  486.   return NULL;
  487. }
  488. /*
  489.  * delete_fluid_oss_midi_driver
  490.  */
  491. int
  492. delete_fluid_oss_midi_driver(fluid_midi_driver_t* p)
  493. {
  494.   fluid_oss_midi_driver_t* dev;
  495.   dev = (fluid_oss_midi_driver_t*) p;
  496.   if (dev == NULL) {
  497.     return FLUID_OK;
  498.   }
  499.   /* cancel the thread and wait for it before cleaning up */
  500.   dev->status = FLUID_MIDI_DONE;
  501.   if (dev->thread)
  502.     fluid_thread_join (dev->thread);
  503.   if (dev->fd >= 0) {
  504.     close(dev->fd);
  505.   }
  506.   if (dev->parser != NULL) {
  507.     delete_fluid_midi_parser(dev->parser);
  508.   }
  509.   FLUID_FREE(dev);
  510.   return FLUID_OK;
  511. }
  512. /*
  513.  * fluid_oss_midi_run
  514.  */
  515. void
  516. fluid_oss_midi_run(void* d)
  517. {
  518.   fluid_oss_midi_driver_t* dev = (fluid_oss_midi_driver_t*) d;
  519.   fluid_midi_event_t* evt;
  520.   struct pollfd fds;
  521.   int n, i;
  522.   /* go into a loop until someone tells us to stop */
  523.   dev->status = FLUID_MIDI_LISTENING;
  524.   fds.fd = dev->fd;
  525.   fds.events = POLLIN;
  526.   fds.revents = 0;
  527.   while (dev->status == FLUID_MIDI_LISTENING) {
  528.     n = poll (&fds, 1, 100);
  529.     if (n == 0) continue;
  530.     if (n < 0)
  531.     {
  532.       FLUID_LOG(FLUID_ERR, "Error waiting for MIDI input: %s", strerror (errno));
  533.       break;
  534.     }
  535.     /* read new data */
  536.     n = read(dev->fd, dev->buffer, BUFFER_LENGTH);
  537.     if (n == -EAGAIN) continue;
  538.     if (n < 0) {
  539.       perror("read");
  540.       FLUID_LOG(FLUID_ERR, "Failed to read the midi input");
  541.       break;
  542.     }
  543.     /* let the parser convert the data into events */
  544.     for (i = 0; i < n; i++) {
  545.       evt = fluid_midi_parser_parse(dev->parser, dev->buffer[i]);
  546.       if (evt != NULL) {
  547. /* send the event to the next link in the chain */
  548. (*dev->driver.handler)(dev->driver.data, evt);
  549.       }
  550.     }
  551.   }
  552. }
  553. int
  554. fluid_oss_midi_driver_status(fluid_midi_driver_t* p)
  555. {
  556.   fluid_oss_midi_driver_t* dev = (fluid_oss_midi_driver_t*) p;
  557.   return dev->status;
  558. }
  559. #endif /*#if OSS_SUPPORT */