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