?? sequencer.c
字號:
void
sequencer_release (int dev, struct fileinfo *file)
{
int i;
int mode = file->mode & O_ACCMODE;
dev = dev >> 4;
DEB (printk ("sequencer_release(dev=%d)\n", dev));
if (dev) /* Patch manager device */
{
dev--;
pmgr_release (dev);
pmgr_present[dev] = 0;
return;
}
/*
* Wait until the queue is empty
*/
while (!PROCESS_ABORTING (seq_sleeper, seq_sleep_flag) && qlen)
{
seq_sync ();
}
if (mode != OPEN_READ)
seq_drain_midi_queues (); /* Ensure the output queues are empty */
seq_reset ();
if (mode != OPEN_READ)
seq_drain_midi_queues (); /* Flush the all notes off messages */
for (i = 0; i < num_midis; i++)
if (midi_opened[i])
midi_devs[i]->close (i);
if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
for (i = 0; i < num_synths; i++)
if (synth_open_mask & (1 << i)) /* Actually opened */
if (synth_devs[i])
synth_devs[i]->close (i);
for (i = 0; i < num_synths; i++)
if (pmgr_present[i])
pmgr_inform (i, PM_E_CLOSED, 0, 0, 0, 0);
sequencer_busy = 0;
}
static int
seq_sync (void)
{
if (qlen && !seq_playing && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_startplay ();
if (qlen && !SOMEONE_WAITING (seq_sleeper, seq_sleep_flag)) /* Queue not empty */
{
DO_SLEEP (seq_sleeper, seq_sleep_flag, 0);
}
return qlen;
}
static void
midi_outc (int dev, unsigned char data)
{
/*
* NOTE! Calls sleep(). Don't call this from interrupt.
*/
int n;
/* This routine sends one byte to the Midi channel. */
/* If the output Fifo is full, it waits until there */
/* is space in the queue */
n = 300; /* Timeout in jiffies */
while (n && !midi_devs[dev]->putc (dev, data))
{
DO_SLEEP (seq_sleeper, seq_sleep_flag, 4);
n--;
}
}
static void
seq_reset (void)
{
/*
* NOTE! Calls sleep(). Don't call this from interrupt.
*/
int i, chn;
sound_stop_timer ();
qlen = qhead = qtail = 0;
iqlen = iqhead = iqtail = 0;
for (i = 0; i < num_synths; i++)
if (synth_open_mask & (1 << i))
if (synth_devs[i])
synth_devs[i]->reset (i);
for (i = 0; i < num_midis; i++)
if (midi_written[i]) /* Midi used. Some notes may still be playing */
{
for (chn = 0; chn < 16; chn++)
{
midi_outc (i,
(unsigned char)(0xb0 + (chn & 0xff))); /* Channel msg */
midi_outc (i, 0x7b);/* All notes off */
midi_outc (i, 0); /* Dummy parameter */
}
midi_devs[i]->close (i);
midi_written[i] = 0;
midi_opened[i] = 0;
}
seq_playing = 0;
if (SOMEONE_WAITING (seq_sleeper, seq_sleep_flag))
printk ("Sequencer Warning: Unexpected sleeping process\n");
}
int
sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
{
int midi_dev, orig_dev;
int mode = file->mode & O_ACCMODE;
orig_dev = dev = dev >> 4;
switch (cmd)
{
case SNDCTL_SEQ_SYNC:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
if (mode == OPEN_READ)
return 0;
while (qlen && !PROCESS_ABORTING (seq_sleeper, seq_sleep_flag))
seq_sync ();
return 0;
break;
case SNDCTL_SEQ_RESET:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
seq_reset ();
return 0;
break;
case SNDCTL_SEQ_TESTMIDI:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
midi_dev = IOCTL_IN (arg);
if (midi_dev >= num_midis)
return RET_ERROR (ENXIO);
if (!midi_opened[midi_dev])
{
int err, mode;
mode = file->mode & O_ACCMODE;
if ((err = midi_devs[midi_dev]->open (midi_dev, mode,
sequencer_midi_input,
sequencer_midi_output)) < 0)
return err;
}
midi_opened[midi_dev] = 1;
return 0;
break;
case SNDCTL_SEQ_GETINCOUNT:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
if (mode == OPEN_WRITE)
return 0;
return IOCTL_OUT (arg, iqlen);
break;
case SNDCTL_SEQ_GETOUTCOUNT:
if (mode == OPEN_READ)
return 0;
return IOCTL_OUT (arg, SEQ_MAX_QUEUE - qlen);
break;
case SNDCTL_SEQ_CTRLRATE:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
/* If *arg == 0, just return the current rate */
return IOCTL_OUT (arg, HZ);
break;
case SNDCTL_SEQ_RESETSAMPLES:
dev = IOCTL_IN (arg);
if (dev < 0 || dev >= num_synths)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)) && !orig_dev)
return RET_ERROR (EBUSY);
if (!orig_dev && pmgr_present[dev])
pmgr_inform (dev, PM_E_PATCH_RESET, 0, 0, 0, 0);
return synth_devs[dev]->ioctl (dev, cmd, arg);
break;
case SNDCTL_SEQ_NRSYNTHS:
return IOCTL_OUT (arg, num_synths);
break;
case SNDCTL_SEQ_NRMIDIS:
return IOCTL_OUT (arg, num_midis);
break;
case SNDCTL_SYNTH_MEMAVL:
{
int dev = IOCTL_IN (arg);
if (dev < 0 || dev >= num_synths)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)) && !orig_dev)
return RET_ERROR (EBUSY);
return IOCTL_OUT (arg, synth_devs[dev]->ioctl (dev, cmd, arg));
}
break;
case SNDCTL_FM_4OP_ENABLE:
{
int dev = IOCTL_IN (arg);
if (dev < 0 || dev >= num_synths)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)))
return RET_ERROR (ENXIO);
synth_devs[dev]->ioctl (dev, cmd, arg);
return 0;
}
break;
case SNDCTL_SYNTH_INFO:
{
struct synth_info inf;
int dev;
IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
dev = inf.device;
if (dev < 0 || dev >= num_synths)
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << dev)) && !orig_dev)
return RET_ERROR (EBUSY);
return synth_devs[dev]->ioctl (dev, cmd, arg);
}
break;
case SNDCTL_MIDI_INFO:
{
struct midi_info inf;
int dev;
IOCTL_FROM_USER ((char *) &inf, (char *) arg, 0, sizeof (inf));
dev = inf.device;
if (dev < 0 || dev >= num_midis)
return RET_ERROR (ENXIO);
IOCTL_TO_USER ((char *) arg, 0, (char *) &(midi_devs[dev]->info), sizeof (inf));
return 0;
}
break;
case SNDCTL_PMGR_IFACE:
{
struct patmgr_info *inf;
int dev, err;
inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));
IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
dev = inf->device;
if (dev < 0 || dev >= num_synths)
{
KERNEL_FREE (inf);
return RET_ERROR (ENXIO);
}
if (!synth_devs[dev]->pmgr_interface)
{
KERNEL_FREE (inf);
return RET_ERROR (ENXIO);
}
if ((err = synth_devs[dev]->pmgr_interface (dev, inf)) == -1)
{
KERNEL_FREE (inf);
return err;
}
IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
KERNEL_FREE (inf);
return 0;
}
break;
case SNDCTL_PMGR_ACCESS:
{
struct patmgr_info *inf;
int dev, err;
inf = (struct patmgr_info *) KERNEL_MALLOC (sizeof (*inf));
IOCTL_FROM_USER ((char *) inf, (char *) arg, 0, sizeof (*inf));
dev = inf->device;
if (dev < 0 || dev >= num_synths)
{
KERNEL_FREE (inf);
return RET_ERROR (ENXIO);
}
if (!pmgr_present[dev])
{
KERNEL_FREE (inf);
return RET_ERROR (ESRCH);
}
if ((err = pmgr_access (dev, inf)) < 0)
{
KERNEL_FREE (inf);
return err;
}
IOCTL_TO_USER ((char *) arg, 0, (char *) inf, sizeof (*inf));
KERNEL_FREE (inf);
return 0;
}
break;
case SNDCTL_SEQ_TRESHOLD:
{
int tmp = IOCTL_IN (arg);
if (dev) /* Patch manager */
return RET_ERROR (EIO);
if (tmp < 1)
tmp = 1;
if (tmp >= SEQ_MAX_QUEUE)
tmp = SEQ_MAX_QUEUE - 1;
output_treshold = tmp;
return 0;
}
break;
default:
if (dev) /* Patch manager */
return RET_ERROR (EIO);
if (mode == OPEN_READ)
return RET_ERROR (EIO);
if (!synth_devs[0])
return RET_ERROR (ENXIO);
if (!(synth_open_mask & (1 << 0)))
return RET_ERROR (ENXIO);
return synth_devs[0]->ioctl (0, cmd, arg);
break;
}
return RET_ERROR (EINVAL);
}
#ifdef ALLOW_SELECT
int
sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
dev = dev >> 4;
switch (sel_type)
{
case SEL_IN:
if (!iqlen)
{
select_wait (&midi_sleeper, wait);
return 0;
}
return 1;
break;
case SEL_OUT:
if (qlen >= SEQ_MAX_QUEUE)
{
select_wait (&seq_sleeper, wait);
return 0;
}
return 1;
break;
case SEL_EX:
return 0;
}
return 0;
}
#endif
void
sequencer_timer (void)
{
seq_startplay ();
}
int
note_to_freq (int note_num)
{
/*
* This routine converts a midi note to a frequency (multiplied by 1000)
*/
int note, octave, note_freq;
int notes[] =
{
261632, 277189, 293671, 311132, 329632, 349232,
369998, 391998, 415306, 440000, 466162, 493880
}; /* Note freq*1000 for octave 5 */
#define BASE_OCTAVE 5
octave = note_num / 12;
note = note_num % 12;
note_freq = notes[note];
if (octave < BASE_OCTAVE)
note_freq >>= (BASE_OCTAVE - octave);
else if (octave > BASE_OCTAVE)
note_freq <<= (octave - BASE_OCTAVE);
/* note_freq >>= 1; */
return note_freq;
}
unsigned long
compute_finetune (unsigned long base_freq, int bend, int range)
{
unsigned long amount;
int negative, semitones, cents;
if (!bend)
return base_freq;
if (!range)
return base_freq;
if (!base_freq)
return base_freq;
if (range >= 8192)
range = 8191;
bend = bend * range / 8192;
if (!bend)
return base_freq;
negative = bend < 0 ? 1 : 0;
if (bend < 0)
bend *= -1;
if (bend > range)
bend = range;
if (bend > 2399)
bend = 2399;
semitones = bend / 100;
cents = bend % 100;
amount = semitone_tuning[semitones] * cent_tuning[cents] / 10000;
if (negative)
return (base_freq * 10000) / amount; /* Bend down */
else
return (base_freq * amount) / 10000; /* Bend up */
}
long
sequencer_init (long mem_start)
{
sequencer_ok = 1;
PERMANENT_MALLOC(unsigned char*, queue, SEQ_MAX_QUEUE*EV_SZ, mem_start);
PERMANENT_MALLOC(unsigned char*, iqueue, SEQ_MAX_QUEUE*IEV_SZ, mem_start);
return mem_start;
}
#else
/* Stub version */
int
sequencer_read (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
return RET_ERROR (EIO);
}
int
sequencer_write (int dev, struct fileinfo *file, snd_rw_buf * buf, int count)
{
return RET_ERROR (EIO);
}
int
sequencer_open (int dev, struct fileinfo *file)
{
return RET_ERROR (ENXIO);
}
void
sequencer_release (int dev, struct fileinfo *file)
{
}
int
sequencer_ioctl (int dev, struct fileinfo *file,
unsigned int cmd, unsigned int arg)
{
return RET_ERROR (EIO);
}
int
sequencer_lseek (int dev, struct fileinfo *file, off_t offset, int orig)
{
return RET_ERROR (EIO);
}
long
sequencer_init (long mem_start)
{
return mem_start;
}
int
sequencer_select (int dev, struct fileinfo *file, int sel_type, select_table * wait)
{
return RET_ERROR (EIO);
}
#endif
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -