123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- ===============================
- OSS Sequencer Emulation on ALSA
- ===============================
- Copyright (c) 1998,1999 by Takashi Iwai
- ver.0.1.8; Nov. 16, 1999
- Description
- ===========
- This directory contains the OSS sequencer emulation driver on ALSA. Note
- that this program is still in the development state.
- What this does - it provides the emulation of the OSS sequencer, access
- via ``/dev/sequencer`` and ``/dev/music`` devices.
- The most of applications using OSS can run if the appropriate ALSA
- sequencer is prepared.
- The following features are emulated by this driver:
- * Normal sequencer and MIDI events:
- They are converted to the ALSA sequencer events, and sent to the
- corresponding port.
- * Timer events:
- The timer is not selectable by ioctl. The control rate is fixed to
- 100 regardless of HZ. That is, even on Alpha system, a tick is always
- 1/100 second. The base rate and tempo can be changed in ``/dev/music``.
- * Patch loading:
- It purely depends on the synth drivers whether it's supported since
- the patch loading is realized by callback to the synth driver.
- * I/O controls:
- Most of controls are accepted. Some controls
- are dependent on the synth driver, as well as even on original OSS.
- Furthermore, you can find the following advanced features:
- * Better queue mechanism:
- The events are queued before processing them.
- * Multiple applications:
- You can run two or more applications simultaneously (even for OSS
- sequencer)!
- However, each MIDI device is exclusive - that is, if a MIDI device
- is opened once by some application, other applications can't use
- it. No such a restriction in synth devices.
- * Real-time event processing:
- The events can be processed in real time without using out of bound
- ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
- events will be processed in real-time without queued. To switch off the
- real-time mode, send RELTIME 0 event.
- * ``/proc`` interface:
- The status of applications and devices can be shown via
- ``/proc/asound/seq/oss`` at any time. In the later version,
- configuration will be changed via ``/proc`` interface, too.
- Installation
- ============
- Run configure script with both sequencer support (``--with-sequencer=yes``)
- and OSS emulation (``--with-oss=yes``) options. A module ``snd-seq-oss.o``
- will be created. If the synth module of your sound card supports for OSS
- emulation (so far, only Emu8000 driver), this module will be loaded
- automatically.
- Otherwise, you need to load this module manually.
- At beginning, this module probes all the MIDI ports which have been
- already connected to the sequencer. Once after that, the creation and deletion
- of ports are watched by announcement mechanism of ALSA sequencer.
- The available synth and MIDI devices can be found in proc interface.
- Run ``cat /proc/asound/seq/oss``, and check the devices. For example,
- if you use an AWE64 card, you'll see like the following:
- ::
- OSS sequencer emulation version 0.1.8
- ALSA client number 63
- ALSA receiver port 0
- Number of applications: 0
- Number of synth devices: 1
- synth 0: [EMU8000]
- type 0x1 : subtype 0x20 : voices 32
- capabilties : ioctl enabled / load_patch enabled
- Number of MIDI devices: 3
- midi 0: [Emu8000 Port-0] ALSA port 65:0
- capability write / opened none
- midi 1: [Emu8000 Port-1] ALSA port 65:1
- capability write / opened none
- midi 2: [0: MPU-401 (UART)] ALSA port 64:0
- capability read/write / opened none
- Note that the device number may be different from the information of
- ``/proc/asound/oss-devices`` or ones of the original OSS driver.
- Use the device number listed in ``/proc/asound/seq/oss``
- to play via OSS sequencer emulation.
- Using Synthesizer Devices
- =========================
- Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
- and xmp-1.1.5. You can load samples via ``/dev/sequencer`` like sfxload,
- too.
- If the lowlevel driver supports multiple access to synth devices (like
- Emu8000 driver), two or more applications are allowed to run at the same
- time.
- Using MIDI Devices
- ==================
- So far, only MIDI output was tested. MIDI input was not checked at all,
- but hopefully it will work. Use the device number listed in
- ``/proc/asound/seq/oss``.
- Be aware that these numbers are mostly different from the list in
- ``/proc/asound/oss-devices``.
- Module Options
- ==============
- The following module options are available:
- maxqlen
- specifies the maximum read/write queue length. This queue is private
- for OSS sequencer, so that it is independent from the queue length of ALSA
- sequencer. Default value is 1024.
- seq_oss_debug
- specifies the debug level and accepts zero (= no debug message) or
- positive integer. Default value is 0.
- Queue Mechanism
- ===============
- OSS sequencer emulation uses an ALSA priority queue. The
- events from ``/dev/sequencer`` are processed and put onto the queue
- specified by module option.
- All the events from ``/dev/sequencer`` are parsed at beginning.
- The timing events are also parsed at this moment, so that the events may
- be processed in real-time. Sending an event ABSTIME 0 switches the operation
- mode to real-time mode, and sending an event RELTIME 0 switches it off.
- In the real-time mode, all events are dispatched immediately.
- The queued events are dispatched to the corresponding ALSA sequencer
- ports after scheduled time by ALSA sequencer dispatcher.
- If the write-queue is full, the application sleeps until a certain amount
- (as default one half) becomes empty in blocking mode. The synchronization
- to write timing was implemented, too.
- The input from MIDI devices or echo-back events are stored on read FIFO
- queue. If application reads ``/dev/sequencer`` in blocking mode, the
- process will be awaked.
- Interface to Synthesizer Device
- ===============================
- Registration
- ------------
- To register an OSS synthesizer device, use snd_seq_oss_synth_register()
- function:
- ::
- int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
- snd_seq_oss_callback_t *oper, void *private_data)
- The arguments ``name``, ``type``, ``subtype`` and ``nvoices``
- are used for making the appropriate synth_info structure for ioctl. The
- return value is an index number of this device. This index must be remembered
- for unregister. If registration is failed, -errno will be returned.
- To release this device, call snd_seq_oss_synth_unregister() function:
- ::
- int snd_seq_oss_synth_unregister(int index)
- where the ``index`` is the index number returned by register function.
- Callbacks
- ---------
- OSS synthesizer devices have capability for sample downloading and ioctls
- like sample reset. In OSS emulation, these special features are realized
- by using callbacks. The registration argument oper is used to specify these
- callbacks. The following callback functions must be defined:
- ::
- snd_seq_oss_callback_t:
- int (*open)(snd_seq_oss_arg_t *p, void *closure);
- int (*close)(snd_seq_oss_arg_t *p);
- int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
- int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
- int (*reset)(snd_seq_oss_arg_t *p);
- Except for ``open`` and ``close`` callbacks, they are allowed to be NULL.
- Each callback function takes the argument type ``snd_seq_oss_arg_t`` as the
- first argument.
- ::
- struct snd_seq_oss_arg_t {
- int app_index;
- int file_mode;
- int seq_mode;
- snd_seq_addr_t addr;
- void *private_data;
- int event_passing;
- };
- The first three fields, ``app_index``, ``file_mode`` and ``seq_mode``
- are initialized by OSS sequencer. The ``app_index`` is the application
- index which is unique to each application opening OSS sequencer. The
- ``file_mode`` is bit-flags indicating the file operation mode. See
- ``seq_oss.h`` for its meaning. The ``seq_mode`` is sequencer operation
- mode. In the current version, only ``SND_OSSSEQ_MODE_SYNTH`` is used.
- The next two fields, ``addr`` and ``private_data``, must be
- filled by the synth driver at open callback. The ``addr`` contains
- the address of ALSA sequencer port which is assigned to this device. If
- the driver allocates memory for ``private_data``, it must be released
- in close callback by itself.
- The last field, ``event_passing``, indicates how to translate note-on
- / off events. In ``PROCESS_EVENTS`` mode, the note 255 is regarded
- as velocity change, and key pressure event is passed to the port. In
- ``PASS_EVENTS`` mode, all note on/off events are passed to the port
- without modified. ``PROCESS_KEYPRESS`` mode checks the note above 128
- and regards it as key pressure event (mainly for Emu8000 driver).
- Open Callback
- -------------
- The ``open`` is called at each time this device is opened by an application
- using OSS sequencer. This must not be NULL. Typically, the open callback
- does the following procedure:
- #. Allocate private data record.
- #. Create an ALSA sequencer port.
- #. Set the new port address on ``arg->addr``.
- #. Set the private data record pointer on ``arg->private_data``.
- Note that the type bit-flags in port_info of this synth port must NOT contain
- ``TYPE_MIDI_GENERIC``
- bit. Instead, ``TYPE_SPECIFIC`` should be used. Also, ``CAP_SUBSCRIPTION``
- bit should NOT be included, too. This is necessary to tell it from other
- normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
- return -errno.
- Ioctl Callback
- --------------
- The ``ioctl`` callback is called when the sequencer receives device-specific
- ioctls. The following two ioctls should be processed by this callback:
- IOCTL_SEQ_RESET_SAMPLES
- reset all samples on memory -- return 0
- IOCTL_SYNTH_MEMAVL
- return the available memory size
- FM_4OP_ENABLE
- can be ignored usually
- The other ioctls are processed inside the sequencer without passing to
- the lowlevel driver.
- Load_Patch Callback
- -------------------
- The ``load_patch`` callback is used for sample-downloading. This callback
- must read the data on user-space and transfer to each device. Return 0
- if succeeded, and -errno if failed. The format argument is the patch key
- in patch_info record. The buf is user-space pointer where patch_info record
- is stored. The offs can be ignored. The count is total data size of this
- sample data.
- Close Callback
- --------------
- The ``close`` callback is called when this device is closed by the
- application. If any private data was allocated in open callback, it must
- be released in the close callback. The deletion of ALSA port should be
- done here, too. This callback must not be NULL.
- Reset Callback
- --------------
- The ``reset`` callback is called when sequencer device is reset or
- closed by applications. The callback should turn off the sounds on the
- relevant port immediately, and initialize the status of the port. If this
- callback is undefined, OSS seq sends a ``HEARTBEAT`` event to the
- port.
- Events
- ======
- Most of the events are processed by sequencer and translated to the adequate
- ALSA sequencer events, so that each synth device can receive by input_event
- callback of ALSA sequencer port. The following ALSA events should be
- implemented by the driver:
- ============= ===================
- ALSA event Original OSS events
- ============= ===================
- NOTEON SEQ_NOTEON, MIDI_NOTEON
- NOTE SEQ_NOTEOFF, MIDI_NOTEOFF
- KEYPRESS MIDI_KEY_PRESSURE
- CHANPRESS SEQ_AFTERTOUCH, MIDI_CHN_PRESSURE
- PGMCHANGE SEQ_PGMCHANGE, MIDI_PGM_CHANGE
- PITCHBEND SEQ_CONTROLLER(CTRL_PITCH_BENDER),
- MIDI_PITCH_BEND
- CONTROLLER MIDI_CTL_CHANGE,
- SEQ_BALANCE (with CTL_PAN)
- CONTROL14 SEQ_CONTROLLER
- REGPARAM SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
- SYSEX SEQ_SYSEX
- ============= ===================
- The most of these behavior can be realized by MIDI emulation driver
- included in the Emu8000 lowlevel driver. In the future release, this module
- will be independent.
- Some OSS events (``SEQ_PRIVATE`` and ``SEQ_VOLUME`` events) are passed as event
- type SND_SEQ_OSS_PRIVATE. The OSS sequencer passes these event 8 byte
- packets without any modification. The lowlevel driver should process these
- events appropriately.
- Interface to MIDI Device
- ========================
- Since the OSS emulation probes the creation and deletion of ALSA MIDI
- sequencer ports automatically by receiving announcement from ALSA
- sequencer, the MIDI devices don't need to be registered explicitly
- like synth devices.
- However, the MIDI port_info registered to ALSA sequencer must include
- a group name ``SND_SEQ_GROUP_DEVICE`` and a capability-bit
- ``CAP_READ`` or ``CAP_WRITE``. Also, subscription capabilities,
- ``CAP_SUBS_READ`` or ``CAP_SUBS_WRITE``, must be defined, too. If
- these conditions are not satisfied, the port is not registered as OSS
- sequencer MIDI device.
- The events via MIDI devices are parsed in OSS sequencer and converted
- to the corresponding ALSA sequencer events. The input from MIDI sequencer
- is also converted to MIDI byte events by OSS sequencer. This works just
- a reverse way of seq_midi module.
- Known Problems / TODO's
- =======================
- * Patch loading via ALSA instrument layer is not implemented yet.
|