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

Reply via email to