• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/iserver/alsa-lib-1.0.26/src/rawmidi/

Lines Matching defs:*

2  *  RawMIDI - Virtual (sequencer mode)
3 * Copyright (c) 2003 by Takashi Iwai <tiwai@suse.de>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include "rawmidi_local.h"
29 #include "seq.h"
30 #include "seq_midi_event.h"
32 #ifndef PIC
33 /* entry for static linking */
34 const char *_snd_module_rawmidi_virt = "";
35 #endif
38 #ifndef DOC_HIDDEN
39 typedef struct {
40 int open;
42 snd_seq_t *handle;
43 int port;
45 snd_midi_event_t *midi_event;
47 snd_seq_event_t *in_event;
48 int in_buf_size;
49 int in_buf_ofs;
50 char *in_buf_ptr;
51 char in_tmp_buf[16];
53 snd_seq_event_t out_event;
54 int pending;
55 } snd_rawmidi_virtual_t;
57 int _snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
58 int streams, int mode, snd_config_t *lconf,
59 snd_config_t *parent_conf);
60 #endif
62 static int snd_rawmidi_virtual_close(snd_rawmidi_t *rmidi)
64 snd_rawmidi_virtual_t *virt = rmidi->private_data;
65 virt->open--;
66 if (virt->open)
67 return 0;
68 snd_seq_close(virt->handle);
69 if (virt->midi_event)
70 snd_midi_event_free(virt->midi_event);
71 free(virt);
72 return 0;
75 static int snd_rawmidi_virtual_nonblock(snd_rawmidi_t *rmidi, int nonblock)
77 snd_rawmidi_virtual_t *virt = rmidi->private_data;
79 return snd_seq_nonblock(virt->handle, nonblock);
82 static int snd_rawmidi_virtual_info(snd_rawmidi_t *rmidi, snd_rawmidi_info_t * info)
84 // snd_rawmidi_virtual_t *virt = rmidi->private_data;
86 info->stream = rmidi->stream;
87 /* FIXME: what values should be there? */
88 info->card = 0;
89 info->device = 0;
90 info->subdevice = 0;
91 info->flags = 0;
92 strcpy((char *)info->id, "Virtual");
93 strcpy((char *)info->name, "Virtual RawMIDI");
94 strcpy((char *)info->subname, "Virtual RawMIDI");
95 info->subdevices_count = 1;
96 info->subdevices_avail = 0;
97 return 0;
100 static int snd_rawmidi_virtual_input_params(snd_rawmidi_virtual_t *virt, snd_rawmidi_params_t *params)
102 int err;
104 // snd_rawmidi_drain_input(substream);
105 if (params->buffer_size < sizeof(snd_seq_event_t) ||
106 params->buffer_size > 1024L * 1024L) {
107 return -EINVAL;
109 if (params->buffer_size != snd_seq_get_input_buffer_size(virt->handle)) {
110 err = snd_seq_set_input_buffer_size(virt->handle, params->buffer_size);
111 if (err < 0)
112 return err;
113 params->buffer_size = snd_seq_get_input_buffer_size(virt->handle);
114 /* FIXME: input pool size? */
116 return 0;
120 static int snd_rawmidi_virtual_output_params(snd_rawmidi_virtual_t *virt, snd_rawmidi_params_t *params)
122 int err;
124 // snd_rawmidi_drain_output(substream);
125 if (params->buffer_size < sizeof(snd_seq_event_t) ||
126 params->buffer_size > 1024L * 1024L) {
127 return -EINVAL;
129 if (params->buffer_size != snd_seq_get_output_buffer_size(virt->handle)) {
130 err = snd_seq_set_output_buffer_size(virt->handle, params->buffer_size);
131 if (err < 0)
132 return err;
133 params->buffer_size = snd_seq_get_output_buffer_size(virt->handle);
135 return 0;
139 static int snd_rawmidi_virtual_params(snd_rawmidi_t *rmidi, snd_rawmidi_params_t * params)
141 snd_rawmidi_virtual_t *virt = rmidi->private_data;
142 params->stream = rmidi->stream;
144 if (rmidi->stream == SND_RAWMIDI_STREAM_INPUT)
145 return snd_rawmidi_virtual_input_params(virt, params);
146 else
147 return snd_rawmidi_virtual_output_params(virt, params);
150 static int snd_rawmidi_virtual_status(snd_rawmidi_t *rmidi, snd_rawmidi_status_t * status)
152 // snd_rawmidi_virtual_t *virt = rmidi->private_data;
153 memset(status, 0, sizeof(*status));
154 status->stream = rmidi->stream;
155 return 0;
158 static int snd_rawmidi_virtual_drop(snd_rawmidi_t *rmidi)
160 snd_rawmidi_virtual_t *virt = rmidi->private_data;
161 if (rmidi->stream == SND_RAWMIDI_STREAM_OUTPUT) {
162 snd_seq_drop_output(virt->handle);
163 snd_midi_event_reset_encode(virt->midi_event);
164 virt->pending = 0;
165 } else {
166 snd_seq_drop_input(virt->handle);
167 snd_midi_event_reset_decode(virt->midi_event);
168 virt->in_buf_ofs = 0;
170 return 0;
173 static int snd_rawmidi_virtual_drain(snd_rawmidi_t *rmidi)
175 snd_rawmidi_virtual_t *virt = rmidi->private_data;
176 int err;
178 if (rmidi->stream == SND_RAWMIDI_STREAM_OUTPUT) {
179 if (virt->pending) {
180 err = snd_seq_event_output(virt->handle, &virt->out_event);
181 if (err < 0)
182 return err;
183 virt->pending = 0;
185 snd_seq_drain_output(virt->handle);
186 snd_seq_sync_output_queue(virt->handle);
188 return snd_rawmidi_virtual_drop(rmidi);
191 static ssize_t snd_rawmidi_virtual_write(snd_rawmidi_t *rmidi, const void *buffer, size_t size)
193 snd_rawmidi_virtual_t *virt = rmidi->private_data;
194 ssize_t result = 0;
195 ssize_t size1;
196 int err;
198 if (virt->pending) {
199 err = snd_seq_event_output(virt->handle, &virt->out_event);
200 if (err < 0) {
201 if (err != -EAGAIN)
202 /* we got some fatal error. removing this event
203 * at the next time
205 virt->pending = 0;
206 return err;
208 virt->pending = 0;
211 while (size > 0) {
212 size1 = snd_midi_event_encode(virt->midi_event, buffer, size, &virt->out_event);
213 if (size1 <= 0)
214 break;
215 size -= size1;
216 result += size1;
217 buffer += size1;
218 if (virt->out_event.type == SND_SEQ_EVENT_NONE)
219 continue;
220 snd_seq_ev_set_subs(&virt->out_event);
221 snd_seq_ev_set_source(&virt->out_event, virt->port);
222 snd_seq_ev_set_direct(&virt->out_event);
223 err = snd_seq_event_output(virt->handle, &virt->out_event);
224 if (err < 0) {
225 virt->pending = 1;
226 return result > 0 ? result : err;
230 if (result > 0)
231 snd_seq_drain_output(virt->handle);
233 return result;
236 static ssize_t snd_rawmidi_virtual_read(snd_rawmidi_t *rmidi, void *buffer, size_t size)
238 snd_rawmidi_virtual_t *virt = rmidi->private_data;
239 ssize_t result = 0;
240 int size1, err;
242 while (size > 0) {
243 if (! virt->in_buf_ofs) {
244 err = snd_seq_event_input_pending(virt->handle, 1);
245 if (err <= 0 && result > 0)
246 return result;
247 err = snd_seq_event_input(virt->handle, &virt->in_event);
248 if (err < 0)
249 return result > 0 ? result : err;
251 if (virt->in_event->type == SND_SEQ_EVENT_SYSEX) {
252 virt->in_buf_ptr = virt->in_event->data.ext.ptr;
253 virt->in_buf_size = virt->in_event->data.ext.len;
254 } else {
255 virt->in_buf_ptr = virt->in_tmp_buf;
256 virt->in_buf_size = snd_midi_event_decode(virt->midi_event,
257 (unsigned char *)virt->in_tmp_buf,
258 sizeof(virt->in_tmp_buf),
259 virt->in_event);
261 if (virt->in_buf_size <= 0)
262 continue;
264 size1 = virt->in_buf_size - virt->in_buf_ofs;
265 if ((size_t)size1 > size) {
266 virt->in_buf_ofs += size1 - size;
267 memcpy(buffer, virt->in_buf_ptr, size);
268 result += size;
269 break;
271 memcpy(buffer, virt->in_buf_ptr + virt->in_buf_ofs, size1);
272 size -= size1;
273 result += size1;
274 buffer += size1;
275 virt->in_buf_ofs = 0;
278 return result;
281 static const snd_rawmidi_ops_t snd_rawmidi_virtual_ops = {
282 .close = snd_rawmidi_virtual_close,
283 .nonblock = snd_rawmidi_virtual_nonblock,
284 .info = snd_rawmidi_virtual_info,
285 .params = snd_rawmidi_virtual_params,
286 .status = snd_rawmidi_virtual_status,
287 .drop = snd_rawmidi_virtual_drop,
288 .drain = snd_rawmidi_virtual_drain,
289 .write = snd_rawmidi_virtual_write,
290 .read = snd_rawmidi_virtual_read,
294 /*! \page rawmidi RawMidi interface
296 \section rawmidi_virt Virtual RawMidi interface
298 The "virtual" plugin creates a virtual RawMidi instance on the ALSA
299 sequencer, which can be accessed through the connection of the sequencer
300 ports.
301 There is no connection established as default.
303 For creating a virtual RawMidi instance, pass "virtual" as its name at
304 creation.
306 Example:
307 \code
308 snd_rawmidi_open(&read_handle, &write_handle, "virtual", 0);
309 \endcode
313 int snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
314 const char *name, snd_seq_t *seq_handle, int port,
315 int merge, int mode)
317 int err;
318 snd_rawmidi_t *rmidi;
319 snd_rawmidi_virtual_t *virt = NULL;
320 struct pollfd pfd;
322 if (inputp)
323 *inputp = 0;
324 if (outputp)
325 *outputp = 0;
327 virt = calloc(1, sizeof(*virt));
328 if (virt == NULL) {
329 err = -ENOMEM;
330 goto _err;
332 virt->handle = seq_handle;
333 virt->port = port;
334 err = snd_midi_event_new(256, &virt->midi_event);
335 if (err < 0)
336 goto _err;
337 snd_midi_event_init(virt->midi_event);
338 snd_midi_event_no_status(virt->midi_event, !merge);
340 if (inputp) {
341 rmidi = calloc(1, sizeof(*rmidi));
342 if (rmidi == NULL) {
343 err = -ENOMEM;
344 goto _err;
346 if (name)
347 rmidi->name = strdup(name);
348 rmidi->type = SND_RAWMIDI_TYPE_VIRTUAL;
349 rmidi->stream = SND_RAWMIDI_STREAM_INPUT;
350 rmidi->mode = mode;
351 err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLIN);
352 if (err < 0)
353 goto _err;
354 rmidi->poll_fd = pfd.fd;
355 rmidi->ops = &snd_rawmidi_virtual_ops;
356 rmidi->private_data = virt;
357 virt->open++;
358 *inputp = rmidi;
360 if (outputp) {
361 rmidi = calloc(1, sizeof(*rmidi));
362 if (rmidi == NULL) {
363 err = -ENOMEM;
364 goto _err;
366 if (name)
367 rmidi->name = strdup(name);
368 rmidi->type = SND_RAWMIDI_TYPE_VIRTUAL;
369 rmidi->stream = SND_RAWMIDI_STREAM_OUTPUT;
370 rmidi->mode = mode;
371 err = snd_seq_poll_descriptors(seq_handle, &pfd, 1, POLLOUT);
372 if (err < 0)
373 goto _err;
374 rmidi->poll_fd = pfd.fd;
375 rmidi->ops = &snd_rawmidi_virtual_ops;
376 rmidi->private_data = virt;
377 virt->open++;
378 *outputp = rmidi;
381 return 0;
383 _err:
384 if (seq_handle)
385 snd_seq_close(seq_handle);
386 if (virt) {
387 if (virt->midi_event)
388 snd_midi_event_free(virt->midi_event);
389 free(virt);
391 if (inputp)
392 free(*inputp);
393 if (outputp)
394 free(*outputp);
395 return err;
398 int _snd_rawmidi_virtual_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
399 char *name, snd_config_t *root ATTRIBUTE_UNUSED,
400 snd_config_t *conf, int mode)
402 snd_config_iterator_t i, next;
403 const char *slave_str = NULL;
404 int err;
405 int streams, seq_mode;
406 int merge = 1;
407 int port;
408 unsigned int caps;
409 snd_seq_t *seq_handle;
411 snd_config_for_each(i, next, conf) {
412 snd_config_t *n = snd_config_iterator_entry(i);
413 const char *id;
414 if (snd_config_get_id(n, &id) < 0)
415 continue;
416 if (snd_rawmidi_conf_generic_id(id))
417 continue;
418 if (strcmp(id, "slave") == 0) {
419 err = snd_config_get_string(n, &slave_str);
420 if (err < 0)
421 return err;
422 continue;
424 if (strcmp(id, "merge") == 0) {
425 merge = snd_config_get_bool(n);
426 continue;
428 return -EINVAL;
431 streams = 0;
432 if (inputp)
433 streams |= SND_SEQ_OPEN_INPUT;
434 if (outputp)
435 streams |= SND_SEQ_OPEN_OUTPUT;
436 if (! streams)
437 return -EINVAL;
439 seq_mode = 0;
440 if (mode & SND_RAWMIDI_NONBLOCK)
441 seq_mode |= SND_SEQ_NONBLOCK;
443 if (! slave_str)
444 slave_str = "default";
445 err = _snd_seq_open_lconf(&seq_handle, slave_str, streams, seq_mode,
446 root, conf);
447 if (err < 0)
448 return err;
450 caps = 0;
451 if (inputp)
452 caps |= SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SYNC_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;
453 if (outputp)
454 caps |= SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SYNC_READ | SND_SEQ_PORT_CAP_SUBS_READ;
455 if (inputp && outputp)
456 caps |= SNDRV_SEQ_PORT_CAP_DUPLEX;
458 port = snd_seq_create_simple_port(seq_handle, "Virtual RawMIDI",
459 caps, SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC);
460 if (port < 0) {
461 snd_seq_close(seq_handle);
462 return port;
465 return snd_rawmidi_virtual_open(inputp, outputp, name, seq_handle, port,
466 merge, mode);
469 #ifndef DOC_HIDDEN
470 SND_DLSYM_BUILD_VERSION(_snd_rawmidi_virtual_open, SND_RAWMIDI_DLSYM_VERSION);
471 #endif