tizen 2.3.1 release
[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 = 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                 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
276 static 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  */
302 int 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  */
325 int 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  */
340 int 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  */
360 const 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  */
373 snd_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  */
386 snd_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  */
397 int 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  */
410 int 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  */
429 int 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  */
448 int 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  */
466 size_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  */
479 int 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  */
495 void 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  */
506 void 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  */
517 unsigned 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  */
528 unsigned 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  */
539 snd_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  */
550 int 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  */
561 unsigned 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  */
572 const 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  */
583 const 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  */
594 const 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  */
605 unsigned 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  */
616 unsigned 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  */
627 void 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  */
638 void 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  */
649 void 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  */
661 int 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  */
672 size_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  */
685 int 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  */
701 void 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  */
712 void 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
726 int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
727 #else
728 int 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  */
742 size_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
755 int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
756 #else
757 int 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  */
771 size_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
785 int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, int val)
786 #else
787 int 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  */
800 int 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  */
812 int 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  */
832 int 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  */
846 size_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  */
859 int 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  */
875 void 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  */
886 void 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  */
897 void 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  */
908 size_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  */
919 size_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  */
931 int 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  */
943 int 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  */
957 int 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  */
969 ssize_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  */
983 ssize_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
992 int 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