The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/midi/midisynth.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright by Hannu Savolainen 1993
    3  *
    4  * Redistribution and use in source and binary forms, with or
    5  * without modification, are permitted provided that the following
    6  * conditions are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above
   10  *    copyright notice, this list of conditions and the following
   11  *    disclaimer in the documentation and/or other materials provided
   12  *    with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS
   15  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   17  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   18  * AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  * $FreeBSD: releng/5.2/sys/dev/sound/midi/midisynth.c 88869 2002-01-04 01:13:49Z tanimura $
   28  *
   29  */
   30 
   31 /*
   32  * This is the interface for a sequencer to interact a midi driver.
   33  * This interface translates the sequencer operations to the corresponding
   34  * midi messages, and vice versa.
   35  */
   36 
   37 #include <dev/sound/midi/midi.h>
   38 
   39 #define TYPEDRANGE(type, x, lower, upper) \
   40 { \
   41         type tl, tu; \
   42         tl = (lower); \
   43         tu = (upper); \
   44         if (x < tl) { \
   45                 x = tl; \
   46         } else if(x > tu) { \
   47                 x = tu; \
   48         } \
   49 }
   50 
   51 /*
   52  * These functions goes into midisynthdev_op_desc.
   53  */
   54 static mdsy_killnote_t synth_killnote;
   55 static mdsy_setinstr_t synth_setinstr;
   56 static mdsy_startnote_t synth_startnote;
   57 static mdsy_reset_t synth_reset;
   58 static mdsy_hwcontrol_t synth_hwcontrol;
   59 static mdsy_loadpatch_t synth_loadpatch;
   60 static mdsy_panning_t synth_panning;
   61 static mdsy_aftertouch_t synth_aftertouch;
   62 static mdsy_controller_t synth_controller;
   63 static mdsy_patchmgr_t synth_patchmgr;
   64 static mdsy_bender_t synth_bender;
   65 static mdsy_allocvoice_t synth_allocvoice;
   66 static mdsy_setupvoice_t synth_setupvoice;
   67 static mdsy_sendsysex_t synth_sendsysex;
   68 static mdsy_prefixcmd_t synth_prefixcmd;
   69 static mdsy_volumemethod_t synth_volumemethod;
   70 static mdsy_readraw_t synth_readraw;
   71 static mdsy_writeraw_t synth_writeraw;
   72 
   73 /*
   74  * This is the synthdev_info for a midi interface device.
   75  * You may have to replace a few of functions for an internal
   76  * synthesizer.
   77  */
   78 synthdev_info midisynth_op_desc = {
   79         synth_killnote,
   80         synth_setinstr,
   81         synth_startnote,
   82         synth_reset,
   83         synth_hwcontrol,
   84         synth_loadpatch,
   85         synth_panning,
   86         synth_aftertouch,
   87         synth_controller,
   88         synth_patchmgr,
   89         synth_bender,
   90         synth_allocvoice,
   91         synth_setupvoice,
   92         synth_sendsysex,
   93         synth_prefixcmd,
   94         synth_volumemethod,
   95         synth_readraw,
   96         synth_writeraw,
   97 };
   98 
   99 /* The following functions are local. */
  100 static int synth_leavesysex(mididev_info *md);
  101 
  102 /*
  103  * Here are the main functions to interact to the midi sequencer.
  104  * These are called from the sequencer functions in sequencer.c.
  105  */
  106 
  107 static int
  108 synth_killnote(mididev_info *md, int chn, int note, int vel)
  109 {
  110         int unit, lenw;
  111         synthdev_info *sd;
  112         u_char c[3];
  113 
  114         unit = md->unit;
  115         sd = &md->synth;
  116 
  117         if (note < 0 || note > 127 || chn < 0 || chn > 15)
  118                 return (EINVAL);
  119         TYPEDRANGE(int, vel, 0, 127);
  120         if (synth_leavesysex(md) == EAGAIN)
  121                 return (EAGAIN);
  122 
  123         if (vel == 64) {
  124                 c[0] = 0x90 | (chn & 0x0f); /* Note on. */
  125                 c[1] = (u_char)note;
  126                 c[2] = 0;
  127         } else {
  128                 c[0] = 0x80 | (chn & 0x0f); /* Note off. */
  129                 c[1] = (u_char)note;
  130                 c[2] = (u_char)vel;
  131         }
  132 
  133         if (synth_prefixcmd(md, c[0]))
  134                 return (0);
  135 
  136         return (md->synth.writeraw(md, c, 3, &lenw, 1));
  137 }
  138 
  139 static int
  140 synth_setinstr(mididev_info *md, int chn, int instr)
  141 {
  142         int unit, lenw;
  143         synthdev_info *sd;
  144         u_char c[2];
  145 
  146         unit = md->unit;
  147         sd = &md->synth;
  148 
  149         if (instr < 0 || instr > 127 || chn < 0 || chn > 15)
  150                 return (EINVAL);
  151 
  152         if (synth_leavesysex(md) == EAGAIN)
  153                 return (EAGAIN);
  154 
  155         c[0] = 0xc0 | (chn & 0x0f); /* Progamme change. */
  156         c[1] = (u_char)instr;
  157 
  158         return (md->synth.writeraw(md, c, 3, &lenw, 1));
  159 }
  160 
  161 static int
  162 synth_startnote(mididev_info *md, int chn, int note, int vel)
  163 {
  164         int unit, lenw;
  165         synthdev_info *sd;
  166         u_char c[3];
  167 
  168         unit = md->unit;
  169         sd = &md->synth;
  170 
  171         if (note < 0 || note > 127 || chn < 0 || chn > 15)
  172                 return (EINVAL);
  173         TYPEDRANGE(int, vel, 0, 127);
  174         if (synth_leavesysex(md) == EAGAIN)
  175                 return (EAGAIN);
  176 
  177         c[0] = 0x90 | (chn & 0x0f); /* Note on. */
  178         c[1] = (u_char)note;
  179         c[2] = (u_char)vel;
  180         if (synth_prefixcmd(md, c[0]))
  181                 return (0);
  182 
  183         return (md->synth.writeraw(md, c, 3, &lenw, 1));
  184 }
  185 
  186 static int
  187 synth_reset(mididev_info *md)
  188 {
  189         synth_leavesysex(md);
  190         return (0);
  191 }
  192 
  193 static int
  194 synth_hwcontrol(mididev_info *md, u_char *event)
  195 {
  196         /* NOP. */
  197         return (0);
  198 }
  199 
  200 static int
  201 synth_loadpatch(mididev_info *md, int format, struct uio *buf, int offs, int count, int pmgr_flag)
  202 {
  203         struct sysex_info sysex;
  204         synthdev_info *sd;
  205         int unit, i, eox_seen, first_byte, left, src_offs, hdr_size, lenw;
  206         u_char c[count];
  207 
  208         unit = md->unit;
  209         sd = &md->synth;
  210 
  211         eox_seen = 0;
  212         first_byte = 1;
  213         hdr_size = offsetof(struct sysex_info, data);
  214 
  215         if (synth_leavesysex(md) == EAGAIN)
  216                 return (EAGAIN);
  217 
  218         if (synth_prefixcmd(md, 0xf0))
  219                 return (0);
  220         if (format != SYSEX_PATCH) {
  221                 printf("synth_loadpatch: patch format 0x%x is invalid.\n", format);
  222                 return (EINVAL);
  223         }
  224         if (count < hdr_size) {
  225                 printf("synth_loadpatch: patch header is too short.\n");
  226                 return (EINVAL);
  227         }
  228         count -= hdr_size;
  229 
  230         /* Copy the patch data. */
  231         if (uiomove((caddr_t)&((char *)&sysex)[offs], hdr_size - offs, buf))
  232                 printf("synth_loadpatch: memory mangled?\n");
  233 
  234         if (count < sysex.len) {
  235                 sysex.len = (long)count;
  236                 printf("synth_loadpatch: sysex record of %d bytes is too long, adjusted to %d bytes.\n", (int)sysex.len, count);
  237         }
  238         left = sysex.len;
  239         src_offs = 0;
  240 
  241         for (i = 0 ; i < left ; i++) {
  242                 uiomove((caddr_t)&c[i], 1, buf);
  243                 eox_seen = i > 0 && (c[i] & 0x80) != 0;
  244                 if (eox_seen && c[i] != 0xf7)
  245                         c[i] = 0xf7;
  246                 if (i == 0 && c[i] != 0x80) {
  247                         printf("synth_loadpatch: sysex does not begin with the status.\n");
  248                         return (EINVAL);
  249                 }
  250                 if (!first_byte && (c[i] & 0x80) != 0) {
  251                         md->synth.writeraw(md, c, i + 1, &lenw, 0);
  252                         return (0);
  253                 }
  254                 first_byte = 0;
  255         }
  256 
  257         if (!eox_seen) {
  258                 c[0] = 0xf7;
  259                 md->synth.writeraw(md, c, 1, &lenw, 0);
  260         }
  261 
  262         return (0);
  263 }
  264 
  265 static int
  266 synth_panning(mididev_info *md, int chn, int pan)
  267 {
  268         /* NOP. */
  269         return (0);
  270 }
  271 
  272 static int
  273 synth_aftertouch(mididev_info *md, int chn, int press)
  274 {
  275         int unit, lenw;
  276         synthdev_info *sd;
  277         u_char c[2];
  278 
  279         unit = md->unit;
  280         sd = &md->synth;
  281 
  282         if (press < 0 || press > 127 || chn < 0 || chn > 15)
  283                 return (EINVAL);
  284         if (synth_leavesysex(md) == EAGAIN)
  285                 return (EAGAIN);
  286 
  287         c[0] = 0xd0 | (chn & 0x0f); /* Channel Pressure. */
  288         c[1] = (u_char)press;
  289         if (synth_prefixcmd(md, c[0]))
  290                 return (0);
  291 
  292         return (md->synth.writeraw(md, c, 2, &lenw, 1));
  293 }
  294 
  295 static int
  296 synth_controller(mididev_info *md, int chn, int ctrlnum, int val)
  297 {
  298         int unit, lenw;
  299         synthdev_info *sd;
  300         u_char c[3];
  301 
  302         unit = md->unit;
  303         sd = &md->synth;
  304 
  305         if (ctrlnum < 1 || ctrlnum > 127 || chn < 0 || chn > 15)
  306                 return (EINVAL);
  307         if (synth_leavesysex(md) == EAGAIN)
  308                 return (EAGAIN);
  309 
  310         c[0] = 0xb0 | (chn & 0x0f); /* Control Message. */
  311         c[1] = (u_char)ctrlnum;
  312         if (synth_prefixcmd(md, c[0]))
  313                 return (0);
  314 
  315         return (md->synth.writeraw(md, c, 3, &lenw, 1));
  316 }
  317 
  318 static int
  319 synth_patchmgr(mididev_info *md, struct patmgr_info *rec)
  320 {
  321         return (EINVAL);
  322 }
  323 
  324 static int
  325 synth_bender(mididev_info *md, int chn, int val)
  326 {
  327         int unit, lenw;
  328         synthdev_info *sd;
  329         u_char c[3];
  330 
  331         unit = md->unit;
  332         sd = &md->synth;
  333 
  334         if (val < 0 || val > 16383 || chn < 0 || chn > 15)
  335                 return (EINVAL);
  336         if (synth_leavesysex(md) == EAGAIN)
  337                 return (EAGAIN);
  338 
  339         c[0] = 0xe0 | (chn & 0x0f); /* Pitch bend. */
  340         c[1] = (u_char)val & 0x7f;
  341         c[2] = (u_char)(val >> 7) & 0x7f;
  342         if (synth_prefixcmd(md, c[0]))
  343                 return (0);
  344 
  345         return (md->synth.writeraw(md, c, 3, &lenw, 1));
  346 }
  347 
  348 static int
  349 synth_allocvoice(mididev_info *md, int chn, int note, struct voice_alloc_info *alloc)
  350 {
  351         /* NOP. */
  352         return (0);
  353 }
  354 
  355 static int
  356 synth_setupvoice(mididev_info *md, int voice, int chn)
  357 {
  358         /* NOP. */
  359         return (0);
  360 }
  361 
  362 static int
  363 synth_sendsysex(mididev_info *md, u_char *sysex, int len)
  364 {
  365         int unit, i, lenw;
  366         synthdev_info *sd;
  367         u_char c[len];
  368 
  369         unit = md->unit;
  370         sd = &md->synth;
  371 
  372         mtx_lock(&sd->status_mtx);
  373         for (i = 0 ; i < len ; i++) {
  374                 switch (sysex[i]) {
  375                 case 0xf0:
  376                         /* Sysex begins. */
  377                         if (synth_prefixcmd(md, 0xf0)) {
  378                                 mtx_unlock(&sd->status_mtx);
  379                                 return (0);
  380                         }
  381                         sd->sysex_state = 1;
  382                         break;
  383                 case 0xf7:
  384                         /* Sysex ends. */
  385                         if (!sd->sysex_state) {
  386                                 mtx_unlock(&sd->status_mtx);
  387                                 return (0);
  388                         }
  389                         sd->sysex_state = 0;
  390                         break;
  391                 default:
  392                         if (!sd->sysex_state) {
  393                                 mtx_unlock(&sd->status_mtx);
  394                                 return (0);
  395                         }
  396                         if ((sysex[i] & 0x80) != 0) {
  397                                 /* A status in a sysex? */
  398                                 sysex[i] = 0xf7;
  399                                 sd->sysex_state = 0;
  400                         }
  401                         break;
  402                 }
  403                 c[i] = sysex[i];
  404                 if (!sd->sysex_state)
  405                         break;
  406         }
  407         mtx_unlock(&sd->status_mtx);
  408 
  409         return (md->synth.writeraw(md, c, i, &lenw, 1));
  410 }
  411 
  412 static int
  413 synth_prefixcmd(mididev_info *md, int status)
  414 {
  415         /* NOP. */
  416         return (0);
  417 }
  418 
  419 static int
  420 synth_volumemethod(mididev_info *md, int mode)
  421 {
  422         /* NOP. */
  423         return (0);
  424 }
  425 
  426 static int
  427 synth_readraw(mididev_info *md, u_char *buf, int len, int *lenr, int nonblock)
  428 {
  429         int unit, ret;
  430 
  431         if (md == NULL)
  432                 return (ENXIO);
  433         if (lenr == NULL)
  434                 return (EINVAL);
  435 
  436         *lenr = 0;
  437         unit = md->unit;
  438 
  439         if ((md->fflags & FREAD) == 0) {
  440                 MIDI_DEBUG(printf("synth_readraw: unit %d is not for reading.\n", unit));
  441                 return (EIO);
  442         }
  443 
  444         mtx_lock(&md->flagqueue_mtx);
  445 
  446         /* Begin recording. */
  447         if ((md->flags & MIDI_F_READING) == 0)
  448                 md->callback(md, MIDI_CB_START | MIDI_CB_RD);
  449 
  450         if (nonblock) {
  451                 /* Have we got enough data to read? */
  452                 if (md->midi_dbuf_in.rl < len) {
  453                         mtx_unlock(&md->flagqueue_mtx);
  454                         return (EAGAIN);
  455                 }
  456         }
  457 
  458         ret = midibuf_seqread(&md->midi_dbuf_in, buf, len, lenr,
  459                               md->callback, md, MIDI_CB_START | MIDI_CB_RD,
  460                               &md->flagqueue_mtx);
  461 
  462         mtx_unlock(&md->flagqueue_mtx);
  463 
  464         return (ret);
  465 }
  466 
  467 static int
  468 synth_writeraw(mididev_info *md, u_char *buf, int len, int *lenw, int nonblock)
  469 {
  470         int unit, ret;
  471 
  472         if (md == NULL)
  473                 return (ENXIO);
  474         if (lenw == NULL)
  475                 return (EINVAL);
  476 
  477         *lenw = 0;
  478         unit = md->unit;
  479 
  480         if ((md->fflags & FWRITE) == 0) {
  481                 MIDI_DEBUG(printf("synth_writeraw: unit %d is not for writing.\n", unit));
  482                 return (EIO);
  483         }
  484 
  485         /* For nonblocking, have we got enough space to write? */
  486         mtx_lock(&md->flagqueue_mtx);
  487         if (nonblock && md->midi_dbuf_out.fl < len) {
  488                 /* Begin playing. */
  489                 md->callback(md, MIDI_CB_START | MIDI_CB_WR);
  490                 mtx_unlock(&md->flagqueue_mtx);
  491                 return (EAGAIN);
  492         }
  493 
  494         ret = midibuf_seqwrite(&md->midi_dbuf_out, buf, len, lenw,
  495                                md->callback, md, MIDI_CB_START | MIDI_CB_WR,
  496                                &md->flagqueue_mtx);
  497 
  498         if (ret == 0)
  499                 /* Begin playing. */
  500                 md->callback(md, MIDI_CB_START | MIDI_CB_WR);
  501 
  502         mtx_unlock(&md->flagqueue_mtx);
  503 
  504         return (ret);
  505 }
  506 
  507 /*
  508  * The functions below here are the libraries for the above ones.
  509  */
  510 
  511 static int
  512 synth_leavesysex(mididev_info *md)
  513 {
  514         int unit, lenw;
  515         synthdev_info *sd;
  516         u_char c;
  517 
  518         unit = md->unit;
  519         sd = &md->synth;
  520 
  521         mtx_lock(&sd->status_mtx);
  522         if (!sd->sysex_state) {
  523                 mtx_unlock(&sd->status_mtx);
  524                 return (0);
  525         }
  526 
  527         sd->sysex_state = 0;
  528         mtx_unlock(&sd->status_mtx);
  529         c = 0xf7;
  530 
  531         return (md->synth.writeraw(md, &c, sizeof(c), &lenw, 1));
  532 }

Cache object: 72258b0686981032ad34d92b6b8e3d54


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.