⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequencer.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sound/sequencer.c *  * The sequencer personality manager. *  * Copyright by Hannu Savolainen 1993 *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. 2. * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *  */#define SEQUENCER_C#include "sound_config.h"#ifdef CONFIGURE_SOUNDCARD#ifndef EXCLUDE_SEQUENCERstatic int      sequencer_ok = 0;DEFINE_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);/* DEFINE_WAIT_QUEUE (midi_sleeper, midi_sleep_flag); */#define midi_sleeper seq_sleeper#define midi_sleep_flag seq_sleep_flagstatic int      midi_opened[MAX_MIDI_DEV] ={0};				/* 1 if the process has opened MIDI */static int      midi_written[MAX_MIDI_DEV] ={0};long            seq_time = 0;	/* Reference point for the timer */#include "tuning.h"#define EV_SZ	8#define IEV_SZ	4static unsigned char *queue = NULL;	/* SEQ_MAX_QUEUE * EV_SZ bytes */static unsigned char *iqueue = NULL;	/* SEQ_MAX_QUEUE * IEV_SZ bytes */static volatile int qhead = 0, qtail = 0, qlen = 0;static volatile int iqhead = 0, iqtail = 0, iqlen = 0;static volatile int seq_playing = 0;static int      sequencer_busy = 0;static int      output_treshold;static unsigned synth_open_mask;static int      seq_queue (unsigned char *note);static void     seq_startplay (void);static int      seq_sync (void);static void     seq_reset (void);static int      pmgr_present[MAX_SYNTH_DEV] ={0};#if MAX_SYNTH_DEV > 15#error Too many synthesizer devices#endifintsequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  int             c = count, p = 0;  dev = dev >> 4;  if (dev)			/* Patch manager device */    return pmgr_read (dev - 1, file, buf, count);  while (c > 3)    {      if (!iqlen)	{	  DO_SLEEP (midi_sleeper, midi_sleep_flag, 0);	  if (!iqlen)	    return count - c;	}      COPY_TO_USER (buf, p, &iqueue[iqhead * IEV_SZ], IEV_SZ);      p += 4;      c -= 4;      iqhead = (iqhead + 1) % SEQ_MAX_QUEUE;      iqlen--;    }  return count - c;}static voidsequencer_midi_output (int dev){  /* Currently NOP */}static voidcopy_to_input (unsigned char *event){  unsigned long   flags;  if (iqlen >= (SEQ_MAX_QUEUE - 1))    return;			/* Overflow */  memcpy (&iqueue[iqtail * IEV_SZ], event, IEV_SZ);  iqlen++;  iqtail = (iqtail + 1) % SEQ_MAX_QUEUE;  DISABLE_INTR (flags);  if (SOMEONE_WAITING (midi_sleeper, midi_sleep_flag))    {      WAKE_UP (midi_sleeper, midi_sleep_flag);    }  RESTORE_INTR (flags);}static voidsequencer_midi_input (int dev, unsigned char data){  int             tstamp;  unsigned char   event[4];  if (data == 0xfe)		/* Active sensing */    return;			/* Ignore */  tstamp = GET_TIME () - seq_time;	/* Time since open() */  tstamp = (tstamp << 8) | SEQ_WAIT;  copy_to_input ((unsigned char *) &tstamp);  event[0] = SEQ_MIDIPUTC;  event[1] = data;  event[2] = dev;  event[3] = 0;  copy_to_input (event);}intsequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count){  unsigned char   event[EV_SZ], ev_code;  int             p = 0, c, ev_size;  int             err;  int             mode = file->mode & O_ACCMODE;  dev = dev >> 4;  DEB (printk ("sequencer_write(dev=%d, count=%d)\n", dev, count));  if (mode == OPEN_READ)    return RET_ERROR (EIO);  if (dev)			/* Patch manager device */    return pmgr_write (dev - 1, file, buf, count);  c = count;  while (c >= 4)    {      COPY_FROM_USER (event, buf, p, 4);      ev_code = event[0];      if (ev_code == SEQ_FULLSIZE)	{	  int             err;	  dev = *(unsigned short *) &event[2];	  if (dev < 0 || dev >= num_synths)	    return RET_ERROR (ENXIO);	  if (!(synth_open_mask & (1 << dev)))	    return RET_ERROR (ENXIO);	  err = synth_devs[dev]->load_patch (dev, *(short *) &event[0], buf, p + 4, c, 0);	  if (err < 0)	    return err;	  return err;	}      if (ev_code == SEQ_EXTENDED || ev_code == SEQ_PRIVATE)	{	  ev_size = 8;	  if (c < ev_size)	    {	      if (!seq_playing)		seq_startplay ();	      return count - c;	    }	  COPY_FROM_USER (&event[4], buf, p + 4, 4);	}      else	ev_size = 4;      if (event[0] == SEQ_MIDIPUTC)	{	  if (!midi_opened[event[2]])	    {	      int             mode;	      int             dev = event[2];	      if (dev >= num_midis)		{		  printk ("Sequencer Error: Nonexistent MIDI device %d\n", dev);		  return RET_ERROR (ENXIO);		}	      mode = file->mode & O_ACCMODE;	      if ((err = midi_devs[dev]->open (dev, mode,			  sequencer_midi_input, sequencer_midi_output)) < 0)		{		  seq_reset ();		  printk ("Sequencer Error: Unable to open Midi #%d\n", dev);		  return err;		}	      midi_opened[dev] = 1;	    }	}      if (!seq_queue (event))	{	  if (!seq_playing)	    seq_startplay ();	  return count - c;	}      p += ev_size;      c -= ev_size;    }  if (!seq_playing)    seq_startplay ();  return count;}static intseq_queue (unsigned char *note){  /* Test if there is space in the queue */  if (qlen >= SEQ_MAX_QUEUE)    if (!seq_playing)      seq_startplay ();		/* Give chance to drain the queue */  if (qlen >= SEQ_MAX_QUEUE && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))    {      /* Sleep until there is enough space on the queue */      DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);    }  if (qlen >= SEQ_MAX_QUEUE)    return 0;			/* To be sure */  memcpy (&queue[qtail * EV_SZ], note, EV_SZ);  qtail = (qtail + 1) % SEQ_MAX_QUEUE;  qlen++;  return 1;}static intextended_event (unsigned char *q){  int             dev = q[2];  if (dev < 0 || dev >= num_synths)    return RET_ERROR (ENXIO);  if (!(synth_open_mask & (1 << dev)))    return RET_ERROR (ENXIO);  switch (q[1])    {    case SEQ_NOTEOFF:      synth_devs[dev]->kill_note (dev, q[3], q[5]);      break;    case SEQ_NOTEON:      if (q[4] > 127 && q[4] != 255)	return 0;      synth_devs[dev]->start_note (dev, q[3], q[4], q[5]);      break;    case SEQ_PGMCHANGE:      synth_devs[dev]->set_instr (dev, q[3], q[4]);      break;    case SEQ_AFTERTOUCH:      synth_devs[dev]->aftertouch (dev, q[3], q[4]);      break;    case SEQ_BALANCE:      synth_devs[dev]->panning (dev, q[3], (char) q[4]);      break;    case SEQ_CONTROLLER:      synth_devs[dev]->controller (dev, q[3], q[4], *(short *) &q[5]);      break;    default:      return RET_ERROR (EINVAL);    }  return 0;}static voidseq_startplay (void){  int             this_one;  unsigned long  *delay;  unsigned char  *q;  while (qlen > 0)    {      qhead = ((this_one = qhead) + 1) % SEQ_MAX_QUEUE;      qlen--;      q = &queue[this_one*EV_SZ];      switch (q[0])	{	case SEQ_NOTEOFF:	  if (synth_open_mask & (1 << 0))	    if (synth_devs[0])	      synth_devs[0]->kill_note (0, q[1], q[3]);	  break;	case SEQ_NOTEON:	  if (q[4] < 128 || q[4] == 255)	    if (synth_open_mask & (1 << 0))	      if (synth_devs[0])		synth_devs[0]->start_note (0, q[1], q[2], q[3]);	  break;	case SEQ_WAIT:	  delay = (unsigned long *) q;	/* Bytes 1 to 3 are containing the					 * delay in GET_TIME() */	  *delay = (*delay >> 8) & 0xffffff;	  if (*delay > 0)	    {	      long            time;	      seq_playing = 1;	      time = *delay;	      request_sound_timer (time);	      if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)		{		  unsigned long   flags;		  DISABLE_INTR (flags);		  if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))		    {		      WAKE_UP (seq_sleeper, seq_sleep_flag);		    }		  RESTORE_INTR (flags);		}	      return;		/* Stop here. Timer routine will continue				 * playing after the delay */	    }	  break;	case SEQ_PGMCHANGE:	  if (synth_open_mask & (1 << 0))	    if (synth_devs[0])	      synth_devs[0]->set_instr (0, q[1], q[2]);	  break;	case SEQ_SYNCTIMER:	/* Reset timer */	  seq_time = GET_TIME ();	  break;	case SEQ_MIDIPUTC:	/* Put a midi character */	  if (midi_opened[q[2]])	    {	      int             dev;	      dev = q[2];	      if (!midi_devs[dev]->putc (dev, q[1]))		{		  /*		   * Output FIFO is full. Wait one timer cycle and try again.		   */		  qlen++;		  qhead = this_one;	/* Restore queue */		  seq_playing = 1;		  request_sound_timer (-1);		  return;		}	      else		midi_written[dev] = 1;	    }	  break;	case SEQ_ECHO:	  copy_to_input (q);	/* Echo back to the process */	  break;	case SEQ_PRIVATE:	  if (q[1] < num_synths)	    synth_devs[q[1]]->hw_control (q[1], q);	  break;	case SEQ_EXTENDED:	  extended_event (q);	  break;	default:;	}    }  seq_playing = 0;  if ((SEQ_MAX_QUEUE - qlen) >= output_treshold)    {      unsigned long   flags;      DISABLE_INTR (flags);      if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))	{	  WAKE_UP (seq_sleeper, seq_sleep_flag);	}      RESTORE_INTR (flags);    }}intsequencer_open (int dev, struct fileinfo *file)  {    int             retval, mode, i;    dev = dev >> 4;    mode = file->mode & O_ACCMODE;    DEB (printk ("sequencer_open(dev=%d)\n", dev));    if (!sequencer_ok)      {	printk ("Soundcard: Sequencer not initialized\n");	return RET_ERROR (ENXIO);      }    if (dev)			/* Patch manager device */      {	int             err;	dev--;	if (pmgr_present[dev])	  return RET_ERROR (EBUSY);	if ((err = pmgr_open (dev)) < 0)	  return err;		/* Failed */	pmgr_present[dev] = 1;	return err;      }    if (sequencer_busy)      {	printk ("Sequencer busy\n");	return RET_ERROR (EBUSY);      }    if (!(num_synths + num_midis))      return RET_ERROR (ENXIO);    synth_open_mask = 0;    if (mode == OPEN_WRITE || mode == OPEN_READWRITE)      for (i = 0; i < num_synths; i++)	/* Open synth devices */	if (synth_devs[i]->open (i, mode) < 0)	  printk ("Sequencer: Warning! Cannot open synth device #%d\n", i);	else	  synth_open_mask |= (1 << i);    seq_time = GET_TIME ();    for (i = 0; i < num_midis; i++)      {	midi_opened[i] = 0;	midi_written[i] = 0;      }    if (mode == OPEN_READ || mode == OPEN_READWRITE)      {				/* Initialize midi input devices */	if (!num_midis)	  {	    printk ("Sequencer: No Midi devices. Input not possible\n");	    return RET_ERROR (ENXIO);	  }	for (i = 0; i < num_midis; i++)	  {	    if ((retval = midi_devs[i]->open (i, mode,			 sequencer_midi_input, sequencer_midi_output)) >= 0)	      midi_opened[i] = 1;	  }      }    sequencer_busy = 1;    RESET_WAIT_QUEUE (seq_sleeper, seq_sleep_flag);    RESET_WAIT_QUEUE (midi_sleeper, midi_sleep_flag);    output_treshold = SEQ_MAX_QUEUE / 2;    for (i = 0; i < num_synths; i++)      if (pmgr_present[i])	pmgr_inform (i, PM_E_OPENED, 0, 0, 0, 0);    return 0;  }voidseq_drain_midi_queues (void){  int             i, n;  /*   * Give the Midi drivers time to drain their output queues   */  n = 1;  while (!PROCESS_ABORTING (midi_sleeper, midi_sleep_flag) && n)    {      n = 0;      for (i = 0; i < num_midis; i++)	if (midi_opened[i] && midi_written[i])	  if (midi_devs[i]->buffer_status != NULL)	    if (midi_devs[i]->buffer_status (i))	      n++;      /*       * Let's have a delay       */      if (n)	{	  DO_SLEEP (seq_sleeper, seq_sleep_flag, HZ / 10);	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -