Update of /cvsroot/alsa/alsa-lib/src/rawmidi In directory sc8-pr-cvs1:/tmp/cvs-serv18228
Modified Files: Makefile.am rawmidi_local.h rawmidi_symbols.c Added Files: rawmidi_virt.c Log Message: added virtual rawmidi plugin. --- NEW FILE: rawmidi_virt.c --- /* * RawMIDI - Virtual (sequencer mode) * Copyright (c) 2003 by Takashi Iwai <[EMAIL PROTECTED]> * * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/ioctl.h> #include "rawmidi_local.h" #include "seq.h" #include "seq_midi_event.h" #ifndef PIC /* entry for static linking */ const char *_snd_module_rawmidi_virt = ""; #endif typedef struct { int open; snd_seq_t *handle; int port; snd_midi_event_t *midi_event; snd_seq_event_t *in_event; int in_buf_size; int in_buf_ofs; char *in_buf_ptr; char in_tmp_buf[16]; snd_seq_event_t out_event; int pending; } snd_rawmidi_virt_t; static int snd_rawmidi_virt_close(snd_rawmidi_t *rmidi) { snd_rawmidi_virt_t *virt = rmidi->private_data; virt->open--; if (virt->open) return 0; snd_seq_close(virt->handle); if (virt->midi_event) snd_midi_event_free(virt->midi_event); free(virt); return 0; } static int snd_rawmidi_virt_nonblock(snd_rawmidi_t *rmidi, int nonblock) { snd_rawmidi_virt_t *virt = rmidi->private_data; return snd_seq_nonblock(virt->handle, nonblock); } static int snd_rawmidi_virt_info(snd_rawmidi_t *rmidi, snd_rawmidi_info_t * info) { // snd_rawmidi_virt_t *virt = rmidi->private_data; info->stream = rmidi->stream; /* FIXME: what values should be there? */ info->card = 0; info->device = 0; info->subdevice = 0; info->flags = 0; strcpy(info->id, "Virtual"); strcpy(info->name, "Virtual RawMIDI"); strcpy(info->subname, "Virtual RawMIDI"); info->subdevices_count = 1; info->subdevices_avail = 0; return 0; } static int snd_rawmidi_virt_input_params(snd_rawmidi_virt_t *virt, snd_rawmidi_params_t *params) { int err; // snd_rawmidi_drain_input(substream); if (params->buffer_size < sizeof(snd_seq_event_t) || params->buffer_size > 1024L * 1024L) { return -EINVAL; } if (params->buffer_size != snd_seq_get_input_buffer_size(virt->handle)) { err = snd_seq_set_input_buffer_size(virt->handle, params->buffer_size); if (err < 0) return err; params->buffer_size = snd_seq_get_input_buffer_size(virt->handle); /* FIXME: input pool size? */ } return 0; } static int snd_rawmidi_virt_output_params(snd_rawmidi_virt_t *virt, snd_rawmidi_params_t *params) { int err; // snd_rawmidi_drain_output(substream); if (params->buffer_size < sizeof(snd_seq_event_t) || params->buffer_size > 1024L * 1024L) { return -EINVAL; } if (params->buffer_size != snd_seq_get_output_buffer_size(virt->handle)) { err = snd_seq_set_output_buffer_size(virt->handle, params->buffer_size); if (err < 0) return err; params->buffer_size = snd_seq_get_output_buffer_size(virt->handle); } return 0; } static int snd_rawmidi_virt_params(snd_rawmidi_t *rmidi, snd_rawmidi_params_t * params) { snd_rawmidi_virt_t *virt = rmidi->private_data; params->stream = rmidi->stream; if (rmidi->stream == SND_RAWMIDI_STREAM_INPUT) return snd_rawmidi_virt_input_params(virt, params); else return snd_rawmidi_virt_output_params(virt, params); } static int snd_rawmidi_virt_status(snd_rawmidi_t *rmidi, snd_rawmidi_status_t * status) { // snd_rawmidi_virt_t *virt = rmidi->private_data; memset(status, 0, sizeof(*status)); status->stream = rmidi->stream; return 0; } static int snd_rawmidi_virt_drop(snd_rawmidi_t *rmidi) { snd_rawmidi_virt_t *virt = rmidi->private_data; if (rmidi->stream == SND_RAWMIDI_STREAM_OUTPUT) { snd_seq_drop_output(virt->handle); snd_midi_event_reset_encode(virt->midi_event); virt->pending = 0; } else { snd_seq_drop_input(virt->handle); snd_midi_event_reset_decode(virt->midi_event); virt->in_buf_ofs = 0; } return 0; } static int snd_rawmidi_virt_drain(snd_rawmidi_t *rmidi) { snd_rawmidi_virt_t *virt = rmidi->private_data; int err; if (rmidi->stream == SND_RAWMIDI_STREAM_OUTPUT) { if (virt->pending) { err = snd_seq_event_output(virt->handle, &virt->out_event); if (err < 0) return err; virt->pending = 0; } snd_seq_drain_output(virt->handle); snd_seq_sync_output_queue(virt->handle); } return snd_rawmidi_virt_drop(rmidi); } static ssize_t snd_rawmidi_virt_write(snd_rawmidi_t *rmidi, const void *buffer, size_t size) { snd_rawmidi_virt_t *virt = rmidi->private_data; ssize_t result = 0; ssize_t size1; int err; if (virt->pending) { err = snd_seq_event_output(virt->handle, &virt->out_event); if (err < 0) { if (err != -EAGAIN) /* we got some fatal error. removing this event * at the next time */ virt->pending = 0; return err; } virt->pending = 0; } while (size > 0) { size1 = snd_midi_event_encode(virt->midi_event, buffer, size, &virt->out_event); if (size1 <= 0) break; if (virt->out_event.type == SND_SEQ_EVENT_NONE) continue; size -= size1; result += size1; buffer += size1; snd_seq_ev_set_subs(&virt->out_event); snd_seq_ev_set_source(&virt->out_event, virt->port); snd_seq_ev_set_direct(&virt->out_event); err = snd_seq_event_output(virt->handle, &virt->out_event); if (err < 0) { virt->pending = 1; return result > 0 ? result : err; } } if (result > 0) snd_seq_drain_output(virt->handle); return result; } static ssize_t snd_rawmidi_virt_read(snd_rawmidi_t *rmidi, void *buffer, size_t size) { snd_rawmidi_virt_t *virt = rmidi->private_data; ssize_t result = 0; int size1, err; while (size > 0) { if (! virt->in_buf_ofs) { err = snd_seq_event_input_pending(virt->handle, 1); if (err <= 0 && result > 0) return result; err = snd_seq_event_input(virt->handle, &virt->in_event); if (err < 0) return result > 0 ? result : err; if (virt->in_event->type == SND_SEQ_EVENT_SYSEX) { virt->in_buf_ptr = virt->in_event->data.ext.ptr; virt->in_buf_size = virt->in_event->data.ext.len; } else { virt->in_buf_ptr = virt->in_tmp_buf; virt->in_buf_size = snd_midi_event_decode(virt->midi_event, virt->in_tmp_buf, sizeof(virt->in_tmp_buf), virt->in_event); } if (virt->in_buf_size <= 0) continue; } size1 = virt->in_buf_size - virt->in_buf_ofs; if ((size_t)size1 > size) { virt->in_buf_ofs += size1 - size; memcpy(buffer, virt->in_buf_ptr, size); result += size; break; } memcpy(buffer, virt->in_buf_ptr + virt->in_buf_ofs, size1); size -= size1; result += size1; buffer += size1; virt->in_buf_ofs = 0; } return result; } snd_rawmidi_ops_t snd_rawmidi_virt_ops = { .close = snd_rawmidi_virt_close, .nonblock = snd_rawmidi_virt_nonblock, .info = snd_rawmidi_virt_info, .params = snd_rawmidi_virt_params, .status = snd_rawmidi_virt_status, .drop = snd_rawmidi_virt_drop, .drain = snd_rawmidi_virt_drain, .write = snd_rawmidi_virt_write, .read = snd_rawmidi_virt_read, }; /*! \page rawmidi RawMidi interface \section rawmidi_virt Virtual RawMidi interface The "virt" plugin creates a virtual RawMidi instance on the ALSA sequencer, which can be accessed through the connection of the sequencer ports. There is no connection established as default. For creating a virtual RawMidi instance, pass "virt" as its name at creation. Example: \code snd_rawmidi_open(&read_handle, &write_handle, "virt", 0); \endcode */ int snd_rawmidi_virt_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, const char *name, snd_seq_t *seq_handle, int port, int merge, int mode) { int err; snd_rawmidi_t *rmidi; snd_rawmidi_virt_t *virt = NULL; struct pollfd pfd; if (inputp) *inputp = 0; if (outputp) *outputp = 0; virt = calloc(1, sizeof(*virt)); if (virt == NULL) { err = -ENOMEM; goto _err; } virt->handle = seq_handle; virt->port = port; err = snd_midi_event_new(256, &virt->midi_event); if (err < 0) goto _err; snd_midi_event_init(virt->midi_event); snd_midi_event_no_status(virt->midi_event, !merge); if (inputp) { rmidi = calloc(1, sizeof(*rmidi)); if (rmidi == NULL) { err = -ENOMEM; goto _err; } if (name) rmidi->name = strdup(name); rmidi->type = SND_RAWMIDI_TYPE_VIRT; rmidi->stream = SND_RAWMIDI_STREAM_INPUT; rmidi->mode = mode; err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLIN); if (err < 0) goto _err; rmidi->poll_fd = pfd.fd; rmidi->ops = &snd_rawmidi_virt_ops; rmidi->private_data = virt; virt->open++; *inputp = rmidi; } if (outputp) { rmidi = calloc(1, sizeof(*rmidi)); if (rmidi == NULL) { err = -ENOMEM; goto _err; } if (name) rmidi->name = strdup(name); rmidi->type = SND_RAWMIDI_TYPE_VIRT; rmidi->stream = SND_RAWMIDI_STREAM_OUTPUT; rmidi->mode = mode; err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLOUT); if (err < 0) goto _err; rmidi->poll_fd = pfd.fd; rmidi->ops = &snd_rawmidi_virt_ops; rmidi->private_data = virt; virt->open++; *outputp = rmidi; } return 0; _err: if (seq_handle) snd_seq_close(seq_handle); if (virt->midi_event) snd_midi_event_free(virt->midi_event); if (virt) free(virt); if (inputp && *inputp) free(*inputp); if (outputp && *outputp) free(*outputp); return err; } int _snd_rawmidi_virt_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, char *name, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *conf, int mode) { snd_config_iterator_t i, next; const char *slave_str = NULL; int err; int streams, seq_mode; int merge = 1; int port; unsigned int caps; snd_seq_t *seq_handle; snd_config_for_each(i, next, conf) { snd_config_t *n = snd_config_iterator_entry(i); const char *id; if (snd_config_get_id(n, &id) < 0) continue; if (strcmp(id, "comment") == 0) continue; if (strcmp(id, "type") == 0) continue; if (strcmp(id, "slave") == 0) { err = snd_config_get_string(n, &slave_str); if (err < 0) return err; continue; } if (strcmp(id, "merge") == 0) { merge = snd_config_get_bool(n); continue; } return -EINVAL; } streams = 0; if (inputp) streams |= SND_SEQ_OPEN_INPUT; if (outputp) streams |= SND_SEQ_OPEN_OUTPUT; if (! streams) return -EINVAL; seq_mode = 0; if (mode & SND_RAWMIDI_NONBLOCK) seq_mode |= O_NONBLOCK; if (! slave_str) slave_str = "default"; err = snd_seq_open_lconf(&seq_handle, slave_str, streams, seq_mode, root); if (err < 0) return err; caps = 0; if (inputp) caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SYNC_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE; if (outputp) caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SYNC_READ | SND_SEQ_PORT_CAP_SUBS_READ; if (inputp && outputp) pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; port = snd_seq_create_simple_port(seq_handle, "Virtual RawMIDI", caps, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC); if (port < 0) { snd_seq_close(seq_handle); return port; } return snd_rawmidi_virt_open(inputp, outputp, name, seq_handle, port, merge, mode); } #ifndef DOC_HIDDEN SND_DLSYM_BUILD_VERSION(_snd_rawmidi_virt_open, SND_RAWMIDI_DLSYM_VERSION); #endif Index: Makefile.am =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/rawmidi/Makefile.am,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- Makefile.am 24 Oct 2001 14:14:16 -0000 1.5 +++ Makefile.am 29 Jul 2003 17:15:34 -0000 1.6 @@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES=librawmidi.la -librawmidi_la_SOURCES = rawmidi.c rawmidi_hw.c rawmidi_symbols.c +librawmidi_la_SOURCES = rawmidi.c rawmidi_hw.c rawmidi_symbols.c rawmidi_virt.c noinst_HEADERS = rawmidi_local.h all: librawmidi.la Index: rawmidi_local.h =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/rawmidi/rawmidi_local.h,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- rawmidi_local.h 7 Nov 2002 15:18:53 -0000 1.14 +++ rawmidi_local.h 29 Jul 2003 17:15:34 -0000 1.15 @@ -53,3 +53,7 @@ int snd_rawmidi_hw_open(snd_rawmidi_t **input, snd_rawmidi_t **output, const char *name, int card, int device, int subdevice, int mode); + +int snd_rawmidi_virt_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp, + const char *name, snd_seq_t *seq_handle, int port, + int merge, int mode); Index: rawmidi_symbols.c =================================================================== RCS file: /cvsroot/alsa/alsa-lib/src/rawmidi/rawmidi_symbols.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- rawmidi_symbols.c 30 Dec 2001 09:22:56 -0000 1.2 +++ rawmidi_symbols.c 29 Jul 2003 17:15:34 -0000 1.3 @@ -21,9 +21,11 @@ #ifndef PIC extern const char *_snd_module_rawmidi_hw; +extern const char *_snd_module_rawmidi_virt; static const char **snd_rawmidi_open_objects[] = { - &_snd_module_rawmidi_hw + &_snd_module_rawmidi_hw, + &_snd_module_rawmidi_virt }; void *snd_rawmidi_open_symbols(void) ------------------------------------------------------- This SF.Net email sponsored by: Free pre-built ASP.NET sites including Data Reports, E-commerce, Portals, and Forums are available now. Download today and enter to win an XBOX or Visual Studio .NET. http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01 _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog