summaryrefslogtreecommitdiff
path: root/lib/libOSSlib
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libOSSlib')
-rw-r--r--lib/libOSSlib/.config2
-rw-r--r--lib/libOSSlib/.nativemake0
-rw-r--r--lib/libOSSlib/Makefile29
-rw-r--r--lib/libOSSlib/Readme120
-rw-r--r--lib/libOSSlib/compile.sh81
-rw-r--r--lib/libOSSlib/gmidi.h259
-rw-r--r--lib/libOSSlib/libmain.c200
-rw-r--r--lib/libOSSlib/midiparser.c401
-rw-r--r--lib/libOSSlib/midiparser.h1
-rw-r--r--lib/libOSSlib/play_event.c273
10 files changed, 1366 insertions, 0 deletions
diff --git a/lib/libOSSlib/.config b/lib/libOSSlib/.config
new file mode 100644
index 0000000..f34695c
--- /dev/null
+++ b/lib/libOSSlib/.config
@@ -0,0 +1,2 @@
+mode=shlib
+targetos=Linux
diff --git a/lib/libOSSlib/.nativemake b/lib/libOSSlib/.nativemake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libOSSlib/.nativemake
diff --git a/lib/libOSSlib/Makefile b/lib/libOSSlib/Makefile
new file mode 100644
index 0000000..98029f1
--- /dev/null
+++ b/lib/libOSSlib/Makefile
@@ -0,0 +1,29 @@
+OBJS=libmain.o midiparser.o play_event.o
+INSTALLLIB=/lib
+LDFLAGS=-shared -fPIC
+CFLAGS=-O -fPIC
+#LDFLAGS=-Bdynamic
+AROPTS=rc
+AR=ar
+
+all:
+ sh ./compile.sh $(INSTALLLIB) "$(CC)" "$(CFLAGS)" "$(MAKE)"
+
+install: all
+ cp libOSSlib.* $(INSTALLLIB)
+ cp drums.o3 std.o3 /etc
+
+static: libOSSlib.a
+ cp libOSSlib.a $(INSTALLLIB)
+
+libOSSlib.so: $(OBJS)
+ ${CC} $(LDFLAGS) -o libOSSlib.so $(OBJS)
+
+dep:
+
+clean:
+ rm -f *.o *.so x y z core *.a
+
+libOSSlib.a: $(OBJS)
+ $(AR) $(AROPTS) libOSSlib.a $(OBJS)
+ #-ranlib libOSSlib.a
diff --git a/lib/libOSSlib/Readme b/lib/libOSSlib/Readme
new file mode 100644
index 0000000..b975b78
--- /dev/null
+++ b/lib/libOSSlib/Readme
@@ -0,0 +1,120 @@
+About OSSlib
+============
+
+This version of OSSlib which supports patch caching for cards like GUS, OPL3
+and SoftOSS. This part of the library is only used by some older synthesizer
+chips that are no longer available. Also the SoftOSS virtual synth is
+compatible with it.
+
+Another part is the midiparser library. It's a simple callback based
+system that translates a stream of MIDI bytes (for example from MIDI
+keyboard) to events.
+
+This library is compatible with all OSS implementations including the freeware
+implementations.
+
+Copying conditions
+------------------
+
+This library can be freely used in ANY applications that is compatible
+with the OSS API. No parts of the code can be borroved to other purposes
+without written permission by 4Front Technologies.
+
+Installing OSSlib
+-----------------
+
+Execute make. If your operating system is recognized you will get
+libOSSlib.so or libOSSlib.a depending on operating system.
+If make complains about unknown operating system you should use
+make libOSSlib.so or make libOSSlib.a to build it.
+
+Finally copy libOSSlib.* to /usr/lib
+
+Using OSSlib in programs
+------------------------
+
+OSSlib is intended to be used in programs using /dev/music but
+it also works with /dev/sequencer too. This version of the library
+contains only some basic patch caching functions to be used with
+OPL3 and GUS (and SoftOSS as well). Support for other cards is still
+missing.
+
+There are steps to be done when using OSSlib in a program:
+
+1) Change Makefile to use -DOSSLIB and -lOSSlib
+
+Version 3.8 of <sys/soundcard.h> has been designed to be compatible
+with OSSlib when this OSSLIB is defined. You can also use
+#ifdef OSSLIB in programs to cover the minor differences between
+the OSSlib and non OSSlib versions.
+
+2) If the program defines segbuf_dump() routine, put it inside
+#ifndef OSSLIB/#endif pair. This routine is included in OSSlib
+and having the same routine inside the program conflicts with it.
+
+3) Add the following call to the program after /dev/music is opened.
+
+#ifdef OSSLIB
+ OSS_init(seqfd, 1024);
+#endif
+
+In the above seqfd is the file descriptor of /dev/music and 1024
+is the size of the local buffer used for output events (1024 is
+a good value).
+
+4) Add patch caching calls to the program. Patch caching should
+be called as early as possible. It's recommended to load all
+_required_ patches before starting the actual playback since
+loading large patches from disk may introduce significant delays
+to playback.
+
+There are two macros (in soundcard.h) to be used when loading
+instruments:
+
+SEQ_LOAD_GMINSTR(dev#, instr#) loads an instrument (melodic) patch.
+The first parameter is the synthesizer/device number (0 to N) and
+the second parameter is the General MIDI instrument number (0 to 127).
+Note that the numbering starts from #0 while many GM instrument
+tables start from #1.
+
+SEQ_LOAD_GMDRUM(dev#, drum#) is similar than the above but it loads
+an General MIDI percussive instrument.
+
+5) After the above steps your program is ready to start playing.
+
+Examples for using OSSlib and for playing MIDI data can be found
+in ../mplay/* and ../gustest/midithru.c
+
+GUS support in OSSlib
+---------------------
+
+You will need the full GM patch set distributed with the Ultrasound
+drivers for DOS. The default location where the library tries to
+find the patches is /dos/ultrasnd/midi but you can change it by
+editing guslib.c (the second line). Alternative patch sets
+(such as midia) are available from the net. Another source is the MIDIA
+library.
+
+Since non PnP GUS has only 1M of
+RAM (at most) it's not possible to load the full patch set. When playing
+lot of MIDI files in sequence it's possible that the menory becomes
+full if the program doesn't reset the samples between files.
+
+OPL3 support in OSSlib
+----------------------
+
+OSSlib supports patch loading to OPL3 FM synth cards (older OPL2 cards
+are not supported). The patch set is included in the std.o3 and drums.o3
+files distributed with this package. These files should be copied to /etc
+(will be done by "make install"). These patch files are the same ones
+included in Adagio/glib package by Greg Lee. They are also distributed
+with playmidi.
+
+Using OSSlib with SoftOSS
+-------------------------
+
+For instructions about using OSSLib with SoftOSS see the instructions
+for GUS (above).
+
+
+For more info about using OSSlib contact hannu@opensound.com
diff --git a/lib/libOSSlib/compile.sh b/lib/libOSSlib/compile.sh
new file mode 100644
index 0000000..0a03b1b
--- /dev/null
+++ b/lib/libOSSlib/compile.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+MAKE=$4
+
+case `uname` in
+
+"Linux")
+ $MAKE libOSSlib.so
+ ;;
+
+"FreeBSD")
+ $MAKE libOSSlib.so
+ ;;
+
+"OSF1")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"NetBSD")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"OpenBSD")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"BSD/OS")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"AIX")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"HP-UX")
+ $MAKE libOSSlib.a CC=$2 CFLAGS=$3
+ ;;
+
+"LynxOS")
+ $MAKE AROPTS=rcs libOSSlib.a CFLAGS=""
+ ;;
+
+"UNIX_SV")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"UnixWare")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"OpenUNIX")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"SCO_SV")
+ $MAKE libOSSlib.a INSTALLLIB="$1" CFLAGS=""
+ ;;
+
+"SunOS")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"PowerMAX_OS")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+"DragonFly")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+"BeOS"|"Haiku")
+ $MAKE libOSSlib.a CFLAGS=""
+ ;;
+
+*)
+ echo Can\'t recognize your operating system '('`uname`')'.
+ echo;echo
+ echo use $MAKE libOSSlib.so or $MAKE libOSSlib.a to build OSSlib
+ exit 0
+
+esac
+
+exit 0
diff --git a/lib/libOSSlib/gmidi.h b/lib/libOSSlib/gmidi.h
new file mode 100644
index 0000000..bc196a9
--- /dev/null
+++ b/lib/libOSSlib/gmidi.h
@@ -0,0 +1,259 @@
+char patch_names[][9] = {
+ /* 0 */ "acpiano",
+ /* 1 */ "britepno",
+ /* 2 */ "synpiano",
+ /* 3 */ "honky",
+ /* 4 */ "epiano1",
+ /* 5 */ "epiano2",
+ /* 6 */ "hrpschrd",
+ /* 7 */ "clavinet",
+ /* 8 */ "celeste",
+ /* 9 */ "glocken",
+ /* 10 */ "musicbox",
+ /* 11 */ "vibes",
+ /* 12 */ "marimba",
+ /* 13 */ "xylophon",
+ /* 14 */ "tubebell",
+ /* 15 */ "santur",
+ /* 16 */ "homeorg",
+ /* 17 */ "percorg",
+ /* 18 */ "rockorg",
+ /* 19 */ "church",
+ /* 20 */ "reedorg",
+ /* 21 */ "accordn",
+ /* 22 */ "harmonca",
+ /* 23 */ "concrtna",
+ /* 24 */ "nyguitar",
+ /* 25 */ "acguitar",
+ /* 26 */ "jazzgtr",
+ /* 27 */ "cleangtr",
+ /* 28 */ "mutegtr",
+ /* 29 */ "odguitar",
+ /* 30 */ "distgtr",
+ /* 31 */ "gtrharm",
+ /* 32 */ "acbass",
+ /* 33 */ "fngrbass",
+ /* 34 */ "pickbass",
+ /* 35 */ "fretless",
+ /* 36 */ "slapbas1",
+ /* 37 */ "slapbas2",
+ /* 38 */ "synbass1",
+ /* 39 */ "synbass2",
+ /* 40 */ "violin",
+ /* 41 */ "viola",
+ /* 42 */ "cello",
+ /* 43 */ "contraba",
+ /* 44 */ "marcato",
+ /* 45 */ "pizzcato",
+ /* 46 */ "harp",
+ /* 47 */ "timpani",
+ /* 48 */ "marcato",
+ /* 49 */ "slowstr",
+ /* 50 */ "synstr1",
+ /* 51 */ "synstr2",
+ /* 52 */ "choir",
+ /* 53 */ "doo",
+ /* 54 */ "voices",
+ /* 55 */ "orchhit",
+ /* 56 */ "trumpet",
+ /* 57 */ "trombone",
+ /* 58 */ "tuba",
+ /* 59 */ "mutetrum",
+ /* 60 */ "frenchrn",
+ /* 61 */ "hitbrass",
+ /* 62 */ "synbras1",
+ /* 63 */ "synbras2",
+ /* 64 */ "sprnosax",
+ /* 65 */ "altosax",
+ /* 66 */ "tenorsax",
+ /* 67 */ "barisax",
+ /* 68 */ "oboe",
+ /* 69 */ "englhorn",
+ /* 70 */ "bassoon",
+ /* 71 */ "clarinet",
+ /* 72 */ "piccolo",
+ /* 73 */ "flute",
+ /* 74 */ "recorder",
+ /* 75 */ "woodflut",
+ /* 76 */ "bottle",
+ /* 77 */ "shakazul",
+ /* 78 */ "whistle",
+ /* 79 */ "ocarina",
+ /* 80 */ "sqrwave",
+ /* 81 */ "sawwave",
+ /* 82 */ "calliope",
+ /* 83 */ "chiflead",
+ /* 84 */ "voxlead",
+ /* 85 */ "voxlead",
+ /* 86 */ "lead5th",
+ /* 87 */ "basslead",
+ /* 88 */ "fantasia",
+ /* 89 */ "warmpad",
+ /* 90 */ "polysyn",
+ /* 91 */ "ghostie",
+ /* 92 */ "bowglass",
+ /* 93 */ "metalpad",
+ /* 94 */ "halopad",
+ /* 95 */ "sweeper",
+ /* 96 */ "aurora",
+ /* 97 */ "soundtrk",
+ /* 98 */ "crystal",
+ /* 99 */ "atmosphr",
+ /* 100 */ "freshair",
+ /* 101 */ "unicorn",
+ /* 102 */ "sweeper",
+ /* 103 */ "startrak",
+ /* 104 */ "sitar",
+ /* 105 */ "banjo",
+ /* 106 */ "shamisen",
+ /* 107 */ "koto",
+ /* 108 */ "kalimba",
+ /* 109 */ "bagpipes",
+ /* 110 */ "fiddle",
+ /* 111 */ "shannai",
+ /* 112 */ "carillon",
+ /* 113 */ "agogo",
+ /* 114 */ "steeldrm",
+ /* 115 */ "woodblk",
+ /* 116 */ "taiko",
+ /* 117 */ "toms",
+ /* 118 */ "syntom",
+ /* 119 */ "revcym",
+ /* 120 */ "fx-fret",
+ /* 121 */ "fx-blow",
+ /* 122 */ "seashore",
+ /* 123 */ "jungle",
+ /* 124 */ "telephon",
+ /* 125 */ "helicptr",
+ /* 126 */ "applause",
+ /* 127 */ "pistol",
+
+ "", /* 128 = drum 0 */
+ "", /* 129 = drum 1 */
+ "", /* 130 = drum 2 */
+ "", /* 131 = drum 3 */
+ "", /* 132 = drum 4 */
+ "", /* 133 = drum 5 */
+ "", /* 134 = drum 6 */
+ "", /* 135 = drum 7 */
+ "", /* 136 = drum 8 */
+ "", /* 137 = drum 9 */
+ "", /* 138 = drum 10 */
+ "", /* 139 = drum 11 */
+ "", /* 140 = drum 12 */
+ "", /* 141 = drum 13 */
+ "", /* 142 = drum 14 */
+ "", /* 143 = drum 15 */
+ "", /* 144 = drum 16 */
+ "", /* 145 = drum 17 */
+ "", /* 146 = drum 18 */
+ "", /* 147 = drum 19 */
+ "", /* 148 = drum 20 */
+ "", /* 149 = drum 21 */
+ "", /* 150 = drum 22 */
+ "", /* 151 = drum 23 */
+ "", /* 152 = drum 24 */
+ "", /* 153 = drum 25 */
+ "", /* 154 = drum 26 */
+ "highq", /* 155 = drum 27 */
+ "slap", /* 156 = drum 28 */
+ "scratch1", /* 157 = drum 29 */
+ "scratch2", /* 158 = drum 30 */
+ "sticks", /* 159 = drum 31 */
+ "sqrclick", /* 160 = drum 32 */
+ "metclick", /* 161 = drum 33 */
+ "metbell", /* 162 = drum 34 */
+ "kick1", /* 163 = drum 35 */
+ "kick2", /* 164 = drum 36 */
+ "stickrim", /* 165 = drum 37 */
+ "snare1", /* 166 = drum 38 */
+ "claps", /* 167 = drum 39 */
+ "snare2", /* 168 = drum 40 */
+ "tomlo2", /* 169 = drum 41 */
+ "hihatcl", /* 170 = drum 42 */
+ "tomlo1", /* 171 = drum 43 */
+ "hihatpd", /* 172 = drum 44 */
+ "tommid2", /* 173 = drum 45 */
+ "hihatop", /* 174 = drum 46 */
+ "tommid1", /* 175 = drum 47 */
+ "tomhi2", /* 176 = drum 48 */
+ "cymcrsh1", /* 177 = drum 49 */
+ "tomhi1", /* 178 = drum 50 */
+ "cymride1", /* 179 = drum 51 */
+ "cymchina", /* 180 = drum 52 */
+ "cymbell", /* 181 = drum 53 */
+ "tamborin", /* 182 = drum 54 */
+ "cymsplsh", /* 183 = drum 55 */
+ "cowbell", /* 184 = drum 56 */
+ "cymcrsh2", /* 185 = drum 57 */
+ "vibslap", /* 186 = drum 58 */
+ "cymride2", /* 187 = drum 59 */
+ "bongohi", /* 188 = drum 60 */
+ "bongolo", /* 189 = drum 61 */
+ "congahi1", /* 190 = drum 62 */
+ "congahi2", /* 191 = drum 63 */
+ "congalo", /* 192 = drum 64 */
+ "timbaleh", /* 193 = drum 65 */
+ "timbalel", /* 194 = drum 66 */
+ "agogohi", /* 195 = drum 67 */
+ "agogolo", /* 196 = drum 68 */
+ "cabasa", /* 197 = drum 69 */
+ "maracas", /* 198 = drum 70 */
+ "whistle1", /* 199 = drum 71 */
+ "whistle2", /* 200 = drum 72 */
+ "guiro1", /* 201 = drum 73 */
+ "guiro2", /* 202 = drum 74 */
+ "clave", /* 203 = drum 75 */
+ "woodblk1", /* 204 = drum 76 */
+ "woodblk2", /* 205 = drum 77 */
+ "cuica1", /* 206 = drum 78 */
+ "cuica2", /* 207 = drum 79 */
+ "triangl1", /* 208 = drum 80 */
+ "triangl2", /* 209 = drum 81 */
+ "shaker", /* 210 = drum 82 */
+ "jingles", /* 211 = drum 83 */
+ "belltree", /* 212 = drum 84 */
+ "castinet", /* 213 = drum 85 */
+ "surdo1", /* 214 = drum 86 */
+ "surdo2", /* 215 = drum 87 */
+ "", /* 216 = drum 88 */
+ "", /* 217 = drum 89 */
+ "", /* 218 = drum 90 */
+ "", /* 219 = drum 91 */
+ "", /* 220 = drum 92 */
+ "", /* 221 = drum 93 */
+ "", /* 222 = drum 94 */
+ "", /* 223 = drum 95 */
+ "", /* 224 = drum 96 */
+ "", /* 225 = drum 97 */
+ "", /* 226 = drum 98 */
+ "", /* 227 = drum 99 */
+ "", /* 228 = drum 100 */
+ "", /* 229 = drum 101 */
+ "", /* 230 = drum 102 */
+ "", /* 231 = drum 103 */
+ "", /* 232 = drum 104 */
+ "", /* 233 = drum 105 */
+ "", /* 234 = drum 106 */
+ "", /* 235 = drum 107 */
+ "", /* 236 = drum 108 */
+ "", /* 237 = drum 109 */
+ "", /* 238 = drum 110 */
+ "", /* 239 = drum 111 */
+ "", /* 240 = drum 112 */
+ "", /* 241 = drum 113 */
+ "", /* 242 = drum 114 */
+ "", /* 243 = drum 115 */
+ "", /* 244 = drum 116 */
+ "", /* 245 = drum 117 */
+ "", /* 246 = drum 118 */
+ "", /* 247 = drum 119 */
+ "", /* 248 = drum 120 */
+ "", /* 249 = drum 121 */
+ "", /* 250 = drum 122 */
+ "", /* 251 = drum 123 */
+ "", /* 252 = drum 124 */
+ "", /* 253 = drum 125 */
+ "", /* 254 = drum 126 */
+ "" /* 255 = drum 127 */
+};
diff --git a/lib/libOSSlib/libmain.c b/lib/libOSSlib/libmain.c
new file mode 100644
index 0000000..d295874
--- /dev/null
+++ b/lib/libOSSlib/libmain.c
@@ -0,0 +1,200 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#define OSSLIB
+#include "../../include/soundcard.h"
+
+int __seqfd = -1;
+static int initialized = 0;
+
+extern void _dump_midi (void); /* From play_event.c */
+
+unsigned char *_seqbuf;
+int _seqbuflen = 0;
+int _seqbufptr = 0;
+
+int synth_types[64] = { 0 };
+
+#define ST_NONE 0
+#define ST_GUS 1
+#define ST_OPL 2
+
+int nrsynths = 0;
+
+extern void play_event (unsigned char *ev);
+
+void
+seqbuf_dump (void)
+{
+ int l = _seqbufptr;
+
+ unsigned char *ev = _seqbuf;
+
+ while (l >= 8)
+ {
+ play_event (ev);
+ l -= 8;
+ ev += 8;
+ }
+
+ _seqbufptr = 0;
+ _dump_midi ();
+}
+
+static int
+oss_init_lib (void)
+{
+ if (_seqbuflen < 32 || _seqbuflen > 2048)
+ _seqbuflen = 2048;
+
+ if ((_seqbuf = malloc (_seqbuflen)) == NULL)
+ return 3;
+
+ initialized = 1;
+ return 0; /* OK */
+}
+
+int
+OSS_init (int userfd, int buflen)
+{
+ if (_seqbuflen || _seqbuflen || __seqfd != -1 || initialized)
+ {
+ fprintf (stderr, "libOSS: OSS_init called too late\n");
+ return 1;
+ }
+
+ __seqfd = userfd;
+
+ if (buflen < 32 || buflen > 2048)
+ {
+ fprintf (stderr, "libOSS: OSS_init called with invalid buflen\n");
+ return 2;
+ }
+
+ _seqbuflen = buflen;
+
+ return oss_init_lib ();
+}
+
+static void
+sanity_check (int fd, unsigned char *buf, int buflen)
+{
+ if (__seqfd != fd)
+ if (__seqfd == -1)
+ __seqfd = fd;
+ else
+ {
+ fprintf (stderr, "OSSlib: seqfd is inconsistent\n");
+ }
+
+ if (buf != _seqbuf)
+ {
+ fprintf (stderr, "OSSlib: _seqbuf is inconsistent\n");
+ }
+
+ if (buflen != _seqbuflen)
+ {
+ fprintf (stderr, "OSSlib: _seqbuf is inconsistent\n");
+ }
+
+ if (!initialized)
+ if (oss_init_lib () != 0)
+ {
+ fprintf (stderr, "OSSlib: Library initialization failed\n");
+ exit (-1);
+ }
+}
+
+void
+OSS_seqbuf_dump (int fd, unsigned char *buf, int buflen)
+{
+ seqbuf_dump ();
+}
+
+void
+OSS_seq_advbuf (int len, int fd, unsigned char *buf, int buflen)
+{
+ sanity_check (fd, buf, buflen);
+ _seqbufptr += len;
+}
+
+void
+OSS_seq_needbuf (int len, int fd, unsigned char *buf, int buflen)
+{
+ sanity_check (fd, buf, buflen);
+
+ if ((_seqbufptr + len) > _seqbuflen)
+ {
+ seqbuf_dump ();
+ }
+}
+
+void
+OSS_patch_caching (int dev, int chn, int patch, int fd, unsigned char *buf,
+ int buflen)
+{
+}
+
+void
+OSS_drum_caching (int dev, int chn, int patch, int fd, unsigned char *buf,
+ int buflen)
+{
+}
+
+void
+OSS_write_patch (int fd, unsigned char *buf, int len)
+{
+ sanity_check (fd, _seqbuf, _seqbuflen);
+
+ if (write (fd, buf, len) == -1)
+ {
+ perror ("OSS_write_patch");
+ exit (-1);
+ }
+}
+
+int
+OSS_write_patch2 (int fd, unsigned char *buf, int len)
+{
+ sanity_check (fd, _seqbuf, _seqbuflen);
+
+ return write (fd, buf, len);
+}
+
+/*
+ * audio routines
+ */
+
+int
+osslib_open (const char *path, int flags, int dummy)
+{
+ return open (path, flags, dummy);
+}
+
+void
+osslib_close (int fd)
+{
+ close (fd);
+}
+
+int
+osslib_write (int fd, const void *buf, int count)
+{
+ return write (fd, buf, count);
+}
+
+int
+osslib_read (int fd, void *buf, int count)
+{
+ return read (fd, buf, count);
+}
+
+int
+osslib_ioctl (int fd, unsigned int request, void *arg)
+{
+ return ioctl (fd, request, arg);
+}
diff --git a/lib/libOSSlib/midiparser.c b/lib/libOSSlib/midiparser.c
new file mode 100644
index 0000000..742e8f5
--- /dev/null
+++ b/lib/libOSSlib/midiparser.c
@@ -0,0 +1,401 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../../include/soundcard.h"
+#include "midiparser.h"
+
+struct _mtc_state
+{
+ int prev_ix;
+ int state;
+ int offset;
+ oss_mtc_data_t mtc, mtc0;
+};
+
+typedef struct midi_input_info
+{ /* MIDI input scanner variables */
+#define MI_MAX 64
+ int m_busy;
+ unsigned char m_buf[MI_MAX];
+ unsigned char m_prev_status; /* For running status */
+ int m_ptr;
+#define MST_INIT 0
+#define MST_DATA 1
+#define MST_SYSEX 2
+ int m_state;
+ int m_left;
+ int m_f1_flag;
+} midi_input_info_t;
+
+struct midiparser_common
+{
+ midi_input_info_t inc;
+ midiparser_callback_t callback;
+ midiparser_mtc_callback_t mtc_callback;
+ void *client_context;
+ struct _mtc_state mtc_state;
+};
+
+#define DBG(x) {}
+
+#define CALLBACK(cat, msg, ch, p1, p2, p3) \
+ { \
+ unsigned char arr[3];arr[0]=p1;arr[1]=p2;arr[2]=p3; \
+ synth->callback(synth->client_context, cat, msg, ch, arr, 3); \
+ }
+#define CALLBACK_A(cat, msg, ch, parms, len) \
+ synth->callback(synth->client_context, cat, msg, ch, parms, len)
+
+void
+do_system_msg (midiparser_common_p synth, unsigned char *msg, int mlen)
+{
+ DBG (printf ("System msg %02x, %02x (%d)\n", msg[0], msg[1], mlen));
+ CALLBACK_A (CAT_REALTIME, *msg, 0, msg, mlen);
+ return;
+}
+
+static void
+do_sysex_msg (midiparser_common_p synth, unsigned char *msg, int mlen)
+{
+ CALLBACK_A (CAT_SYSEX, 0, 0, msg, mlen);
+ return;
+}
+
+static void
+do_realtime_msg (midiparser_common_p synth, unsigned char data)
+{
+}
+
+void
+do_midi_msg (midiparser_common_p synth, unsigned char *msg, int mlen)
+{
+ switch (msg[0] & 0xf0)
+ {
+ case 0x90:
+ if (msg[2] != 0)
+ {
+ CALLBACK (CAT_VOICE, 0x90, msg[0] & 0x0f, msg[1], msg[2], 0);
+ break;
+ }
+ msg[2] = 64;
+
+ case 0x80:
+ CALLBACK (CAT_VOICE, 0x80, msg[0] & 0x0f, msg[1], msg[2], 0);
+ break;
+
+ case 0xA0:
+ CALLBACK (CAT_VOICE, 0xA0, msg[0] & 0x0f, msg[1], msg[2], 0);
+ break;
+
+ case 0xB0:
+ CALLBACK (CAT_CHN, 0xB0, msg[0] & 0x0f, msg[1], msg[2], 0);
+ break;
+
+ case 0xC0:
+ CALLBACK (CAT_CHN, 0xC0, msg[0] & 0x0f, msg[1], 0, 0);
+ break;
+
+ case 0xD0:
+ CALLBACK (CAT_CHN, 0xD0, msg[0] & 0x0f, msg[1], 0, 0);
+ break;
+
+ case 0xE0:
+ CALLBACK (CAT_VOICE, 0xE0, msg[0] & 0x0f, msg[1], msg[2], 0);
+ break;
+
+ case 0xf0: /* System common messages */
+ do_system_msg (synth, msg, mlen);
+ break;
+
+ default:
+ ;
+ }
+}
+
+static void
+send_mtc (midiparser_common_p synth, struct _mtc_state *st)
+{
+ oss_mtc_data_t mtc;
+
+ memcpy (&mtc, &st->mtc, sizeof (mtc));
+
+ mtc.qframes += st->offset;
+ mtc.frames += mtc.qframes / 4;
+ mtc.qframes %= 4;
+
+ if (mtc.time_code_type == 0)
+ mtc.time_code_type = 30;
+ mtc.seconds += mtc.frames / mtc.time_code_type; /* TODO: Handle drop frames */
+ mtc.frames %= mtc.time_code_type;
+
+ mtc.minutes += mtc.seconds / 60;
+ mtc.seconds %= 60;
+
+ mtc.hours += mtc.minutes / 60;
+ mtc.minutes %= 60;
+
+#if 0
+ printf ("%2d:%02d:%02d %02d.%d %2dFPS\n",
+ mtc.hours, mtc.minutes,
+ mtc.seconds, mtc.frames, mtc.qframes, mtc.time_code_type);
+#endif
+
+ synth->mtc_callback (synth->client_context, &mtc);
+}
+
+void
+mtc_message (midiparser_common_p synth, struct _mtc_state *st,
+ unsigned char b)
+{
+ static char frame_types[4] = { 24, 25, 29, 30 };
+ int ix, data;
+ int previx;
+
+ ix = b >> 4;
+ data = b & 0x0f;
+
+ previx = (st->prev_ix + 1) % 8;
+
+ if (ix == previx)
+ st->mtc0.direction = st->mtc.direction = MTC_DIR_FORWARD;
+ else if (ix == st->prev_ix)
+ st->mtc0.direction = st->mtc.direction = MTC_DIR_STOPPED;
+ else
+ st->mtc0.direction = st->mtc.direction = MTC_DIR_BACKWARD;
+ st->prev_ix = ix;
+
+ if (st->state == 0)
+ {
+ if (ix != 0) /* Not the beginning of the sequence yet */
+ return;
+ st->state = 1;
+ st->offset = -1;
+ }
+
+ switch (ix)
+ {
+ case 0: /* Frame count LS nibble */
+ st->mtc0.qframes = 0;
+ st->mtc0.frames = data;
+ break;
+
+ case 1: /* Frame count MS nibble */
+ st->mtc0.frames |= data << 4;
+ break;
+
+ case 2: /* Seconds count LS nibble */
+ st->mtc0.seconds = data;
+ break;
+
+ case 3: /* Seconds count MS nibble */
+ st->mtc0.seconds |= data << 4;
+ break;
+
+ case 4: /* Minutes count LS nibble */
+ st->mtc0.minutes = data;
+ break;
+
+ case 5: /* Minutes count MS nibble */
+ st->mtc0.minutes |= data << 4;
+ break;
+
+ case 6: /* Hours count LS nibble */
+ st->mtc0.hours = data;
+ break;
+
+ case 7: /* Hours count MS nibble */
+ st->mtc0.hours |= data << 4;
+ st->mtc0.time_code_type = frame_types[(st->mtc0.hours >> 5) & 0x03];
+ st->mtc0.hours &= 0x1f;
+ memcpy (&st->mtc, &st->mtc0, sizeof (st->mtc));
+ break;
+ }
+
+ if (ix == 7)
+ st->offset = 7;
+ else
+ st->offset++;
+ send_mtc (synth, st);
+}
+
+static void
+handle_midi_input (midiparser_common_p synth, midi_input_info_t * inc,
+ unsigned char data)
+{
+ extern int seq_actsense_enable;
+ extern int seq_rt_enable;
+
+ static unsigned char len_tab[] = /* # of data bytes following a status
+ */
+ {
+ 2, /* 8x */
+ 2, /* 9x */
+ 2, /* Ax */
+ 2, /* Bx */
+ 1, /* Cx */
+ 1, /* Dx */
+ 2, /* Ex */
+ 0 /* Fx */
+ };
+ /* printf("%02x (%d) ", data, inc->m_state); */
+
+ if (data == 0xfe) /* Active sensing */
+ {
+ return;
+ }
+
+ if (data >= 0xf8) /* Real time message */
+ {
+ do_realtime_msg (synth, data);
+ CALLBACK (CAT_REALTIME, data, 0, 0, 0, 0);
+ return;
+ }
+
+ if (data == 0xf1) /* MTC quarter frame (1st byte) */
+ {
+ inc->m_f1_flag = 1;
+ return;
+ }
+
+ if (inc->m_f1_flag) /* MTC quarter frame (2nd byte) */
+ {
+ inc->m_f1_flag = 0;
+
+ if (synth->mtc_callback != NULL)
+ {
+ mtc_message (synth, &synth->mtc_state, data);
+ return;
+ }
+ CALLBACK (CAT_MTC, 0xf1, 0, data, 0, 0);
+ return;
+ }
+
+ switch (inc->m_state)
+ {
+ case MST_INIT:
+ if (data & 0x80) /* MIDI status byte */
+ {
+ if ((data & 0xf0) == 0xf0) /* Common message */
+ {
+ switch (data)
+ {
+ case 0xf0: /* Sysex */
+ inc->m_state = MST_SYSEX;
+ inc->m_ptr = 1;
+ inc->m_left = MI_MAX;
+ inc->m_buf[0] = data;
+ break; /* Sysex */
+
+ case 0xf1: /* MTC quarter frame */
+ case 0xf3: /* Song select */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = 1;
+ inc->m_buf[0] = data;
+ break;
+
+ case 0xf2: /* Song position pointer */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = 2;
+ inc->m_buf[0] = data;
+ break;
+
+ default: /* Other common messages */
+ inc->m_buf[0] = data;
+ inc->m_ptr = 1;
+ do_midi_msg (synth, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ inc->m_left = 0;
+ }
+ }
+ else
+ {
+ /* Channel messages */
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 1;
+ inc->m_left = len_tab[(data >> 4) - 8];
+ inc->m_buf[0] = inc->m_prev_status = data;
+ }
+ }
+ else /* Running status */ if (inc->m_prev_status & 0x80) /* Ignore if no previous status (yet) */
+ {
+ inc->m_state = MST_DATA;
+ inc->m_ptr = 2;
+ inc->m_left = len_tab[(inc->m_prev_status >> 4) - 8] - 1;
+ inc->m_buf[0] = inc->m_prev_status;
+ inc->m_buf[1] = data;
+ }
+ break; /* MST_INIT */
+
+ case MST_DATA:
+ inc->m_buf[inc->m_ptr++] = data;
+ if (--inc->m_left <= 0)
+ {
+ inc->m_state = MST_INIT;
+ do_midi_msg (synth, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ }
+ break; /* MST_DATA */
+
+ case MST_SYSEX:
+ inc->m_buf[inc->m_ptr++] = data;
+ if (data == 0xf7) /* Sysex end */
+ {
+ do_sysex_msg (synth, inc->m_buf, inc->m_ptr);
+ inc->m_state = MST_INIT;
+ inc->m_left = 0;
+ inc->m_ptr = 0;
+
+ }
+ else if (inc->m_ptr >= MI_MAX) /* Overflow protection */
+ {
+ do_sysex_msg (synth, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ }
+
+ break; /* MST_SYSEX */
+
+ default:
+ inc->m_state = MST_INIT;
+ }
+}
+
+midiparser_common_p
+midiparser_create (midiparser_callback_t callback, void *context)
+{
+ midiparser_common_p synth;
+
+ if ((synth = malloc (sizeof (*synth))) == NULL)
+ return NULL;
+
+ memset (synth, 0, sizeof (*synth));
+
+ synth->callback = callback;
+ synth->client_context = context;
+ synth->mtc_state.prev_ix = -1;
+
+ return synth;
+}
+
+void
+midiparser_mtc_callback (midiparser_common_p common,
+ midiparser_mtc_callback_t callback)
+{
+ common->mtc_callback = callback;
+}
+
+void
+midiparser_input (midiparser_common_p synth, unsigned char data)
+{
+ handle_midi_input (synth, &synth->inc, data);
+}
+
+void
+midiparser_input_buf (midiparser_common_p synth, unsigned char *data, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ handle_midi_input (synth, &synth->inc, data[i]);
+}
diff --git a/lib/libOSSlib/midiparser.h b/lib/libOSSlib/midiparser.h
new file mode 100644
index 0000000..20aac3a
--- /dev/null
+++ b/lib/libOSSlib/midiparser.h
@@ -0,0 +1 @@
+#include "../../kernel/framework/include/midiparser.h"
diff --git a/lib/libOSSlib/play_event.c b/lib/libOSSlib/play_event.c
new file mode 100644
index 0000000..62687ef
--- /dev/null
+++ b/lib/libOSSlib/play_event.c
@@ -0,0 +1,273 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include "../../include/soundcard.h"
+#include <sys/time.h>
+
+#undef DEBUG
+
+extern int __seqfd;
+
+static midi_packet_t midi_packet;
+
+static unsigned char *midibuf = &midi_packet.payload[0];
+static int mp = 0;
+
+oss_midi_time_t current_tick = 0;
+
+static int timer_started = 0;
+
+void
+OSS_set_timebase (int tb)
+{
+/* TODO? */
+}
+
+#if 1
+#define _write write
+#else
+static size_t
+_write (int fildes, void *b, size_t nbyte)
+{
+ midi_packet_header_t *hdr = b;
+ unsigned char *buf;
+ int l = nbyte;
+
+
+ buf = (unsigned char *) b + sizeof (*hdr);
+
+ if (hdr->magic == MIDI_HDR_MAGIC) /* Timed mode write */
+ {
+ l -= sizeof (*hdr);
+
+ switch (hdr->event_type)
+ {
+ case MIDI_EV_WRITE:
+ printf ("%9lu: MIDI_EV_WRITE: ", hdr->time);
+ break;
+ case MIDI_EV_TEMPO:
+ printf ("%9lu: MIDI_EV_TEMPO: ", hdr->time);
+ break;
+ case MIDI_EV_ECHO:
+ printf ("%9lu: MIDI_EV_ECHO: ", hdr->time);
+ break;
+ case MIDI_EV_START:
+ printf ("%9lu: MIDI_EV_START: ", hdr->time);
+ break;
+ case MIDI_EV_STOP:
+ printf ("%9lu: MIDI_EV_STOP: ", hdr->time);
+ break;
+ default:
+ printf ("%9lu: MIDI_EV_%d: ", hdr->time, hdr->event_type);
+ break;
+ }
+
+ if (hdr->options & MIDI_OPT_TIMED)
+ printf ("TIMED ");
+
+ if (l > 0)
+ {
+ int i;
+
+ printf ("%d bytes (", l);
+
+ for (i = 0; i < l; i++)
+ printf ("%02x ", buf[i]);
+ printf (")");
+ }
+
+ printf ("\n");
+ }
+
+ return write (fildes, b, nbyte);
+}
+#endif
+
+static void
+start_timer (void)
+{
+#ifndef DEBUG
+ midi_packet_header_t hdr;
+
+ hdr.magic = MIDI_HDR_MAGIC;
+ hdr.event_type = MIDI_EV_START;
+ hdr.options = MIDI_OPT_NONE;
+ hdr.time = 0;
+ hdr.parm = 0;
+ if (_write (__seqfd, &hdr, sizeof (hdr)) != sizeof (hdr))
+ {
+ perror ("Write start timer");
+ exit (-1);
+ }
+
+ timer_started = 1;
+ printf ("Timer started\n");
+#endif
+}
+
+void
+_dump_midi (void)
+{
+ if (mp > 0)
+ {
+ if (!timer_started)
+ start_timer ();
+ midi_packet.hdr.magic = MIDI_HDR_MAGIC;
+ midi_packet.hdr.options = MIDI_OPT_TIMED;
+ midi_packet.hdr.event_type = MIDI_EV_WRITE;
+ midi_packet.hdr.parm = 0;
+ midi_packet.hdr.time = current_tick;
+
+#ifdef DEBUG
+ if (write (1, &midi_packet.payload[0], mp) == -1)
+#else
+ if (_write (__seqfd, &midi_packet, sizeof (midi_packet_header_t) + mp)
+ == -1)
+#endif
+ {
+ perror ("MIDI write");
+ exit (-1);
+ }
+ mp = 0;
+ }
+}
+
+static void
+oss_do_timing (unsigned char *ev)
+{
+ unsigned int parm = *(unsigned int *) &ev[4];
+ midi_packet_header_t hdr;
+
+ oss_midi_time_t tick;
+
+ _dump_midi ();
+
+ switch (ev[1])
+ {
+ case TMR_TEMPO:
+#ifndef DEBUG
+ if (!timer_started)
+ start_timer ();
+ hdr.magic = MIDI_HDR_MAGIC;
+ hdr.event_type = MIDI_EV_TEMPO;
+ hdr.options = MIDI_OPT_TIMED;
+ hdr.time = current_tick;
+ hdr.parm = parm;
+ if (_write (__seqfd, &hdr, sizeof (hdr)) != sizeof (hdr))
+ {
+ perror ("Write tempo");
+ exit (-1);
+ }
+#endif
+ break;
+
+ case TMR_WAIT_REL:
+ tick = current_tick + parm;
+
+ current_tick = tick;
+ break;
+
+ case TMR_WAIT_ABS:
+ tick = parm;
+ current_tick = tick;
+ break;
+ }
+
+}
+
+static void
+out_midi3 (unsigned char a, unsigned char b, unsigned char c)
+{
+ if (mp > 950)
+ _dump_midi ();
+ midibuf[mp++] = a;
+ midibuf[mp++] = b;
+ midibuf[mp++] = c;
+/* printf("Out %02x %02x %02x\n", a, b, c); */
+}
+
+static void
+out_midi2 (unsigned char a, unsigned char b)
+{
+ if (mp > 950)
+ _dump_midi ();
+ midibuf[mp++] = a;
+ midibuf[mp++] = b;
+/* printf("Out %02x %02x\n", a, b); */
+}
+
+void
+play_event (unsigned char *ev)
+{
+ int i;
+
+ switch (ev[0])
+ {
+ case EV_TIMING:
+ oss_do_timing (ev);
+ return;
+ break;
+
+ case EV_SEQ_LOCAL:
+ break;
+
+ case EV_CHN_COMMON:
+ switch (ev[2])
+ {
+ case MIDI_PGM_CHANGE:
+ /* printf("PGM change %02x %d\n", ev[2]|ev[3], ev[4]); */
+ out_midi2 (ev[2] | ev[3], ev[4]);
+ break;
+
+ case MIDI_CHN_PRESSURE:
+ out_midi2 (ev[2] | ev[3], ev[4]);
+ break;
+
+ case MIDI_CTL_CHANGE:
+ out_midi3 (ev[2] | ev[3], ev[4], *(short *) &ev[6]);
+ break;
+
+ default:
+ out_midi3 (ev[2] | ev[3], ev[4], *(short *) &ev[6]);
+ }
+ return;
+ break;
+
+ case EV_CHN_VOICE:
+ out_midi3 (ev[2] | ev[3], ev[4], ev[5]);
+ return;
+ break;
+
+ case EV_SYSEX:
+ {
+ int i, l;
+ l = 8;
+ for (i = 2; i < 8; i++)
+ if (ev[i] == 0xff)
+ {
+ l = i;
+ break;
+ }
+ if (mp > 950)
+ _dump_midi ();
+ for (i = 2; i < l; i++)
+ midibuf[mp++] = ev[i];
+ }
+ return;
+ break;
+
+ case EV_SYSTEM:
+ printf ("EV_SYSTEM: ");
+ break;
+
+ default:
+ printf ("Unknown event %d: ", ev[0]);
+
+ }
+
+ for (i = 0; i < 8; i++)
+ printf ("%02x ", ev[i]);
+ printf ("\n");
+}