OSDN Git Service

Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz
[android-x86/external-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 writting 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 = 0;
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                         goto _err;
205                 }
206                 snd_config_for_each(i, next, type_conf) {
207                         snd_config_t *n = snd_config_iterator_entry(i);
208                         const char *id;
209                         if (snd_config_get_id(n, &id) < 0)
210                                 continue;
211                         if (strcmp(id, "comment") == 0)
212                                 continue;
213                         if (strcmp(id, "lib") == 0) {
214                                 err = snd_config_get_string(n, &lib);
215                                 if (err < 0) {
216                                         SNDERR("Invalid type for %s", id);
217                                         goto _err;
218                                 }
219                                 continue;
220                         }
221                         if (strcmp(id, "open") == 0) {
222                                 err = snd_config_get_string(n, &open_name);
223                                 if (err < 0) {
224                                         SNDERR("Invalid type for %s", id);
225                                         goto _err;
226                                 }
227                                 continue;
228                         }
229                         SNDERR("Unknown field %s", id);
230                         err = -EINVAL;
231                         goto _err;
232                 }
233         }
234         if (!open_name) {
235                 open_name = buf;
236                 snprintf(buf, sizeof(buf), "_snd_rawmidi_%s_open", str);
237         }
238 #ifndef PIC
239         snd_rawmidi_open_symbols();
240 #endif
241         h = snd_dlopen(lib, RTLD_NOW);
242         if (h)
243                 open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION));
244         err = 0;
245         if (!h) {
246                 SNDERR("Cannot open shared library %s", lib);
247                 err = -ENOENT;
248         } else if (!open_func) {
249                 SNDERR("symbol %s is not defined inside %s", open_name, lib);
250                 snd_dlclose(h);
251                 err = -ENXIO;
252         }
253        _err:
254         if (type_conf)
255                 snd_config_delete(type_conf);
256         if (err >= 0)
257                 err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
258         if (err < 0)
259                 return err;
260         if (inputp) {
261                 (*inputp)->dl_handle = h; h = NULL;
262                 snd_rawmidi_params_default(*inputp, &params);
263                 err = snd_rawmidi_params(*inputp, &params);
264                 assert(err >= 0);
265         }
266         if (outputp) {
267                 (*outputp)->dl_handle = h;
268                 snd_rawmidi_params_default(*outputp, &params);
269                 err = snd_rawmidi_params(*outputp, &params);
270                 assert(err >= 0);
271         }
272         return 0;
273 }
274
275 static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
276                                      snd_config_t *root, const char *name, int mode)
277 {
278         int err;
279         snd_config_t *rawmidi_conf;
280         err = snd_config_search_definition(root, "rawmidi", name, &rawmidi_conf);
281         if (err < 0) {
282                 SNDERR("Unknown RawMidi %s", name);
283                 return err;
284         }
285         err = snd_rawmidi_open_conf(inputp, outputp, name, root, rawmidi_conf, mode);
286         snd_config_delete(rawmidi_conf);
287         return err;
288 }
289
290 /**
291  * \brief Opens a new connection to the RawMidi interface.
292  * \param inputp Returned input handle (NULL if not wanted)
293  * \param outputp Returned output handle (NULL if not wanted)
294  * \param name ASCII identifier of the RawMidi handle
295  * \param mode Open mode
296  * \return 0 on success otherwise a negative error code
297  *
298  * Opens a new connection to the RawMidi interface specified with
299  * an ASCII identifier and mode.
300  */
301 int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
302                      const char *name, int mode)
303 {
304         int err;
305         assert((inputp || outputp) && name);
306         err = snd_config_update();
307         if (err < 0)
308                 return err;
309         return snd_rawmidi_open_noupdate(inputp, outputp, snd_config, name, mode);
310 }
311
312 /**
313  * \brief Opens a new connection to the RawMidi interface using local configuration
314  * \param inputp Returned input handle (NULL if not wanted)
315  * \param outputp Returned output handle (NULL if not wanted)
316  * \param name ASCII identifier of the RawMidi handle
317  * \param mode Open mode
318  * \param lconf Local configuration
319  * \return 0 on success otherwise a negative error code
320  *
321  * Opens a new connection to the RawMidi interface specified with
322  * an ASCII identifier and mode.
323  */
324 int snd_rawmidi_open_lconf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
325                            const char *name, int mode, snd_config_t *lconf)
326 {
327         assert((inputp || outputp) && name && lconf);
328         return snd_rawmidi_open_noupdate(inputp, outputp, lconf, name, mode);
329 }
330
331 /**
332  * \brief close RawMidi handle
333  * \param rawmidi RawMidi handle
334  * \return 0 on success otherwise a negative error code
335  *
336  * Closes the specified RawMidi handle and frees all associated
337  * resources.
338  */
339 int snd_rawmidi_close(snd_rawmidi_t *rawmidi)
340 {
341         int err;
342         assert(rawmidi);
343         err = rawmidi->ops->close(rawmidi);
344         free(rawmidi->name);
345         if (rawmidi->dl_handle)
346                 snd_dlclose(rawmidi->dl_handle);
347         free(rawmidi);
348         return err;
349 }
350
351 /**
352  * \brief get identifier of RawMidi handle
353  * \param rawmidi a RawMidi handle
354  * \return ascii identifier of RawMidi handle
355  *
356  * Returns the ASCII identifier of given RawMidi handle. It's the same
357  * identifier specified in snd_rawmidi_open().
358  */
359 const char *snd_rawmidi_name(snd_rawmidi_t *rawmidi)
360 {
361         assert(rawmidi);
362         return rawmidi->name;
363 }
364
365 /**
366  * \brief get type of RawMidi handle
367  * \param rawmidi a RawMidi handle
368  * \return type of RawMidi handle
369  *
370  * Returns the type #snd_rawmidi_type_t of given RawMidi handle.
371  */
372 snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rawmidi)
373 {
374         assert(rawmidi);
375         return rawmidi->type;
376 }
377
378 /**
379  * \brief get stream (direction) of RawMidi handle
380  * \param rawmidi a RawMidi handle
381  * \return stream of RawMidi handle
382  *
383  * Returns the stream #snd_rawmidi_stream_t of given RawMidi handle.
384  */
385 snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi)
386 {
387         assert(rawmidi);
388         return rawmidi->stream;
389 }
390
391 /**
392  * \brief get count of poll descriptors for RawMidi handle
393  * \param rawmidi RawMidi handle
394  * \return count of poll descriptors
395  */
396 int snd_rawmidi_poll_descriptors_count(snd_rawmidi_t *rawmidi)
397 {
398         assert(rawmidi);
399         return 1;
400 }
401
402 /**
403  * \brief get poll descriptors
404  * \param rawmidi RawMidi handle
405  * \param pfds array of poll descriptors
406  * \param space space in the poll descriptor array
407  * \return count of filled descriptors
408  */
409 int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int space)
410 {
411         assert(rawmidi);
412         if (space >= 1) {
413                 pfds->fd = rawmidi->poll_fd;
414                 pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? (POLLOUT|POLLERR|POLLNVAL) : (POLLIN|POLLERR|POLLNVAL);
415                 return 1;
416         }
417         return 0;
418 }
419
420 /**
421  * \brief get returned events from poll descriptors
422  * \param rawmidi rawmidi RawMidi handle
423  * \param pfds array of poll descriptors
424  * \param nfds count of poll descriptors
425  * \param revents returned events
426  * \return zero if success, otherwise a negative error code
427  */
428 int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
429 {
430         assert(rawmidi && pfds && revents);
431         if (nfds == 1) {
432                 *revents = pfds->revents;
433                 return 0;
434         }
435         return -EINVAL;
436 }
437
438 /**
439  * \brief set nonblock mode
440  * \param rawmidi RawMidi handle
441  * \param nonblock 0 = block, 1 = nonblock mode
442  * \return 0 on success otherwise a negative error code
443  *
444  * The nonblock mode cannot be used when the stream is in
445  * #SND_RAWMIDI_APPEND state.
446  */
447 int snd_rawmidi_nonblock(snd_rawmidi_t *rawmidi, int nonblock)
448 {
449         int err;
450         assert(rawmidi);
451         assert(!(rawmidi->mode & SND_RAWMIDI_APPEND));
452         if ((err = rawmidi->ops->nonblock(rawmidi, nonblock)) < 0)
453                 return err;
454         if (nonblock)
455                 rawmidi->mode |= SND_RAWMIDI_NONBLOCK;
456         else
457                 rawmidi->mode &= ~SND_RAWMIDI_NONBLOCK;
458         return 0;
459 }
460
461 /**
462  * \brief get size of the snd_rawmidi_info_t structure in bytes
463  * \return size of the snd_rawmidi_info_t structure in bytes
464  */
465 size_t snd_rawmidi_info_sizeof()
466 {
467         return sizeof(snd_rawmidi_info_t);
468 }
469
470 /**
471  * \brief allocate a new snd_rawmidi_info_t structure
472  * \param info returned pointer
473  * \return 0 on success otherwise a negative error code if fails
474  *
475  * Allocates a new snd_rawmidi_params_t structure using the standard
476  * malloc C library function.
477  */
478 int snd_rawmidi_info_malloc(snd_rawmidi_info_t **info)
479 {
480         assert(info);
481         *info = calloc(1, sizeof(snd_rawmidi_info_t));
482         if (!*info)
483                 return -ENOMEM;
484         return 0;
485 }
486
487 /**
488  * \brief frees the snd_rawmidi_info_t structure
489  * \param info pointer to the snd_rawmidi_info_t structure to free
490  *
491  * Frees the given snd_rawmidi_params_t structure using the standard
492  * free C library function.
493  */
494 void snd_rawmidi_info_free(snd_rawmidi_info_t *info)
495 {
496         assert(info);
497         free(info);
498 }
499
500 /**
501  * \brief copy one snd_rawmidi_info_t structure to another
502  * \param dst destination snd_rawmidi_info_t structure
503  * \param src source snd_rawmidi_info_t structure
504  */
505 void snd_rawmidi_info_copy(snd_rawmidi_info_t *dst, const snd_rawmidi_info_t *src)
506 {
507         assert(dst && src);
508         *dst = *src;
509 }
510
511 /**
512  * \brief get rawmidi device number
513  * \param info pointer to a snd_rawmidi_info_t structure
514  * \return rawmidi device number
515  */
516 unsigned int snd_rawmidi_info_get_device(const snd_rawmidi_info_t *info)
517 {
518         assert(info);
519         return info->device;
520 }
521
522 /**
523  * \brief get rawmidi subdevice number
524  * \param info pointer to a snd_rawmidi_info_t structure
525  * \return rawmidi subdevice number
526  */
527 unsigned int snd_rawmidi_info_get_subdevice(const snd_rawmidi_info_t *info)
528 {
529         assert(info);
530         return info->subdevice;
531 }
532
533 /**
534  * \brief get rawmidi stream identification
535  * \param info pointer to a snd_rawmidi_info_t structure
536  * \return rawmidi stream identification
537  */
538 snd_rawmidi_stream_t snd_rawmidi_info_get_stream(const snd_rawmidi_info_t *info)
539 {
540         assert(info);
541         return info->stream;
542 }
543
544 /**
545  * \brief get rawmidi card number
546  * \param info pointer to a snd_rawmidi_info_t structure
547  * \return rawmidi card number
548  */
549 int snd_rawmidi_info_get_card(const snd_rawmidi_info_t *info)
550 {
551         assert(info);
552         return info->card;
553 }
554
555 /**
556  * \brief get rawmidi flags
557  * \param info pointer to a snd_rawmidi_info_t structure
558  * \return rawmidi flags
559  */
560 unsigned int snd_rawmidi_info_get_flags(const snd_rawmidi_info_t *info)
561 {
562         assert(info);
563         return info->flags;
564 }
565
566 /**
567  * \brief get rawmidi hardware driver identifier
568  * \param info pointer to a snd_rawmidi_info_t structure
569  * \return rawmidi hardware driver identifier
570  */
571 const char *snd_rawmidi_info_get_id(const snd_rawmidi_info_t *info)
572 {
573         assert(info);
574         return (const char *)info->id;
575 }
576
577 /**
578  * \brief get rawmidi hardware driver name
579  * \param info pointer to a snd_rawmidi_info_t structure
580  * \return rawmidi hardware driver name
581  */
582 const char *snd_rawmidi_info_get_name(const snd_rawmidi_info_t *info)
583 {
584         assert(info);
585         return (const char *)info->name;
586 }
587
588 /**
589  * \brief get rawmidi subdevice name
590  * \param info pointer to a snd_rawmidi_info_t structure
591  * \return rawmidi subdevice name
592  */
593 const char *snd_rawmidi_info_get_subdevice_name(const snd_rawmidi_info_t *info)
594 {
595         assert(info);
596         return (const char *)info->subname;
597 }
598
599 /**
600  * \brief get rawmidi count of subdevices
601  * \param info pointer to a snd_rawmidi_info_t structure
602  * \return rawmidi count of subdevices
603  */
604 unsigned int snd_rawmidi_info_get_subdevices_count(const snd_rawmidi_info_t *info)
605 {
606         assert(info);
607         return info->subdevices_count;
608 }
609
610 /**
611  * \brief get rawmidi available count of subdevices
612  * \param info pointer to a snd_rawmidi_info_t structure
613  * \return rawmidi available count of subdevices
614  */
615 unsigned int snd_rawmidi_info_get_subdevices_avail(const snd_rawmidi_info_t *info)
616 {
617         assert(info);
618         return info->subdevices_avail;
619 }
620
621 /**
622  * \brief set rawmidi device number
623  * \param info pointer to a snd_rawmidi_info_t structure
624  * \param val device number
625  */
626 void snd_rawmidi_info_set_device(snd_rawmidi_info_t *info, unsigned int val)
627 {
628         assert(info);
629         info->device = val;
630 }
631
632 /**
633  * \brief set rawmidi subdevice number
634  * \param info pointer to a snd_rawmidi_info_t structure
635  * \param val subdevice number
636  */
637 void snd_rawmidi_info_set_subdevice(snd_rawmidi_info_t *info, unsigned int val)
638 {
639         assert(info);
640         info->subdevice = val;
641 }
642
643 /**
644  * \brief set rawmidi stream identifier
645  * \param info pointer to a snd_rawmidi_info_t structure
646  * \param val rawmidi stream identifier
647  */
648 void snd_rawmidi_info_set_stream(snd_rawmidi_info_t *info, snd_rawmidi_stream_t val)
649 {
650         assert(info);
651         info->stream = val;
652 }
653
654 /**
655  * \brief get information about RawMidi handle
656  * \param rawmidi RawMidi handle
657  * \param info pointer to a snd_rawmidi_info_t structure to be filled
658  * \return 0 on success otherwise a negative error code
659  */
660 int snd_rawmidi_info(snd_rawmidi_t *rawmidi, snd_rawmidi_info_t * info)
661 {
662         assert(rawmidi);
663         assert(info);
664         return rawmidi->ops->info(rawmidi, info);
665 }
666
667 /**
668  * \brief get size of the snd_rawmidi_params_t structure in bytes
669  * \return size of the snd_rawmidi_params_t structure in bytes
670  */
671 size_t snd_rawmidi_params_sizeof()
672 {
673         return sizeof(snd_rawmidi_params_t);
674 }
675
676 /**
677  * \brief allocate the snd_rawmidi_params_t structure
678  * \param params returned pointer
679  * \return 0 on success otherwise a negative error code if fails
680  *
681  * Allocates a new snd_rawmidi_params_t structure using the standard
682  * malloc C library function.
683  */
684 int snd_rawmidi_params_malloc(snd_rawmidi_params_t **params)
685 {
686         assert(params);
687         *params = calloc(1, sizeof(snd_rawmidi_params_t));
688         if (!*params)
689                 return -ENOMEM;
690         return 0;
691 }
692
693 /**
694  * \brief frees the snd_rawmidi_params_t structure
695  * \param params pointer to the #snd_rawmidi_params_t structure to free
696  *
697  * Frees the given snd_rawmidi_params_t structure using the standard
698  * free C library function.
699  */
700 void snd_rawmidi_params_free(snd_rawmidi_params_t *params)
701 {
702         assert(params);
703         free(params);
704 }
705
706 /**
707  * \brief copy one snd_rawmidi_params_t structure to another
708  * \param dst destination snd_rawmidi_params_t structure
709  * \param src source snd_rawmidi_params_t structure
710  */
711 void snd_rawmidi_params_copy(snd_rawmidi_params_t *dst, const snd_rawmidi_params_t *src)
712 {
713         assert(dst && src);
714         *dst = *src;
715 }
716
717 /**
718  * \brief set rawmidi I/O ring buffer size
719  * \param rawmidi RawMidi handle
720  * \param params pointer to a snd_rawmidi_params_t structure
721  * \param val size in bytes
722  * \return 0 on success otherwise a negative error code
723  */
724 #ifndef DOXYGEN
725 int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
726 #else
727 int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
728 #endif
729 {
730         assert(rawmidi && params);
731         assert(val > params->avail_min);
732         params->buffer_size = val;
733         return 0;
734 }
735
736 /**
737  * \brief get rawmidi I/O ring buffer size
738  * \param params pointer to a snd_rawmidi_params_t structure
739  * \return size of rawmidi I/O ring buffer in bytes
740  */
741 size_t snd_rawmidi_params_get_buffer_size(const snd_rawmidi_params_t *params)
742 {
743         assert(params);
744         return params->buffer_size;
745 }
746
747 /**
748  * \brief set minimum available bytes in rawmidi I/O ring buffer for wakeup
749  * \param rawmidi RawMidi handle
750  * \param params pointer to a snd_rawmidi_params_t structure
751  * \param val desired value
752  */
753 #ifndef DOXYGEN
754 int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
755 #else
756 int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
757 #endif
758 {
759         assert(rawmidi && params);
760         assert(val < params->buffer_size);
761         params->avail_min = val;
762         return 0;
763 }
764
765 /**
766  * \brief get minimum available bytes in rawmidi I/O ring buffer for wakeup
767  * \param params pointer to snd_rawmidi_params_t structure
768  * \return minimum available bytes
769  */
770 size_t snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t *params)
771 {
772         assert(params);
773         return params->avail_min;
774 }
775
776 /**
777  * \brief set no-active-sensing action on snd_rawmidi_close()
778  * \param rawmidi RawMidi handle
779  * \param params pointer to snd_rawmidi_params_t structure
780  * \param val value: 0 = enable to send the active sensing message, 1 = disable
781  * \return 0 on success otherwise a negative error code
782  */
783 #ifndef DOXYGEN
784 int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, int val)
785 #else
786 int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, int val)
787 #endif
788 {
789         assert(rawmidi && params);
790         params->no_active_sensing = val;
791         return 0;
792 }
793
794 /**
795  * \brief get no-active-sensing action status
796  * \param params pointer to snd_rawmidi_params_t structure
797  * \return the current status (0 = enable, 1 = disable the active sensing message)
798  */
799 int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params)
800 {
801         assert(params);
802         return params->no_active_sensing;
803 }
804
805 /**
806  * \brief set parameters about rawmidi stream
807  * \param rawmidi RawMidi handle
808  * \param params pointer to a snd_rawmidi_params_t structure to be filled
809  * \return 0 on success otherwise a negative error code
810  */
811 int snd_rawmidi_params(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t * params)
812 {
813         int err;
814         assert(rawmidi);
815         assert(params);
816         err = rawmidi->ops->params(rawmidi, params);
817         if (err < 0)
818                 return err;
819         rawmidi->buffer_size = params->buffer_size;
820         rawmidi->avail_min = params->avail_min;
821         rawmidi->no_active_sensing = params->no_active_sensing;
822         return 0;
823 }
824
825 /**
826  * \brief get current parameters about rawmidi stream
827  * \param rawmidi RawMidi handle
828  * \param params pointer to a snd_rawmidi_params_t structure to be filled
829  * \return 0 on success otherwise a negative error code
830  */
831 int snd_rawmidi_params_current(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
832 {
833         assert(rawmidi);
834         assert(params);
835         params->buffer_size = rawmidi->buffer_size;
836         params->avail_min = rawmidi->avail_min;
837         params->no_active_sensing = rawmidi->no_active_sensing;
838         return 0;
839 }
840
841 /**
842  * \brief get size of the snd_rawmidi_status_t structure in bytes
843  * \return size of the snd_rawmidi_status_t structure in bytes
844  */
845 size_t snd_rawmidi_status_sizeof()
846 {
847         return sizeof(snd_rawmidi_status_t);
848 }
849
850 /**
851  * \brief allocate the snd_rawmidi_status_t structure
852  * \param ptr returned pointer
853  * \return 0 on success otherwise a negative error code if fails
854  *
855  * Allocates a new snd_rawmidi_status_t structure using the standard
856  * malloc C library function.
857  */
858 int snd_rawmidi_status_malloc(snd_rawmidi_status_t **ptr)
859 {
860         assert(ptr);
861         *ptr = calloc(1, sizeof(snd_rawmidi_status_t));
862         if (!*ptr)
863                 return -ENOMEM;
864         return 0;
865 }
866
867 /**
868  * \brief frees the snd_rawmidi_status_t structure
869  * \param status pointer to the snd_rawmidi_status_t structure to free
870  *
871  * Frees the given snd_rawmidi_status_t structure using the standard
872  * free C library function.
873  */
874 void snd_rawmidi_status_free(snd_rawmidi_status_t *status)
875 {
876         assert(status);
877         free(status);
878 }
879
880 /**
881  * \brief copy one snd_rawmidi_status_t structure to another
882  * \param dst destination snd_rawmidi_status_t structure
883  * \param src source snd_rawmidi_status_t structure
884  */
885 void snd_rawmidi_status_copy(snd_rawmidi_status_t *dst, const snd_rawmidi_status_t *src)
886 {
887         assert(dst && src);
888         *dst = *src;
889 }
890
891 /**
892  * \brief get the start timestamp
893  * \param status pointer to a snd_rawmidi_status_t structure
894  * \param tstamp returned timestamp value
895  */
896 void snd_rawmidi_status_get_tstamp(const snd_rawmidi_status_t *status, snd_htimestamp_t *tstamp)
897 {
898         assert(status && tstamp);
899         *tstamp = status->tstamp;
900 }
901
902 /**
903  * \brief get current available bytes in the rawmidi I/O ring buffer
904  * \param status pointer to a snd_rawmidi_status_t structure
905  * \return current available bytes in the rawmidi I/O ring buffer
906  */
907 size_t snd_rawmidi_status_get_avail(const snd_rawmidi_status_t *status)
908 {
909         assert(status);
910         return status->avail;
911 }
912
913 /**
914  * \brief get count of xruns
915  * \param status pointer to a snd_rawmidi_status_t structure
916  * \return count of xruns
917  */
918 size_t snd_rawmidi_status_get_xruns(const snd_rawmidi_status_t *status)
919 {
920         assert(status);
921         return status->xruns;
922 }
923
924 /**
925  * \brief get status of rawmidi stream
926  * \param rawmidi RawMidi handle
927  * \param status pointer to a snd_rawmidi_status_t structure to be filled
928  * \return 0 on success otherwise a negative error code
929  */
930 int snd_rawmidi_status(snd_rawmidi_t *rawmidi, snd_rawmidi_status_t * status)
931 {
932         assert(rawmidi);
933         assert(status);
934         return rawmidi->ops->status(rawmidi, status);
935 }
936
937 /**
938  * \brief drop all bytes in the rawmidi I/O ring buffer immediately
939  * \param rawmidi RawMidi handle
940  * \return 0 on success otherwise a negative error code
941  */
942 int snd_rawmidi_drop(snd_rawmidi_t *rawmidi)
943 {
944         assert(rawmidi);
945         return rawmidi->ops->drop(rawmidi);
946 }
947
948 /**
949  * \brief drain all bytes in the rawmidi I/O ring buffer
950  * \param rawmidi RawMidi handle
951  * \return 0 on success otherwise a negative error code
952  *
953  * Waits until all MIDI bytes are not drained (sent) to the
954  * hardware device.
955  */
956 int snd_rawmidi_drain(snd_rawmidi_t *rawmidi)
957 {
958         assert(rawmidi);
959         return rawmidi->ops->drain(rawmidi);
960 }
961
962 /**
963  * \brief write MIDI bytes to MIDI stream
964  * \param rawmidi RawMidi handle
965  * \param buffer buffer containing MIDI bytes
966  * \param size output buffer size in bytes
967  */
968 ssize_t snd_rawmidi_write(snd_rawmidi_t *rawmidi, const void *buffer, size_t size)
969 {
970         assert(rawmidi);
971         assert(rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT);
972         assert(buffer || size == 0);
973         return rawmidi->ops->write(rawmidi, buffer, size);
974 }
975
976 /**
977  * \brief read MIDI bytes from MIDI stream
978  * \param rawmidi RawMidi handle
979  * \param buffer buffer to store the input MIDI bytes
980  * \param size input buffer size in bytes
981  */
982 ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
983 {
984         assert(rawmidi);
985         assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
986         assert(buffer || size == 0);
987         return (rawmidi->ops->read)(rawmidi, buffer, size);
988 }
989
990 int snd_rawmidi_conf_generic_id(const char *id)
991 {
992         static const char *ids[] = {
993                 "comment",
994                 "type",
995                 "hint",
996         };
997         unsigned int k;
998
999         for (k = 0; k < sizeof ids / sizeof *ids; ++k) {
1000                 if (strcmp(id, ids[k]) == 0)
1001                         return 1;
1002         }
1003         return 0;
1004 }