summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/midi/sequencer.c
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-01-01 17:36:26 +0000
committertanimura <tanimura@FreeBSD.org>2002-01-01 17:36:26 +0000
commita46d1d7f893729bbd95a207f15da7cf72690209c (patch)
tree2bf9e44e75f8effab6b654ff7122f77f882aeee0 /sys/dev/sound/midi/sequencer.c
parentcfe419eb213db0b2937a261122224454d75db7a4 (diff)
downloadFreeBSD-src-a46d1d7f893729bbd95a207f15da7cf72690209c.zip
FreeBSD-src-a46d1d7f893729bbd95a207f15da7cf72690209c.tar.gz
- Do not uiomove with a mutex locked.
- Move from msleep/wakeup to condvar. - Return either zero or a positive errno value from a function. Return additional result via references. - Unify the typedef of callback functions.
Diffstat (limited to 'sys/dev/sound/midi/sequencer.c')
-rw-r--r--sys/dev/sound/midi/sequencer.c130
1 files changed, 66 insertions, 64 deletions
diff --git a/sys/dev/sound/midi/sequencer.c b/sys/dev/sound/midi/sequencer.c
index ab35f81..3677c76 100644
--- a/sys/dev/sound/midi/sequencer.c
+++ b/sys/dev/sound/midi/sequencer.c
@@ -69,7 +69,7 @@ enum {
*/
static midi_intr_t seq_intr;
-static seq_callback_t seq_callback;
+static midi_callback_t seq_callback;
/* These are the entries to the sequencer driver. */
static d_open_t seq_open;
@@ -372,9 +372,10 @@ seq_close(dev_t i_dev, int flags, int mode, struct thread *td)
int
seq_read(dev_t i_dev, struct uio *buf, int flag)
{
- int unit, ret, len;
+ int unit, ret, len, lenr;
sc_p scp;
seqdev_info *sd;
+ u_char *uiobuf;
unit = MIDIUNIT(i_dev);
@@ -396,27 +397,34 @@ seq_read(dev_t i_dev, struct uio *buf, int flag)
return (EIO);
}
+ len = buf->uio_resid;
+ lenr = 0;
+
+ uiobuf = (u_char *)malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+ if (uiobuf == NULL)
+ return (ENOMEM);
+
mtx_lock(&sd->flagqueue_mtx);
/* Begin recording. */
if ((sd->flags & SEQ_F_READING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_RD);
- len = 0;
-
/* Have we got the data to read? */
if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_in.rl == 0)
ret = EAGAIN;
- else {
- len = buf->uio_resid;
- ret = midibuf_uioread(&sd->midi_dbuf_in, buf, len, &sd->flagqueue_mtx);
- if (ret < 0)
- ret = -ret;
- else
- ret = 0;
- }
+ else
+ ret = midibuf_seqread(&sd->midi_dbuf_in, uiobuf, len, &lenr,
+ sd->callback, sd, SEQ_CB_START | SEQ_CB_RD,
+ &sd->flagqueue_mtx);
+
mtx_unlock(&sd->flagqueue_mtx);
+ if (ret == 0 && lenr > 0)
+ ret = uiomove(uiobuf, lenr, buf);
+
+ free(uiobuf, M_DEVBUF);
+
return (ret);
}
@@ -965,10 +973,13 @@ seq_intr(void *p, mididev_info *md)
}
static int
-seq_callback(seqdev_info *sd, int reason)
+seq_callback(void *d, int reason)
{
int unit;
sc_p scp;
+ seqdev_info *sd;
+
+ sd = (seqdev_info *)d;
/*DEB(printf("seq_callback: reason 0x%x.\n", reason));*/
@@ -1020,7 +1031,7 @@ seq_callback(seqdev_info *sd, int reason)
static int
seq_queue(sc_p scp, u_char *note)
{
- int unit, err;
+ int unit, err, lenw;
seqdev_info *sd;
sd = scp->devinfo;
@@ -1030,10 +1041,8 @@ seq_queue(sc_p scp, u_char *note)
/*DEB(printf("seq%d: queueing.\n", unit));*/
- if ((sd->flags & SEQ_F_INSYNC) != 0) {
+ if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
- cv_signal(&sd->insync_cv);
- }
if (sd->midi_dbuf_out.fl < EV_SZ) {
/* We have no space. Start playing if not yet. */
@@ -1042,26 +1051,14 @@ seq_queue(sc_p scp, u_char *note)
if ((sd->flags & SEQ_F_NBIO) != 0 && sd->midi_dbuf_out.fl < EV_SZ)
/* We would block. */
return (EAGAIN);
- else {
- while (sd->midi_dbuf_out.fl < EV_SZ) {
- /* We have no space. Good night. */
- err = msleep(&sd->midi_dbuf_out.tsleep_out, &sd->flagqueue_mtx, PRIBIO | PCATCH, "seqque", 0);
- if (err == EINTR || err == ERESTART) {
- if (err == EINTR)
- sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
- return (err);
- }
- }
- }
}
- /* We now have enough space to write. */
- err = midibuf_seqwrite(&sd->midi_dbuf_out, note, EV_SZ, &sd->flagqueue_mtx);
+ /* Write to the queue. */
+ err = midibuf_seqwrite(&sd->midi_dbuf_out, note, EV_SZ, &lenw,
+ sd->callback, sd, SEQ_CB_START | SEQ_CB_WR,
+ &sd->flagqueue_mtx);
- if (err < 0)
- err = -err;
- else {
- err = 0;
+ if (err == 0) {
/* Start playing if we have some data in the queue. */
if (sd->midi_dbuf_out.rl >= EV_SZ && ((sd->flags & SEQ_F_WRITING) == 0))
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
@@ -1073,7 +1070,7 @@ seq_queue(sc_p scp, u_char *note)
static void
seq_startplay(sc_p scp)
{
- int unit;
+ int unit, lenr;
u_char event[EV_SZ];
seqdev_info *sd;
@@ -1082,19 +1079,28 @@ seq_startplay(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
+ sd->flags |= SEQ_F_WRITING;
+
/* Dequeue the events to play. */
while (sd->midi_dbuf_out.rl >= EV_SZ) {
- midibuf_seqread(&sd->midi_dbuf_out, event, EV_SZ, &sd->flagqueue_mtx);
+ midibuf_seqcopy(&sd->midi_dbuf_out, event, EV_SZ, &lenr,
+ NULL, NULL, 0,
+ &sd->flagqueue_mtx);
switch (seq_playevent(scp, event)) {
case TIMERARMED:
+ midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
+ NULL, NULL, 0,
+ &sd->flagqueue_mtx);
return;
case QUEUEFULL:
/* We cannot play any further. */
- midibuf_sequnread(&sd->midi_dbuf_out, event, EV_SZ, &sd->flagqueue_mtx);
return;
case MORE:
+ midibuf_seqdelete(&sd->midi_dbuf_out, EV_SZ, &lenr,
+ NULL, NULL, 0,
+ &sd->flagqueue_mtx);
break;
}
}
@@ -1106,7 +1112,7 @@ seq_startplay(sc_p scp)
static int
seq_playevent(sc_p scp, u_char *event)
{
- int unit, ret;
+ int unit, ret, lenw;
long *delay;
seqdev_info *sd;
mididev_info *md;
@@ -1182,14 +1188,12 @@ seq_playevent(sc_p scp, u_char *event)
break;
}
mtx_unlock(&sd->flagqueue_mtx);
- if (md->synth.writeraw(md, &event[1], sizeof(event[1]), 1) == EAGAIN) {
- mtx_lock(&sd->flagqueue_mtx);
+ if (md->synth.writeraw(md, &event[1], sizeof(event[1]), &lenw, 1) == EAGAIN)
/* The queue was full. Try again later. */
ret = QUEUEFULL;
- break;
- }
+ else
+ ret = MORE;
mtx_lock(&sd->flagqueue_mtx);
- ret = MORE;
break;
case SEQ_ECHO:
/* Echo this event back. */
@@ -1325,7 +1329,7 @@ seq_stoptimer(sc_p scp)
static void
seq_midiinput(sc_p scp, mididev_info *md)
{
- int unit, midiunit;
+ int unit, midiunit, lenr;
u_long tstamp;
u_char event[4];
seqdev_info *sd;
@@ -1342,7 +1346,7 @@ seq_midiinput(sc_p scp, mididev_info *md)
if ((md->flags & MIDI_F_READING) != 0 && md->intrarg == sd) {
/* Read the input data. */
- while (md->synth.readraw(md, &event[1], sizeof(event[1]), 1) == 0) {
+ while (md->synth.readraw(md, &event[1], sizeof(event[1]), &lenr, 1) == 0) {
tstamp = seq_gettime() - scp->seq_time;
if (tstamp != scp->prev_input_time) {
/* Insert a wait between events. */
@@ -1361,16 +1365,16 @@ seq_midiinput(sc_p scp, mididev_info *md)
static int
seq_copytoinput(sc_p scp, u_char *event, int len)
{
+ int ret, leni;
seqdev_info *sd;
sd = scp->devinfo;
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
- if (midibuf_input_intr(&sd->midi_dbuf_in, event, len) == -EAGAIN)
- return (EAGAIN);
+ ret = midibuf_input_intr(&sd->midi_dbuf_in, event, len, &leni);
- return (0);
+ return (ret);
}
static int
@@ -1482,7 +1486,7 @@ seq_chnvoice(sc_p scp, u_char *event)
#if notyet
if (voice == -1 && scp->seq_mode == SEQ_2 && md->synth.allocvoice)
/* This is an internal synthesizer. (FM, GUS, etc) */
- if ((voice = seq_allocvoice(scp, md, chn, note)) == -EAGAIN)
+ if ((voice = seq_allocvoice(scp, md, chn, note)) == EAGAIN)
return (QUEUEFULL);
#endif /* notyet */
if (voice == -1)
@@ -1572,9 +1576,9 @@ seq_allocvoice(sc_p scp, mididev_info *md, int chn, int note)
key = (chn << 8) | (note + 1);
mtx_unlock(&scp->devinfo->flagqueue_mtx);
- if ((voice = md->synth.allocvoice(md, chn, note, &md->synth.alloc)) == -EAGAIN) {
+ if ((voice = md->synth.allocvoice(md, chn, note, &md->synth.alloc)) == EAGAIN) {
mtx_lock(&scp->devinfo->flagqueue_mtx);
- return (-EAGAIN);
+ return (EAGAIN);
}
mtx_lock(&scp->devinfo->flagqueue_mtx);
@@ -1737,9 +1741,9 @@ seq_timing(sc_p scp, u_char *event)
#endif /* notyet */
switch (event[1]) {
case TMR_WAIT_REL:
+ parm += scp->prev_event_time;
+ /* FALLTHRU */
case TMR_WAIT_ABS:
- if (event[1] == TMR_WAIT_REL)
- parm += scp->prev_event_time;
if (parm > 0) {
sd->flags |= SEQ_F_WRITING;
if (seq_requesttimer(scp, parm))
@@ -1881,7 +1885,7 @@ seq_openmidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td)
TAILQ_INSERT_TAIL(&scp->midi_open, md, md_linkseq);
if (insync)
- cv_signal(&scp->devinfo->insync_cv);
+ cv_broadcast(&scp->devinfo->insync_cv);
return (0);
}
@@ -1916,7 +1920,7 @@ seq_closemidi(sc_p scp, mididev_info *md, int flags, int mode, struct thread *td
TAILQ_REMOVE(&scp->midi_open, md, md_linkseq);
if (insync)
- cv_signal(&scp->devinfo->insync_cv);
+ cv_broadcast(&scp->devinfo->insync_cv);
return (0);
}
@@ -1932,7 +1936,7 @@ seq_panic(sc_p scp)
static int
seq_reset(sc_p scp)
{
- int unit, chn;
+ int unit, chn, lenw;
seqdev_info *sd;
mididev_info *md;
u_char c[3];
@@ -1942,10 +1946,8 @@ seq_reset(sc_p scp)
mtx_assert(&sd->flagqueue_mtx, MA_OWNED);
- if ((sd->flags & SEQ_F_INSYNC) != 0) {
+ if ((sd->flags & SEQ_F_INSYNC) != 0)
cv_wait(&sd->insync_cv, &sd->flagqueue_mtx);
- cv_signal(&sd->insync_cv);
- }
/* Stop reading and writing. */
sd->callback(sd, SEQ_CB_ABORT | SEQ_CB_RD | SEQ_CB_WR);
@@ -1977,11 +1979,11 @@ seq_reset(sc_p scp)
c[0] = 0xb0 | (chn & 0x0f);
c[1] = (u_char)0x78; /* All sound off */
c[2] = (u_char)0;
- md->synth.writeraw(md, c, 3, 0);
+ md->synth.writeraw(md, c, 3, &lenw, 0);
c[1] = (u_char)0x7b; /* All note off */
- md->synth.writeraw(md, c, 3, 0);
+ md->synth.writeraw(md, c, 3, &lenw, 0);
c[1] = (u_char)0x79; /* Reset all controller */
- md->synth.writeraw(md, c, 3, 0);
+ md->synth.writeraw(md, c, 3, &lenw, 0);
}
}
seq_sync(scp);
@@ -2012,7 +2014,7 @@ seq_sync(sc_p scp)
if ((sd->flags & SEQ_F_WRITING) == 0)
sd->callback(sd, SEQ_CB_START | SEQ_CB_WR);
rl = sd->midi_dbuf_out.rl;
- i = msleep(&sd->midi_dbuf_out.tsleep_out, &sd->flagqueue_mtx, PRIBIO | PCATCH, "seqsnc", SEQ_SYNC_TIMEOUT * hz);
+ i = cv_timedwait_sig(&sd->midi_dbuf_out.cv_out, &sd->flagqueue_mtx, SEQ_SYNC_TIMEOUT * hz);
if (i == EINTR || i == ERESTART) {
if (i == EINTR)
sd->callback(sd, SEQ_CB_STOP | SEQ_CB_WR);
@@ -2048,7 +2050,7 @@ seq_sync(sc_p scp)
mtx_lock(&sd->flagqueue_mtx);
sd->flags &= ~SEQ_F_INSYNC;
- cv_signal(&sd->insync_cv);
+ cv_broadcast(&sd->insync_cv);
return (0);
}
OpenPOWER on IntegriCloud