1/**
2 * \file rawmidi/rawmidi.c
3 * \brief RawMidi Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \date 2000-2001
7 *
8 * See the \ref rawmidi page for more details.
9 */
10/*
11 *
12 *   This library is free software; you can redistribute it and/or modify
13 *   it under the terms of the GNU Lesser General Public License as
14 *   published by the Free Software Foundation; either version 2.1 of
15 *   the License, or (at your option) any later version.
16 *
17 *   This program is distributed in the hope that it will be useful,
18 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 *   GNU Lesser General Public License for more details.
21 *
22 *   You should have received a copy of the GNU Lesser General Public
23 *   License along with this library; if not, write to the Free Software
24 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
25 *
26 */
27
28/*! \page rawmidi RawMidi interface
29
30<P>RawMidi Interface is designed to write or read raw (unchanged) MIDI
31data over the MIDI line without any timestamps defined in interface. MIDI
32stands Musical Instrument Digital Interface and more information about
33this standard can be found at http://www.midi.org.
34
35\section rawmidi_general_overview General overview
36
37The rawmidi implementation uses ring buffers to store outgoing and incoming
38MIDI stream. The buffer size is tunable and drivers report underruns for incoming
39stream as well.
40
41\section rawmidi_open Open handling
42
43RawMidi devices are opened exclusively for a selected direction.
44While more than one process may not open a given MIDI device in the same
45direction simultaneously, separate processes may open a single MIDI device
46in different directions (i.e. process one opens a MIDI device in write
47direction and process two opens the same device in read direction).
48
49\subsection rawmidi_open_nonblock Nonblocking open (flag)
50
51Using #SND_RAWMIDI_NONBLOCK flag for snd_rawmidi_open() or snd_rawmidi_open_lconf()
52instruct device driver to return the -EBUSY error when device is already occupied
53with another application. This flag also changes behaviour of snd_rawmidi_write()
54and snd_rawmidi_read() returning -EAGAIN when no more bytes can be processed.
55
56Note: In opposite (default) behaviour, application is blocked until device resources
57are free.
58
59\subsection rawmidi_open_append Append open (flag)
60
61Using #SND_RAWMIDI_APPEND flag (output only) instruct device driver to append
62contents of written buffer - passed by snd_rawmidi_write() - atomically
63to output ring buffer in the kernel space. This flag also means that device
64is not opened exclusively, so more applications can share given rawmidi device.
65Note that applications must send the whole MIDI message including the running status,
66because another writting application might break the MIDI message in the output
67buffer.
68
69\subsection rawmidi_open_sync Sync open (flag)
70
71Using #SND_RAWMIDI_SYNC flag (output only) assures that the contents of output
72buffer specified using snd_rawmidi_write() is always drained before the function
73exits. This behaviour is same like 'snd_rawmidi_write() followed by
74snd_rawmidi_drain() immediately'.
75
76\subsection rawmidi_io I/O handling
77
78There is only standard read/write access to device internal ring buffer. Use
79snd_rawmidi_read() and snd_rawmidi_write() functions to obtain / write MIDI bytes.
80
81\subsection rawmidi_dev_names RawMidi naming conventions
82
83The ALSA library uses a generic string representation for names of devices.
84The devices might be virtual, physical or a mix of both. The generic string
85is passed to \link ::snd_rawmidi_open() \endlink or \link ::snd_rawmidi_open_lconf() \endlink.
86It contains two parts: device name and arguments. Devices and arguments are described
87in configuration files. The usual place for default definitions is at /usr/share/alsa/alsa.conf.
88
89\subsection rawmidi_dev_names_default
90
91The default device is equal to hw device. The defaults are used:
92
93defaults.rawmidi.card 0
94defaults.rawmidi.device 0
95defaults.rawmidi.subdevice -1
96
97These defaults can be freely overwritten in local configuration files.
98
99Example:
100
101\code
102default
103\endcode
104
105\subsection rawmidi_dev_names_hw HW device
106
107The hw device description uses the hw plugin. The three arguments (in order: CARD,DEV,SUBDEV)
108specify card number or identifier, device number and subdevice number (-1 means any).
109
110Example:
111
112\code
113hw
114hw:0
115hw:0,0
116hw:supersonic,1
117hw:soundwave,1,2
118hw:DEV=1,CARD=soundwave,SUBDEV=2
119\endcode
120
121\section rawmidi_examples Examples
122
123The full featured examples with cross-links:
124
125\par Simple input/output test program
126\ref example_test_rawmidi "example code"
127\par
128This example shows open and read/write rawmidi operations.
129
130*/
131
132/**
133 * \example ../test/rawmidi.c
134 * \anchor example_test_rawmidi
135 */
136
137#include <stdio.h>
138#include <stdlib.h>
139#include <stdarg.h>
140#include <unistd.h>
141#include <string.h>
142#include "rawmidi_local.h"
143
144/**
145 * \brief setup the default parameters
146 * \param rawmidi RawMidi handle
147 * \param params pointer to a snd_rawmidi_params_t structure
148 * \return 0 on success otherwise a negative error code
149 */
150static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
151{
152	assert(rawmidi);
153	assert(params);
154	params->buffer_size = page_size();
155	params->avail_min = 1;
156	params->no_active_sensing = 1;
157	return 0;
158}
159
160static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
161				 const char *name, snd_config_t *rawmidi_root,
162				 snd_config_t *rawmidi_conf, int mode)
163{
164	const char *str;
165	char buf[256];
166	int err;
167	snd_config_t *conf, *type_conf = NULL;
168	snd_config_iterator_t i, next;
169	snd_rawmidi_params_t params;
170	const char *id;
171	const char *lib = NULL, *open_name = NULL;
172	int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **,
173			 const char *, snd_config_t *, snd_config_t *, int) = NULL;
174#ifndef PIC
175	extern void *snd_rawmidi_open_symbols(void);
176#endif
177	void *h = NULL;
178	if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
179		if (name)
180			SNDERR("Invalid type for RAWMIDI %s definition", name);
181		else
182			SNDERR("Invalid type for RAWMIDI definition");
183		return -EINVAL;
184	}
185	err = snd_config_search(rawmidi_conf, "type", &conf);
186	if (err < 0) {
187		SNDERR("type is not defined");
188		return err;
189	}
190	err = snd_config_get_id(conf, &id);
191	if (err < 0) {
192		SNDERR("unable to get id");
193		return err;
194	}
195	err = snd_config_get_string(conf, &str);
196	if (err < 0) {
197		SNDERR("Invalid type for %s", id);
198		return err;
199	}
200	err = snd_config_search_definition(rawmidi_root, "rawmidi_type", str, &type_conf);
201	if (err >= 0) {
202		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
203			SNDERR("Invalid type for RAWMIDI type %s definition", str);
204			err = -EINVAL;
205			goto _err;
206		}
207		snd_config_for_each(i, next, type_conf) {
208			snd_config_t *n = snd_config_iterator_entry(i);
209			const char *id;
210			if (snd_config_get_id(n, &id) < 0)
211				continue;
212			if (strcmp(id, "comment") == 0)
213				continue;
214			if (strcmp(id, "lib") == 0) {
215				err = snd_config_get_string(n, &lib);
216				if (err < 0) {
217					SNDERR("Invalid type for %s", id);
218					goto _err;
219				}
220				continue;
221			}
222			if (strcmp(id, "open") == 0) {
223				err = snd_config_get_string(n, &open_name);
224				if (err < 0) {
225					SNDERR("Invalid type for %s", id);
226					goto _err;
227				}
228				continue;
229			}
230			SNDERR("Unknown field %s", id);
231			err = -EINVAL;
232			goto _err;
233		}
234	}
235	if (!open_name) {
236		open_name = buf;
237		snprintf(buf, sizeof(buf), "_snd_rawmidi_%s_open", str);
238	}
239#ifndef PIC
240	snd_rawmidi_open_symbols();
241#endif
242	h = snd_dlopen(lib, RTLD_NOW);
243	if (h)
244		open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION));
245	err = 0;
246	if (!h) {
247		SNDERR("Cannot open shared library %s", lib);
248		err = -ENOENT;
249	} else if (!open_func) {
250		SNDERR("symbol %s is not defined inside %s", open_name, lib);
251		snd_dlclose(h);
252		err = -ENXIO;
253	}
254       _err:
255	if (type_conf)
256		snd_config_delete(type_conf);
257	if (err >= 0)
258		err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
259	if (err < 0)
260		return err;
261	if (inputp) {
262		(*inputp)->dl_handle = h; h = NULL;
263		snd_rawmidi_params_default(*inputp, &params);
264		err = snd_rawmidi_params(*inputp, &params);
265		assert(err >= 0);
266	}
267	if (outputp) {
268		(*outputp)->dl_handle = h;
269		snd_rawmidi_params_default(*outputp, &params);
270		err = snd_rawmidi_params(*outputp, &params);
271		assert(err >= 0);
272	}
273	return 0;
274}
275
276static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
277				     snd_config_t *root, const char *name, int mode)
278{
279	int err;
280	snd_config_t *rawmidi_conf;
281	err = snd_config_search_definition(root, "rawmidi", name, &rawmidi_conf);
282	if (err < 0) {
283		SNDERR("Unknown RawMidi %s", name);
284		return err;
285	}
286	err = snd_rawmidi_open_conf(inputp, outputp, name, root, rawmidi_conf, mode);
287	snd_config_delete(rawmidi_conf);
288	return err;
289}
290
291/**
292 * \brief Opens a new connection to the RawMidi interface.
293 * \param inputp Returned input handle (NULL if not wanted)
294 * \param outputp Returned output handle (NULL if not wanted)
295 * \param name ASCII identifier of the RawMidi handle
296 * \param mode Open mode
297 * \return 0 on success otherwise a negative error code
298 *
299 * Opens a new connection to the RawMidi interface specified with
300 * an ASCII identifier and mode.
301 */
302int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
303		     const char *name, int mode)
304{
305	int err;
306	assert((inputp || outputp) && name);
307	err = snd_config_update();
308	if (err < 0)
309		return err;
310	return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode);
311}
312
313/**
314 * \brief Opens a new connection to the RawMidi interface using local configuration
315 * \param inputp Returned input handle (NULL if not wanted)
316 * \param outputp Returned output handle (NULL if not wanted)
317 * \param name ASCII identifier of the RawMidi handle
318 * \param mode Open mode
319 * \param lconf Local configuration
320 * \return 0 on success otherwise a negative error code
321 *
322 * Opens a new connection to the RawMidi interface specified with
323 * an ASCII identifier and mode.
324 */
325int snd_rawmidi_open_lconf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
326			   const char *name, int mode, snd_config_t *lconf)
327{
328	assert((inputp || outputp) && name && lconf);
329	return snd_rawmidi_open_noupdate(inputp, outputp, lconf, name, mode);
330}
331
332/**
333 * \brief close RawMidi handle
334 * \param rawmidi RawMidi handle
335 * \return 0 on success otherwise a negative error code
336 *
337 * Closes the specified RawMidi handle and frees all associated
338 * resources.
339 */
340int snd_rawmidi_close(snd_rawmidi_t *rawmidi)
341{
342	int err;
343  	assert(rawmidi);
344	err = rawmidi->ops->close(rawmidi);
345	free(rawmidi->name);
346	if (rawmidi->dl_handle)
347		snd_dlclose(rawmidi->dl_handle);
348	free(rawmidi);
349	return err;
350}
351
352/**
353 * \brief get identifier of RawMidi handle
354 * \param rawmidi a RawMidi handle
355 * \return ascii identifier of RawMidi handle
356 *
357 * Returns the ASCII identifier of given RawMidi handle. It's the same
358 * identifier specified in snd_rawmidi_open().
359 */
360const char *snd_rawmidi_name(snd_rawmidi_t *rawmidi)
361{
362	assert(rawmidi);
363	return rawmidi->name;
364}
365
366/**
367 * \brief get type of RawMidi handle
368 * \param rawmidi a RawMidi handle
369 * \return type of RawMidi handle
370 *
371 * Returns the type #snd_rawmidi_type_t of given RawMidi handle.
372 */
373snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rawmidi)
374{
375	assert(rawmidi);
376	return rawmidi->type;
377}
378
379/**
380 * \brief get stream (direction) of RawMidi handle
381 * \param rawmidi a RawMidi handle
382 * \return stream of RawMidi handle
383 *
384 * Returns the stream #snd_rawmidi_stream_t of given RawMidi handle.
385 */
386snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi)
387{
388	assert(rawmidi);
389	return rawmidi->stream;
390}
391
392/**
393 * \brief get count of poll descriptors for RawMidi handle
394 * \param rawmidi RawMidi handle
395 * \return count of poll descriptors
396 */
397int snd_rawmidi_poll_descriptors_count(snd_rawmidi_t *rawmidi)
398{
399	assert(rawmidi);
400	return 1;
401}
402
403/**
404 * \brief get poll descriptors
405 * \param rawmidi RawMidi handle
406 * \param pfds array of poll descriptors
407 * \param space space in the poll descriptor array
408 * \return count of filled descriptors
409 */
410int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int space)
411{
412	assert(rawmidi);
413	if (space >= 1) {
414		pfds->fd = rawmidi->poll_fd;
415		pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? (POLLOUT|POLLERR|POLLNVAL) : (POLLIN|POLLERR|POLLNVAL);
416		return 1;
417	}
418	return 0;
419}
420
421/**
422 * \brief get returned events from poll descriptors
423 * \param rawmidi rawmidi RawMidi handle
424 * \param pfds array of poll descriptors
425 * \param nfds count of poll descriptors
426 * \param revents returned events
427 * \return zero if success, otherwise a negative error code
428 */
429int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
430{
431        assert(rawmidi && pfds && revents);
432        if (nfds == 1) {
433                *revents = pfds->revents;
434                return 0;
435        }
436        return -EINVAL;
437}
438
439/**
440 * \brief set nonblock mode
441 * \param rawmidi RawMidi handle
442 * \param nonblock 0 = block, 1 = nonblock mode
443 * \return 0 on success otherwise a negative error code
444 *
445 * The nonblock mode cannot be used when the stream is in
446 * #SND_RAWMIDI_APPEND state.
447 */
448int snd_rawmidi_nonblock(snd_rawmidi_t *rawmidi, int nonblock)
449{
450	int err;
451	assert(rawmidi);
452	assert(!(rawmidi->mode & SND_RAWMIDI_APPEND));
453	if ((err = rawmidi->ops->nonblock(rawmidi, nonblock)) < 0)
454		return err;
455	if (nonblock)
456		rawmidi->mode |= SND_RAWMIDI_NONBLOCK;
457	else
458		rawmidi->mode &= ~SND_RAWMIDI_NONBLOCK;
459	return 0;
460}
461
462/**
463 * \brief get size of the snd_rawmidi_info_t structure in bytes
464 * \return size of the snd_rawmidi_info_t structure in bytes
465 */
466size_t snd_rawmidi_info_sizeof()
467{
468	return sizeof(snd_rawmidi_info_t);
469}
470
471/**
472 * \brief allocate a new snd_rawmidi_info_t structure
473 * \param info returned pointer
474 * \return 0 on success otherwise a negative error code if fails
475 *
476 * Allocates a new snd_rawmidi_params_t structure using the standard
477 * malloc C library function.
478 */
479int snd_rawmidi_info_malloc(snd_rawmidi_info_t **info)
480{
481	assert(info);
482	*info = calloc(1, sizeof(snd_rawmidi_info_t));
483	if (!*info)
484		return -ENOMEM;
485	return 0;
486}
487
488/**
489 * \brief frees the snd_rawmidi_info_t structure
490 * \param info pointer to the snd_rawmidi_info_t structure to free
491 *
492 * Frees the given snd_rawmidi_params_t structure using the standard
493 * free C library function.
494 */
495void snd_rawmidi_info_free(snd_rawmidi_info_t *info)
496{
497	assert(info);
498	free(info);
499}
500
501/**
502 * \brief copy one snd_rawmidi_info_t structure to another
503 * \param dst destination snd_rawmidi_info_t structure
504 * \param src source snd_rawmidi_info_t structure
505 */
506void snd_rawmidi_info_copy(snd_rawmidi_info_t *dst, const snd_rawmidi_info_t *src)
507{
508	assert(dst && src);
509	*dst = *src;
510}
511
512/**
513 * \brief get rawmidi device number
514 * \param info pointer to a snd_rawmidi_info_t structure
515 * \return rawmidi device number
516 */
517unsigned int snd_rawmidi_info_get_device(const snd_rawmidi_info_t *info)
518{
519	assert(info);
520	return info->device;
521}
522
523/**
524 * \brief get rawmidi subdevice number
525 * \param info pointer to a snd_rawmidi_info_t structure
526 * \return rawmidi subdevice number
527 */
528unsigned int snd_rawmidi_info_get_subdevice(const snd_rawmidi_info_t *info)
529{
530	assert(info);
531	return info->subdevice;
532}
533
534/**
535 * \brief get rawmidi stream identification
536 * \param info pointer to a snd_rawmidi_info_t structure
537 * \return rawmidi stream identification
538 */
539snd_rawmidi_stream_t snd_rawmidi_info_get_stream(const snd_rawmidi_info_t *info)
540{
541	assert(info);
542	return info->stream;
543}
544
545/**
546 * \brief get rawmidi card number
547 * \param info pointer to a snd_rawmidi_info_t structure
548 * \return rawmidi card number
549 */
550int snd_rawmidi_info_get_card(const snd_rawmidi_info_t *info)
551{
552	assert(info);
553	return info->card;
554}
555
556/**
557 * \brief get rawmidi flags
558 * \param info pointer to a snd_rawmidi_info_t structure
559 * \return rawmidi flags
560 */
561unsigned int snd_rawmidi_info_get_flags(const snd_rawmidi_info_t *info)
562{
563	assert(info);
564	return info->flags;
565}
566
567/**
568 * \brief get rawmidi hardware driver identifier
569 * \param info pointer to a snd_rawmidi_info_t structure
570 * \return rawmidi hardware driver identifier
571 */
572const char *snd_rawmidi_info_get_id(const snd_rawmidi_info_t *info)
573{
574	assert(info);
575	return (const char *)info->id;
576}
577
578/**
579 * \brief get rawmidi hardware driver name
580 * \param info pointer to a snd_rawmidi_info_t structure
581 * \return rawmidi hardware driver name
582 */
583const char *snd_rawmidi_info_get_name(const snd_rawmidi_info_t *info)
584{
585	assert(info);
586	return (const char *)info->name;
587}
588
589/**
590 * \brief get rawmidi subdevice name
591 * \param info pointer to a snd_rawmidi_info_t structure
592 * \return rawmidi subdevice name
593 */
594const char *snd_rawmidi_info_get_subdevice_name(const snd_rawmidi_info_t *info)
595{
596	assert(info);
597	return (const char *)info->subname;
598}
599
600/**
601 * \brief get rawmidi count of subdevices
602 * \param info pointer to a snd_rawmidi_info_t structure
603 * \return rawmidi count of subdevices
604 */
605unsigned int snd_rawmidi_info_get_subdevices_count(const snd_rawmidi_info_t *info)
606{
607	assert(info);
608	return info->subdevices_count;
609}
610
611/**
612 * \brief get rawmidi available count of subdevices
613 * \param info pointer to a snd_rawmidi_info_t structure
614 * \return rawmidi available count of subdevices
615 */
616unsigned int snd_rawmidi_info_get_subdevices_avail(const snd_rawmidi_info_t *info)
617{
618	assert(info);
619	return info->subdevices_avail;
620}
621
622/**
623 * \brief set rawmidi device number
624 * \param info pointer to a snd_rawmidi_info_t structure
625 * \param val device number
626 */
627void snd_rawmidi_info_set_device(snd_rawmidi_info_t *info, unsigned int val)
628{
629	assert(info);
630	info->device = val;
631}
632
633/**
634 * \brief set rawmidi subdevice number
635 * \param info pointer to a snd_rawmidi_info_t structure
636 * \param val subdevice number
637 */
638void snd_rawmidi_info_set_subdevice(snd_rawmidi_info_t *info, unsigned int val)
639{
640	assert(info);
641	info->subdevice = val;
642}
643
644/**
645 * \brief set rawmidi stream identifier
646 * \param info pointer to a snd_rawmidi_info_t structure
647 * \param val rawmidi stream identifier
648 */
649void snd_rawmidi_info_set_stream(snd_rawmidi_info_t *info, snd_rawmidi_stream_t val)
650{
651	assert(info);
652	info->stream = val;
653}
654
655/**
656 * \brief get information about RawMidi handle
657 * \param rawmidi RawMidi handle
658 * \param info pointer to a snd_rawmidi_info_t structure to be filled
659 * \return 0 on success otherwise a negative error code
660 */
661int snd_rawmidi_info(snd_rawmidi_t *rawmidi, snd_rawmidi_info_t * info)
662{
663	assert(rawmidi);
664	assert(info);
665	return rawmidi->ops->info(rawmidi, info);
666}
667
668/**
669 * \brief get size of the snd_rawmidi_params_t structure in bytes
670 * \return size of the snd_rawmidi_params_t structure in bytes
671 */
672size_t snd_rawmidi_params_sizeof()
673{
674	return sizeof(snd_rawmidi_params_t);
675}
676
677/**
678 * \brief allocate the snd_rawmidi_params_t structure
679 * \param params returned pointer
680 * \return 0 on success otherwise a negative error code if fails
681 *
682 * Allocates a new snd_rawmidi_params_t structure using the standard
683 * malloc C library function.
684 */
685int snd_rawmidi_params_malloc(snd_rawmidi_params_t **params)
686{
687	assert(params);
688	*params = calloc(1, sizeof(snd_rawmidi_params_t));
689	if (!*params)
690		return -ENOMEM;
691	return 0;
692}
693
694/**
695 * \brief frees the snd_rawmidi_params_t structure
696 * \param params pointer to the #snd_rawmidi_params_t structure to free
697 *
698 * Frees the given snd_rawmidi_params_t structure using the standard
699 * free C library function.
700 */
701void snd_rawmidi_params_free(snd_rawmidi_params_t *params)
702{
703	assert(params);
704	free(params);
705}
706
707/**
708 * \brief copy one snd_rawmidi_params_t structure to another
709 * \param dst destination snd_rawmidi_params_t structure
710 * \param src source snd_rawmidi_params_t structure
711 */
712void snd_rawmidi_params_copy(snd_rawmidi_params_t *dst, const snd_rawmidi_params_t *src)
713{
714	assert(dst && src);
715	*dst = *src;
716}
717
718/**
719 * \brief set rawmidi I/O ring buffer size
720 * \param rawmidi RawMidi handle
721 * \param params pointer to a snd_rawmidi_params_t structure
722 * \param val size in bytes
723 * \return 0 on success otherwise a negative error code
724 */
725#ifndef DOXYGEN
726int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
727#else
728int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
729#endif
730{
731	assert(rawmidi && params);
732	assert(val > params->avail_min);
733	params->buffer_size = val;
734	return 0;
735}
736
737/**
738 * \brief get rawmidi I/O ring buffer size
739 * \param params pointer to a snd_rawmidi_params_t structure
740 * \return size of rawmidi I/O ring buffer in bytes
741 */
742size_t snd_rawmidi_params_get_buffer_size(const snd_rawmidi_params_t *params)
743{
744	assert(params);
745	return params->buffer_size;
746}
747
748/**
749 * \brief set minimum available bytes in rawmidi I/O ring buffer for wakeup
750 * \param rawmidi RawMidi handle
751 * \param params pointer to a snd_rawmidi_params_t structure
752 * \param val desired value
753 */
754#ifndef DOXYGEN
755int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
756#else
757int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
758#endif
759{
760	assert(rawmidi && params);
761	assert(val < params->buffer_size);
762	params->avail_min = val;
763	return 0;
764}
765
766/**
767 * \brief get minimum available bytes in rawmidi I/O ring buffer for wakeup
768 * \param params pointer to snd_rawmidi_params_t structure
769 * \return minimum available bytes
770 */
771size_t snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t *params)
772{
773	assert(params);
774	return params->avail_min;
775}
776
777/**
778 * \brief set no-active-sensing action on snd_rawmidi_close()
779 * \param rawmidi RawMidi handle
780 * \param params pointer to snd_rawmidi_params_t structure
781 * \param val value: 0 = enable to send the active sensing message, 1 = disable
782 * \return 0 on success otherwise a negative error code
783 */
784#ifndef DOXYGEN
785int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, int val)
786#else
787int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, int val)
788#endif
789{
790	assert(rawmidi && params);
791	params->no_active_sensing = val;
792	return 0;
793}
794
795/**
796 * \brief get no-active-sensing action status
797 * \param params pointer to snd_rawmidi_params_t structure
798 * \return the current status (0 = enable, 1 = disable the active sensing message)
799 */
800int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params)
801{
802	assert(params);
803	return params->no_active_sensing;
804}
805
806/**
807 * \brief set parameters about rawmidi stream
808 * \param rawmidi RawMidi handle
809 * \param params pointer to a snd_rawmidi_params_t structure to be filled
810 * \return 0 on success otherwise a negative error code
811 */
812int snd_rawmidi_params(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t * params)
813{
814	int err;
815	assert(rawmidi);
816	assert(params);
817	err = rawmidi->ops->params(rawmidi, params);
818	if (err < 0)
819		return err;
820	rawmidi->buffer_size = params->buffer_size;
821	rawmidi->avail_min = params->avail_min;
822	rawmidi->no_active_sensing = params->no_active_sensing;
823	return 0;
824}
825
826/**
827 * \brief get current parameters about rawmidi stream
828 * \param rawmidi RawMidi handle
829 * \param params pointer to a snd_rawmidi_params_t structure to be filled
830 * \return 0 on success otherwise a negative error code
831 */
832int snd_rawmidi_params_current(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
833{
834	assert(rawmidi);
835	assert(params);
836	params->buffer_size = rawmidi->buffer_size;
837	params->avail_min = rawmidi->avail_min;
838	params->no_active_sensing = rawmidi->no_active_sensing;
839	return 0;
840}
841
842/**
843 * \brief get size of the snd_rawmidi_status_t structure in bytes
844 * \return size of the snd_rawmidi_status_t structure in bytes
845 */
846size_t snd_rawmidi_status_sizeof()
847{
848	return sizeof(snd_rawmidi_status_t);
849}
850
851/**
852 * \brief allocate the snd_rawmidi_status_t structure
853 * \param ptr returned pointer
854 * \return 0 on success otherwise a negative error code if fails
855 *
856 * Allocates a new snd_rawmidi_status_t structure using the standard
857 * malloc C library function.
858 */
859int snd_rawmidi_status_malloc(snd_rawmidi_status_t **ptr)
860{
861	assert(ptr);
862	*ptr = calloc(1, sizeof(snd_rawmidi_status_t));
863	if (!*ptr)
864		return -ENOMEM;
865	return 0;
866}
867
868/**
869 * \brief frees the snd_rawmidi_status_t structure
870 * \param status pointer to the snd_rawmidi_status_t structure to free
871 *
872 * Frees the given snd_rawmidi_status_t structure using the standard
873 * free C library function.
874 */
875void snd_rawmidi_status_free(snd_rawmidi_status_t *status)
876{
877	assert(status);
878	free(status);
879}
880
881/**
882 * \brief copy one snd_rawmidi_status_t structure to another
883 * \param dst destination snd_rawmidi_status_t structure
884 * \param src source snd_rawmidi_status_t structure
885 */
886void snd_rawmidi_status_copy(snd_rawmidi_status_t *dst, const snd_rawmidi_status_t *src)
887{
888	assert(dst && src);
889	*dst = *src;
890}
891
892/**
893 * \brief get the start timestamp
894 * \param status pointer to a snd_rawmidi_status_t structure
895 * \param tstamp returned timestamp value
896 */
897void snd_rawmidi_status_get_tstamp(const snd_rawmidi_status_t *status, snd_htimestamp_t *tstamp)
898{
899	assert(status && tstamp);
900	*tstamp = status->tstamp;
901}
902
903/**
904 * \brief get current available bytes in the rawmidi I/O ring buffer
905 * \param status pointer to a snd_rawmidi_status_t structure
906 * \return current available bytes in the rawmidi I/O ring buffer
907 */
908size_t snd_rawmidi_status_get_avail(const snd_rawmidi_status_t *status)
909{
910	assert(status);
911	return status->avail;
912}
913
914/**
915 * \brief get count of xruns
916 * \param status pointer to a snd_rawmidi_status_t structure
917 * \return count of xruns
918 */
919size_t snd_rawmidi_status_get_xruns(const snd_rawmidi_status_t *status)
920{
921	assert(status);
922	return status->xruns;
923}
924
925/**
926 * \brief get status of rawmidi stream
927 * \param rawmidi RawMidi handle
928 * \param status pointer to a snd_rawmidi_status_t structure to be filled
929 * \return 0 on success otherwise a negative error code
930 */
931int snd_rawmidi_status(snd_rawmidi_t *rawmidi, snd_rawmidi_status_t * status)
932{
933	assert(rawmidi);
934	assert(status);
935	return rawmidi->ops->status(rawmidi, status);
936}
937
938/**
939 * \brief drop all bytes in the rawmidi I/O ring buffer immediately
940 * \param rawmidi RawMidi handle
941 * \return 0 on success otherwise a negative error code
942 */
943int snd_rawmidi_drop(snd_rawmidi_t *rawmidi)
944{
945	assert(rawmidi);
946	return rawmidi->ops->drop(rawmidi);
947}
948
949/**
950 * \brief drain all bytes in the rawmidi I/O ring buffer
951 * \param rawmidi RawMidi handle
952 * \return 0 on success otherwise a negative error code
953 *
954 * Waits until all MIDI bytes are not drained (sent) to the
955 * hardware device.
956 */
957int snd_rawmidi_drain(snd_rawmidi_t *rawmidi)
958{
959	assert(rawmidi);
960	return rawmidi->ops->drain(rawmidi);
961}
962
963/**
964 * \brief write MIDI bytes to MIDI stream
965 * \param rawmidi RawMidi handle
966 * \param buffer buffer containing MIDI bytes
967 * \param size output buffer size in bytes
968 */
969ssize_t snd_rawmidi_write(snd_rawmidi_t *rawmidi, const void *buffer, size_t size)
970{
971	assert(rawmidi);
972	assert(rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT);
973	assert(buffer || size == 0);
974	return rawmidi->ops->write(rawmidi, buffer, size);
975}
976
977/**
978 * \brief read MIDI bytes from MIDI stream
979 * \param rawmidi RawMidi handle
980 * \param buffer buffer to store the input MIDI bytes
981 * \param size input buffer size in bytes
982 */
983ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
984{
985	assert(rawmidi);
986	assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
987	assert(buffer || size == 0);
988	return (rawmidi->ops->read)(rawmidi, buffer, size);
989}
990
991#ifndef DOC_HIDDEN
992int snd_rawmidi_conf_generic_id(const char *id)
993{
994	static const char ids[][8] = {
995		"comment",
996		"type",
997		"hint",
998	};
999	unsigned int k;
1000
1001	for (k = 0; k < sizeof ids / sizeof *ids; ++k) {
1002		if (strcmp(id, ids[k]) == 0)
1003			return 1;
1004	}
1005	return 0;
1006}
1007#endif
1008