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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 read_mode Read mode
122
123 Optionally, incoming rawmidi bytes can be marked with timestamps. The library hides
124 the kernel implementation (linux kernel 5.14+) and exports
125 the \link ::snd_rawmidi_tread() \endlink function which returns the
126 midi bytes marked with the identical timestamp in one iteration.
127
128 The timestamping is available only on input streams.
129
130 \section rawmidi_examples Examples
131
132 The full featured examples with cross-links:
133
134 \par Simple input/output test program
135 \link example_test_rawmidi example code \endlink
136 \par
137 This example shows open and read/write rawmidi operations.
138
139 */
140
141 /**
142 * \example ../test/rawmidi.c
143 * \anchor example_test_rawmidi
144 * Shows open and read/write rawmidi operations.
145 */
146
147 #include "rawmidi_local.h"
148 #include <stdio.h>
149 #include <stdlib.h>
150 #include <stdarg.h>
151 #include <unistd.h>
152 #include <string.h>
153
154 /**
155 * \brief setup the default parameters
156 * \param rawmidi RawMidi handle
157 * \param params pointer to a snd_rawmidi_params_t structure
158 * \return 0 on success otherwise a negative error code
159 */
snd_rawmidi_params_default(snd_rawmidi_t * rawmidi,snd_rawmidi_params_t * params)160 static int snd_rawmidi_params_default(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
161 {
162 assert(rawmidi);
163 assert(params);
164 params->buffer_size = page_size();
165 params->avail_min = 1;
166 params->no_active_sensing = 1;
167 params->mode = 0;
168 memset(params->reserved, 0, sizeof(params->reserved));
169 return 0;
170 }
171
snd_rawmidi_open_conf(snd_rawmidi_t ** inputp,snd_rawmidi_t ** outputp,const char * name,snd_config_t * rawmidi_root,snd_config_t * rawmidi_conf,int mode)172 static int snd_rawmidi_open_conf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
173 const char *name, snd_config_t *rawmidi_root,
174 snd_config_t *rawmidi_conf, int mode)
175 {
176 const char *str;
177 char buf[256];
178 int err;
179 snd_config_t *conf, *type_conf = NULL;
180 snd_config_iterator_t i, next;
181 snd_rawmidi_params_t params;
182 const char *id;
183 const char *lib = NULL, *open_name = NULL;
184 int (*open_func)(snd_rawmidi_t **, snd_rawmidi_t **,
185 const char *, snd_config_t *, snd_config_t *, int) = NULL;
186 #ifndef PIC
187 extern void *snd_rawmidi_open_symbols(void);
188 #endif
189 if (snd_config_get_type(rawmidi_conf) != SND_CONFIG_TYPE_COMPOUND) {
190 if (name)
191 SNDERR("Invalid type for RAWMIDI %s definition", name);
192 else
193 SNDERR("Invalid type for RAWMIDI definition");
194 return -EINVAL;
195 }
196 err = snd_config_search(rawmidi_conf, "type", &conf);
197 if (err < 0) {
198 SNDERR("type is not defined");
199 return err;
200 }
201 err = snd_config_get_id(conf, &id);
202 if (err < 0) {
203 SNDERR("unable to get id");
204 return err;
205 }
206 err = snd_config_get_string(conf, &str);
207 if (err < 0) {
208 SNDERR("Invalid type for %s", id);
209 return err;
210 }
211 err = snd_config_search_definition(rawmidi_root, "rawmidi_type", str, &type_conf);
212 if (err >= 0) {
213 if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
214 SNDERR("Invalid type for RAWMIDI type %s definition", str);
215 err = -EINVAL;
216 goto _err;
217 }
218 snd_config_for_each(i, next, type_conf) {
219 snd_config_t *n = snd_config_iterator_entry(i);
220 const char *id;
221 if (snd_config_get_id(n, &id) < 0)
222 continue;
223 if (strcmp(id, "comment") == 0)
224 continue;
225 if (strcmp(id, "lib") == 0) {
226 err = snd_config_get_string(n, &lib);
227 if (err < 0) {
228 SNDERR("Invalid type for %s", id);
229 goto _err;
230 }
231 continue;
232 }
233 if (strcmp(id, "open") == 0) {
234 err = snd_config_get_string(n, &open_name);
235 if (err < 0) {
236 SNDERR("Invalid type for %s", id);
237 goto _err;
238 }
239 continue;
240 }
241 SNDERR("Unknown field %s", id);
242 err = -EINVAL;
243 goto _err;
244 }
245 }
246 if (!open_name) {
247 open_name = buf;
248 snprintf(buf, sizeof(buf), "_snd_rawmidi_%s_open", str);
249 }
250 #ifndef PIC
251 snd_rawmidi_open_symbols();
252 #endif
253 open_func = snd_dlobj_cache_get2(lib, open_name,
254 SND_DLSYM_VERSION(SND_RAWMIDI_DLSYM_VERSION), 1);
255 if (!open_func) {
256 err = -ENXIO;
257 goto _err;
258 }
259 if (type_conf)
260 snd_config_delete(type_conf);
261 err = open_func(inputp, outputp, name, rawmidi_root, rawmidi_conf, mode);
262 if (err < 0)
263 goto _err;
264 if (inputp) {
265 (*inputp)->open_func = open_func;
266 snd_rawmidi_params_default(*inputp, ¶ms);
267 err = snd_rawmidi_params(*inputp, ¶ms);
268 assert(err >= 0);
269 }
270 if (outputp) {
271 (*outputp)->open_func = open_func;
272 snd_rawmidi_params_default(*outputp, ¶ms);
273 err = snd_rawmidi_params(*outputp, ¶ms);
274 assert(err >= 0);
275 }
276 return 0;
277
278 _err:
279 if (open_func)
280 snd_dlobj_cache_put(open_func);
281 if (type_conf)
282 snd_config_delete(type_conf);
283 return err;
284 }
285
snd_rawmidi_open_noupdate(snd_rawmidi_t ** inputp,snd_rawmidi_t ** outputp,snd_config_t * root,const char * name,int mode)286 static int snd_rawmidi_open_noupdate(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
287 snd_config_t *root, const char *name, int mode)
288 {
289 int err;
290 snd_config_t *rawmidi_conf;
291 err = snd_config_search_definition(root, "rawmidi", name, &rawmidi_conf);
292 if (err < 0) {
293 SNDERR("Unknown RawMidi %s", name);
294 return err;
295 }
296 err = snd_rawmidi_open_conf(inputp, outputp, name, root, rawmidi_conf, mode);
297 snd_config_delete(rawmidi_conf);
298 return err;
299 }
300
301 /**
302 * \brief Opens a new connection to the RawMidi interface.
303 * \param inputp Returned input handle (NULL if not wanted)
304 * \param outputp Returned output handle (NULL if not wanted)
305 * \param name ASCII identifier of the RawMidi handle
306 * \param mode Open mode
307 * \return 0 on success otherwise a negative error code
308 *
309 * Opens a new connection to the RawMidi interface specified with
310 * an ASCII identifier and mode.
311 */
snd_rawmidi_open(snd_rawmidi_t ** inputp,snd_rawmidi_t ** outputp,const char * name,int mode)312 int snd_rawmidi_open(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
313 const char *name, int mode)
314 {
315 snd_config_t *top;
316 int err;
317
318 assert((inputp || outputp) && name);
319 if (_snd_is_ucm_device(name)) {
320 name = uc_mgr_alibcfg_by_device(&top, name);
321 if (name == NULL)
322 return -ENODEV;
323 } else {
324 err = snd_config_update_ref(&top);
325 if (err < 0)
326 return err;
327 }
328 err = snd_rawmidi_open_noupdate(inputp, outputp, top, name, mode);
329 snd_config_unref(top);
330 return err;
331 }
332
333 /**
334 * \brief Opens a new connection to the RawMidi interface using local configuration
335 * \param inputp Returned input handle (NULL if not wanted)
336 * \param outputp Returned output handle (NULL if not wanted)
337 * \param name ASCII identifier of the RawMidi handle
338 * \param mode Open mode
339 * \param lconf Local configuration
340 * \return 0 on success otherwise a negative error code
341 *
342 * Opens a new connection to the RawMidi interface specified with
343 * an ASCII identifier and mode.
344 */
snd_rawmidi_open_lconf(snd_rawmidi_t ** inputp,snd_rawmidi_t ** outputp,const char * name,int mode,snd_config_t * lconf)345 int snd_rawmidi_open_lconf(snd_rawmidi_t **inputp, snd_rawmidi_t **outputp,
346 const char *name, int mode, snd_config_t *lconf)
347 {
348 assert((inputp || outputp) && name && lconf);
349 return snd_rawmidi_open_noupdate(inputp, outputp, lconf, name, mode);
350 }
351
352 /**
353 * \brief close RawMidi handle
354 * \param rawmidi RawMidi handle
355 * \return 0 on success otherwise a negative error code
356 *
357 * Closes the specified RawMidi handle and frees all associated
358 * resources.
359 */
snd_rawmidi_close(snd_rawmidi_t * rawmidi)360 int snd_rawmidi_close(snd_rawmidi_t *rawmidi)
361 {
362 int err;
363 assert(rawmidi);
364 err = rawmidi->ops->close(rawmidi);
365 free(rawmidi->name);
366 if (rawmidi->open_func)
367 snd_dlobj_cache_put(rawmidi->open_func);
368 free(rawmidi);
369 return err;
370 }
371
372 /**
373 * \brief get identifier of RawMidi handle
374 * \param rawmidi a RawMidi handle
375 * \return ascii identifier of RawMidi handle
376 *
377 * Returns the ASCII identifier of given RawMidi handle. It's the same
378 * identifier specified in snd_rawmidi_open().
379 */
snd_rawmidi_name(snd_rawmidi_t * rawmidi)380 const char *snd_rawmidi_name(snd_rawmidi_t *rawmidi)
381 {
382 assert(rawmidi);
383 return rawmidi->name;
384 }
385
386 /**
387 * \brief get type of RawMidi handle
388 * \param rawmidi a RawMidi handle
389 * \return type of RawMidi handle
390 *
391 * Returns the type #snd_rawmidi_type_t of given RawMidi handle.
392 */
snd_rawmidi_type(snd_rawmidi_t * rawmidi)393 snd_rawmidi_type_t snd_rawmidi_type(snd_rawmidi_t *rawmidi)
394 {
395 assert(rawmidi);
396 return rawmidi->type;
397 }
398
399 /**
400 * \brief get stream (direction) of RawMidi handle
401 * \param rawmidi a RawMidi handle
402 * \return stream of RawMidi handle
403 *
404 * Returns the stream #snd_rawmidi_stream_t of given RawMidi handle.
405 */
snd_rawmidi_stream(snd_rawmidi_t * rawmidi)406 snd_rawmidi_stream_t snd_rawmidi_stream(snd_rawmidi_t *rawmidi)
407 {
408 assert(rawmidi);
409 return rawmidi->stream;
410 }
411
412 /**
413 * \brief get count of poll descriptors for RawMidi handle
414 * \param rawmidi RawMidi handle
415 * \return count of poll descriptors
416 */
snd_rawmidi_poll_descriptors_count(snd_rawmidi_t * rawmidi)417 int snd_rawmidi_poll_descriptors_count(snd_rawmidi_t *rawmidi)
418 {
419 assert(rawmidi);
420 return 1;
421 }
422
423 /**
424 * \brief get poll descriptors
425 * \param rawmidi RawMidi handle
426 * \param pfds array of poll descriptors
427 * \param space space in the poll descriptor array
428 * \return count of filled descriptors
429 */
snd_rawmidi_poll_descriptors(snd_rawmidi_t * rawmidi,struct pollfd * pfds,unsigned int space)430 int snd_rawmidi_poll_descriptors(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int space)
431 {
432 assert(rawmidi);
433 if (space >= 1) {
434 pfds->fd = rawmidi->poll_fd;
435 pfds->events = rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT ? (POLLOUT|POLLERR|POLLNVAL) : (POLLIN|POLLERR|POLLNVAL);
436 return 1;
437 }
438 return 0;
439 }
440
441 /**
442 * \brief get returned events from poll descriptors
443 * \param rawmidi rawmidi RawMidi handle
444 * \param pfds array of poll descriptors
445 * \param nfds count of poll descriptors
446 * \param revents returned events
447 * \return zero if success, otherwise a negative error code
448 */
snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t * rawmidi,struct pollfd * pfds,unsigned int nfds,unsigned short * revents)449 int snd_rawmidi_poll_descriptors_revents(snd_rawmidi_t *rawmidi, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
450 {
451 assert(rawmidi && pfds && revents);
452 if (nfds == 1) {
453 *revents = pfds->revents;
454 return 0;
455 }
456 return -EINVAL;
457 }
458
459 /**
460 * \brief set nonblock mode
461 * \param rawmidi RawMidi handle
462 * \param nonblock 0 = block, 1 = nonblock mode
463 * \return 0 on success otherwise a negative error code
464 *
465 * The nonblock mode cannot be used when the stream is in
466 * #SND_RAWMIDI_APPEND state.
467 */
snd_rawmidi_nonblock(snd_rawmidi_t * rawmidi,int nonblock)468 int snd_rawmidi_nonblock(snd_rawmidi_t *rawmidi, int nonblock)
469 {
470 int err;
471 assert(rawmidi);
472 assert(!(rawmidi->mode & SND_RAWMIDI_APPEND));
473 if ((err = rawmidi->ops->nonblock(rawmidi, nonblock)) < 0)
474 return err;
475 if (nonblock)
476 rawmidi->mode |= SND_RAWMIDI_NONBLOCK;
477 else
478 rawmidi->mode &= ~SND_RAWMIDI_NONBLOCK;
479 return 0;
480 }
481
482 /**
483 * \brief get size of the snd_rawmidi_info_t structure in bytes
484 * \return size of the snd_rawmidi_info_t structure in bytes
485 */
snd_rawmidi_info_sizeof()486 size_t snd_rawmidi_info_sizeof()
487 {
488 return sizeof(snd_rawmidi_info_t);
489 }
490
491 /**
492 * \brief allocate a new snd_rawmidi_info_t structure
493 * \param info returned pointer
494 * \return 0 on success otherwise a negative error code if fails
495 *
496 * Allocates a new snd_rawmidi_params_t structure using the standard
497 * malloc C library function.
498 */
snd_rawmidi_info_malloc(snd_rawmidi_info_t ** info)499 int snd_rawmidi_info_malloc(snd_rawmidi_info_t **info)
500 {
501 assert(info);
502 *info = calloc(1, sizeof(snd_rawmidi_info_t));
503 if (!*info)
504 return -ENOMEM;
505 return 0;
506 }
507
508 /**
509 * \brief frees the snd_rawmidi_info_t structure
510 * \param info pointer to the snd_rawmidi_info_t structure to free
511 *
512 * Frees the given snd_rawmidi_params_t structure using the standard
513 * free C library function.
514 */
snd_rawmidi_info_free(snd_rawmidi_info_t * info)515 void snd_rawmidi_info_free(snd_rawmidi_info_t *info)
516 {
517 assert(info);
518 free(info);
519 }
520
521 /**
522 * \brief copy one snd_rawmidi_info_t structure to another
523 * \param dst destination snd_rawmidi_info_t structure
524 * \param src source snd_rawmidi_info_t structure
525 */
snd_rawmidi_info_copy(snd_rawmidi_info_t * dst,const snd_rawmidi_info_t * src)526 void snd_rawmidi_info_copy(snd_rawmidi_info_t *dst, const snd_rawmidi_info_t *src)
527 {
528 assert(dst && src);
529 *dst = *src;
530 }
531
532 /**
533 * \brief get rawmidi device number
534 * \param info pointer to a snd_rawmidi_info_t structure
535 * \return rawmidi device number
536 */
snd_rawmidi_info_get_device(const snd_rawmidi_info_t * info)537 unsigned int snd_rawmidi_info_get_device(const snd_rawmidi_info_t *info)
538 {
539 assert(info);
540 return info->device;
541 }
542
543 /**
544 * \brief get rawmidi subdevice number
545 * \param info pointer to a snd_rawmidi_info_t structure
546 * \return rawmidi subdevice number
547 */
snd_rawmidi_info_get_subdevice(const snd_rawmidi_info_t * info)548 unsigned int snd_rawmidi_info_get_subdevice(const snd_rawmidi_info_t *info)
549 {
550 assert(info);
551 return info->subdevice;
552 }
553
554 /**
555 * \brief get rawmidi stream identification
556 * \param info pointer to a snd_rawmidi_info_t structure
557 * \return rawmidi stream identification
558 */
snd_rawmidi_info_get_stream(const snd_rawmidi_info_t * info)559 snd_rawmidi_stream_t snd_rawmidi_info_get_stream(const snd_rawmidi_info_t *info)
560 {
561 assert(info);
562 return info->stream;
563 }
564
565 /**
566 * \brief get rawmidi card number
567 * \param info pointer to a snd_rawmidi_info_t structure
568 * \return rawmidi card number
569 */
snd_rawmidi_info_get_card(const snd_rawmidi_info_t * info)570 int snd_rawmidi_info_get_card(const snd_rawmidi_info_t *info)
571 {
572 assert(info);
573 return info->card;
574 }
575
576 /**
577 * \brief get rawmidi flags
578 * \param info pointer to a snd_rawmidi_info_t structure
579 * \return rawmidi flags
580 */
snd_rawmidi_info_get_flags(const snd_rawmidi_info_t * info)581 unsigned int snd_rawmidi_info_get_flags(const snd_rawmidi_info_t *info)
582 {
583 assert(info);
584 return info->flags;
585 }
586
587 /**
588 * \brief get rawmidi hardware driver identifier
589 * \param info pointer to a snd_rawmidi_info_t structure
590 * \return rawmidi hardware driver identifier
591 */
snd_rawmidi_info_get_id(const snd_rawmidi_info_t * info)592 const char *snd_rawmidi_info_get_id(const snd_rawmidi_info_t *info)
593 {
594 assert(info);
595 return (const char *)info->id;
596 }
597
598 /**
599 * \brief get rawmidi hardware driver name
600 * \param info pointer to a snd_rawmidi_info_t structure
601 * \return rawmidi hardware driver name
602 */
snd_rawmidi_info_get_name(const snd_rawmidi_info_t * info)603 const char *snd_rawmidi_info_get_name(const snd_rawmidi_info_t *info)
604 {
605 assert(info);
606 return (const char *)info->name;
607 }
608
609 /**
610 * \brief get rawmidi subdevice name
611 * \param info pointer to a snd_rawmidi_info_t structure
612 * \return rawmidi subdevice name
613 */
snd_rawmidi_info_get_subdevice_name(const snd_rawmidi_info_t * info)614 const char *snd_rawmidi_info_get_subdevice_name(const snd_rawmidi_info_t *info)
615 {
616 assert(info);
617 return (const char *)info->subname;
618 }
619
620 /**
621 * \brief get rawmidi count of subdevices
622 * \param info pointer to a snd_rawmidi_info_t structure
623 * \return rawmidi count of subdevices
624 */
snd_rawmidi_info_get_subdevices_count(const snd_rawmidi_info_t * info)625 unsigned int snd_rawmidi_info_get_subdevices_count(const snd_rawmidi_info_t *info)
626 {
627 assert(info);
628 return info->subdevices_count;
629 }
630
631 /**
632 * \brief get rawmidi available count of subdevices
633 * \param info pointer to a snd_rawmidi_info_t structure
634 * \return rawmidi available count of subdevices
635 */
snd_rawmidi_info_get_subdevices_avail(const snd_rawmidi_info_t * info)636 unsigned int snd_rawmidi_info_get_subdevices_avail(const snd_rawmidi_info_t *info)
637 {
638 assert(info);
639 return info->subdevices_avail;
640 }
641
642 /**
643 * \brief set rawmidi device number
644 * \param info pointer to a snd_rawmidi_info_t structure
645 * \param val device number
646 */
snd_rawmidi_info_set_device(snd_rawmidi_info_t * info,unsigned int val)647 void snd_rawmidi_info_set_device(snd_rawmidi_info_t *info, unsigned int val)
648 {
649 assert(info);
650 info->device = val;
651 }
652
653 /**
654 * \brief set rawmidi subdevice number
655 * \param info pointer to a snd_rawmidi_info_t structure
656 * \param val subdevice number
657 */
snd_rawmidi_info_set_subdevice(snd_rawmidi_info_t * info,unsigned int val)658 void snd_rawmidi_info_set_subdevice(snd_rawmidi_info_t *info, unsigned int val)
659 {
660 assert(info);
661 info->subdevice = val;
662 }
663
664 /**
665 * \brief set rawmidi stream identifier
666 * \param info pointer to a snd_rawmidi_info_t structure
667 * \param val rawmidi stream identifier
668 */
snd_rawmidi_info_set_stream(snd_rawmidi_info_t * info,snd_rawmidi_stream_t val)669 void snd_rawmidi_info_set_stream(snd_rawmidi_info_t *info, snd_rawmidi_stream_t val)
670 {
671 assert(info);
672 info->stream = val;
673 }
674
675 /**
676 * \brief get information about RawMidi handle
677 * \param rawmidi RawMidi handle
678 * \param info pointer to a snd_rawmidi_info_t structure to be filled
679 * \return 0 on success otherwise a negative error code
680 */
snd_rawmidi_info(snd_rawmidi_t * rawmidi,snd_rawmidi_info_t * info)681 int snd_rawmidi_info(snd_rawmidi_t *rawmidi, snd_rawmidi_info_t * info)
682 {
683 assert(rawmidi);
684 assert(info);
685 return rawmidi->ops->info(rawmidi, info);
686 }
687
688 /**
689 * \brief get size of the snd_rawmidi_params_t structure in bytes
690 * \return size of the snd_rawmidi_params_t structure in bytes
691 */
snd_rawmidi_params_sizeof()692 size_t snd_rawmidi_params_sizeof()
693 {
694 return sizeof(snd_rawmidi_params_t);
695 }
696
697 /**
698 * \brief allocate the snd_rawmidi_params_t structure
699 * \param params returned pointer
700 * \return 0 on success otherwise a negative error code if fails
701 *
702 * Allocates a new snd_rawmidi_params_t structure using the standard
703 * malloc C library function.
704 */
snd_rawmidi_params_malloc(snd_rawmidi_params_t ** params)705 int snd_rawmidi_params_malloc(snd_rawmidi_params_t **params)
706 {
707 assert(params);
708 *params = calloc(1, sizeof(snd_rawmidi_params_t));
709 if (!*params)
710 return -ENOMEM;
711 return 0;
712 }
713
714 /**
715 * \brief frees the snd_rawmidi_params_t structure
716 * \param params pointer to the #snd_rawmidi_params_t structure to free
717 *
718 * Frees the given snd_rawmidi_params_t structure using the standard
719 * free C library function.
720 */
snd_rawmidi_params_free(snd_rawmidi_params_t * params)721 void snd_rawmidi_params_free(snd_rawmidi_params_t *params)
722 {
723 assert(params);
724 free(params);
725 }
726
727 /**
728 * \brief copy one snd_rawmidi_params_t structure to another
729 * \param dst destination snd_rawmidi_params_t structure
730 * \param src source snd_rawmidi_params_t structure
731 */
snd_rawmidi_params_copy(snd_rawmidi_params_t * dst,const snd_rawmidi_params_t * src)732 void snd_rawmidi_params_copy(snd_rawmidi_params_t *dst, const snd_rawmidi_params_t *src)
733 {
734 assert(dst && src);
735 *dst = *src;
736 }
737
738 /**
739 * \brief set rawmidi I/O ring buffer size
740 * \param rawmidi RawMidi handle
741 * \param params pointer to a snd_rawmidi_params_t structure
742 * \param val size in bytes
743 * \return 0 on success otherwise a negative error code
744 */
745 #ifndef DOXYGEN
snd_rawmidi_params_set_buffer_size(snd_rawmidi_t * rawmidi ATTRIBUTE_UNUSED,snd_rawmidi_params_t * params,size_t val)746 int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
747 #else
748 int snd_rawmidi_params_set_buffer_size(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
749 #endif
750 {
751 assert(rawmidi && params);
752 assert(val > params->avail_min);
753 params->buffer_size = val;
754 return 0;
755 }
756
757 /**
758 * \brief get rawmidi I/O ring buffer size
759 * \param params pointer to a snd_rawmidi_params_t structure
760 * \return size of rawmidi I/O ring buffer in bytes
761 */
snd_rawmidi_params_get_buffer_size(const snd_rawmidi_params_t * params)762 size_t snd_rawmidi_params_get_buffer_size(const snd_rawmidi_params_t *params)
763 {
764 assert(params);
765 return params->buffer_size;
766 }
767
768 /**
769 * \brief set minimum available bytes in rawmidi I/O ring buffer for wakeup
770 * \param rawmidi RawMidi handle
771 * \param params pointer to a snd_rawmidi_params_t structure
772 * \param val desired value
773 */
774 #ifndef DOXYGEN
snd_rawmidi_params_set_avail_min(snd_rawmidi_t * rawmidi ATTRIBUTE_UNUSED,snd_rawmidi_params_t * params,size_t val)775 int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, size_t val)
776 #else
777 int snd_rawmidi_params_set_avail_min(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, size_t val)
778 #endif
779 {
780 assert(rawmidi && params);
781 assert(val < params->buffer_size);
782 params->avail_min = val;
783 return 0;
784 }
785
786 /**
787 * \brief get minimum available bytes in rawmidi I/O ring buffer for wakeup
788 * \param params pointer to snd_rawmidi_params_t structure
789 * \return minimum available bytes
790 */
snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t * params)791 size_t snd_rawmidi_params_get_avail_min(const snd_rawmidi_params_t *params)
792 {
793 assert(params);
794 return params->avail_min;
795 }
796
797 /**
798 * \brief set no-active-sensing action on snd_rawmidi_close()
799 * \param rawmidi RawMidi handle
800 * \param params pointer to snd_rawmidi_params_t structure
801 * \param val value: 0 = enable to send the active sensing message, 1 = disable
802 * \return 0 on success otherwise a negative error code
803 */
804 #ifndef DOXYGEN
snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t * rawmidi ATTRIBUTE_UNUSED,snd_rawmidi_params_t * params,int val)805 int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi ATTRIBUTE_UNUSED, snd_rawmidi_params_t *params, int val)
806 #else
807 int snd_rawmidi_params_set_no_active_sensing(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, int val)
808 #endif
809 {
810 assert(rawmidi && params);
811 params->no_active_sensing = val;
812 return 0;
813 }
814
815 /**
816 * \brief get no-active-sensing action status
817 * \param params pointer to snd_rawmidi_params_t structure
818 * \return the current status (0 = enable, 1 = disable the active sensing message)
819 */
snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t * params)820 int snd_rawmidi_params_get_no_active_sensing(const snd_rawmidi_params_t *params)
821 {
822 assert(params);
823 return params->no_active_sensing;
824 }
825
826 /**
827 * \brief set read mode
828 * \param rawmidi RawMidi handle
829 * \param params pointer to snd_rawmidi_params_t structure
830 * \param val type of read_mode
831 * \return 0 on success, otherwise a negative error code.
832 *
833 * Notable error codes:
834 * -EINVAL - "val" is invalid
835 * -ENOTSUP - mode is not supported
836 *
837 */
snd_rawmidi_params_set_read_mode(const snd_rawmidi_t * rawmidi,snd_rawmidi_params_t * params,snd_rawmidi_read_mode_t val)838 int snd_rawmidi_params_set_read_mode(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, snd_rawmidi_read_mode_t val)
839 {
840 unsigned int framing;
841 assert(rawmidi && params);
842
843 switch (val) {
844 case SND_RAWMIDI_READ_STANDARD:
845 framing = SNDRV_RAWMIDI_MODE_FRAMING_NONE;
846 break;
847 case SND_RAWMIDI_READ_TSTAMP:
848 if (rawmidi->ops->tread == NULL)
849 return -ENOTSUP;
850 framing = SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP;
851 break;
852 default:
853 return -EINVAL;
854 }
855
856 if (framing != SNDRV_RAWMIDI_MODE_FRAMING_NONE &&
857 (rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT))
858 return -ENOTSUP;
859 params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_FRAMING_MASK) | framing;
860 return 0;
861 }
862
863 /**
864 * \brief get current read mode
865 * \param params pointer to snd_rawmidi_params_t structure
866 * \return the current read mode (see enum)
867 */
snd_rawmidi_params_get_read_mode(const snd_rawmidi_params_t * params)868 snd_rawmidi_read_mode_t snd_rawmidi_params_get_read_mode(const snd_rawmidi_params_t *params)
869 {
870 unsigned int framing;
871
872 assert(params);
873 framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;
874 if (framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
875 return SND_RAWMIDI_READ_TSTAMP;
876 return SND_RAWMIDI_READ_STANDARD;
877 }
878
879 /**
880 * \brief sets clock type for tstamp type framing
881 * \param rawmidi RawMidi handle
882 * \param params pointer to snd_rawmidi_params_t structure
883 * \param val one of the SND_RAWMIDI_CLOCK_* constants
884 * \return 0 on success, otherwise a negative error code.
885 *
886 * Notable error codes:
887 * -EINVAL - "val" is invalid
888 * -ENOTSUP - Kernel is too old to support framing.
889 *
890 */
snd_rawmidi_params_set_clock_type(const snd_rawmidi_t * rawmidi,snd_rawmidi_params_t * params,snd_rawmidi_clock_t val)891 int snd_rawmidi_params_set_clock_type(const snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params, snd_rawmidi_clock_t val)
892 {
893 assert(rawmidi && params);
894 if (val > SNDRV_RAWMIDI_MODE_CLOCK_MASK >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT)
895 return -EINVAL;
896 if (val != SNDRV_RAWMIDI_MODE_CLOCK_NONE &&
897 (rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) || rawmidi->stream != SND_RAWMIDI_STREAM_INPUT))
898 return -ENOTSUP;
899 params->mode = (params->mode & ~SNDRV_RAWMIDI_MODE_CLOCK_MASK) + (val << SNDRV_RAWMIDI_MODE_CLOCK_SHIFT);
900 return 0;
901 }
902
903 /**
904 * \brief get current clock type (for tstamp type framing)
905 * \param params pointer to snd_rawmidi_params_t structure
906 * \return the current clock type (one of the SND_RAWMIDI_CLOCK_* constants)
907 */
snd_rawmidi_params_get_clock_type(const snd_rawmidi_params_t * params)908 snd_rawmidi_clock_t snd_rawmidi_params_get_clock_type(const snd_rawmidi_params_t *params)
909 {
910 assert(params);
911 return (params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK) >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT;
912 }
913
914
915 /**
916 * \brief set parameters about rawmidi stream
917 * \param rawmidi RawMidi handle
918 * \param params pointer to a snd_rawmidi_params_t structure to be filled
919 * \return 0 on success otherwise a negative error code
920 */
snd_rawmidi_params(snd_rawmidi_t * rawmidi,snd_rawmidi_params_t * params)921 int snd_rawmidi_params(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t * params)
922 {
923 int err;
924 assert(rawmidi);
925 assert(params);
926 err = rawmidi->ops->params(rawmidi, params);
927 if (err < 0)
928 return err;
929 rawmidi->buffer_size = params->buffer_size;
930 rawmidi->avail_min = params->avail_min;
931 rawmidi->no_active_sensing = params->no_active_sensing;
932 rawmidi->params_mode = rawmidi->version < SNDRV_PROTOCOL_VERSION(2, 0, 2) ? 0 : params->mode;
933 return 0;
934 }
935
936 /**
937 * \brief get current parameters about rawmidi stream
938 * \param rawmidi RawMidi handle
939 * \param params pointer to a snd_rawmidi_params_t structure to be filled
940 * \return 0 on success otherwise a negative error code
941 */
snd_rawmidi_params_current(snd_rawmidi_t * rawmidi,snd_rawmidi_params_t * params)942 int snd_rawmidi_params_current(snd_rawmidi_t *rawmidi, snd_rawmidi_params_t *params)
943 {
944 assert(rawmidi);
945 assert(params);
946 params->buffer_size = rawmidi->buffer_size;
947 params->avail_min = rawmidi->avail_min;
948 params->no_active_sensing = rawmidi->no_active_sensing;
949 params->mode = rawmidi->params_mode;
950 return 0;
951 }
952
953 /**
954 * \brief get size of the snd_rawmidi_status_t structure in bytes
955 * \return size of the snd_rawmidi_status_t structure in bytes
956 */
snd_rawmidi_status_sizeof()957 size_t snd_rawmidi_status_sizeof()
958 {
959 return sizeof(snd_rawmidi_status_t);
960 }
961
962 /**
963 * \brief allocate the snd_rawmidi_status_t structure
964 * \param ptr returned pointer
965 * \return 0 on success otherwise a negative error code if fails
966 *
967 * Allocates a new snd_rawmidi_status_t structure using the standard
968 * malloc C library function.
969 */
snd_rawmidi_status_malloc(snd_rawmidi_status_t ** ptr)970 int snd_rawmidi_status_malloc(snd_rawmidi_status_t **ptr)
971 {
972 assert(ptr);
973 *ptr = calloc(1, sizeof(snd_rawmidi_status_t));
974 if (!*ptr)
975 return -ENOMEM;
976 return 0;
977 }
978
979 /**
980 * \brief frees the snd_rawmidi_status_t structure
981 * \param status pointer to the snd_rawmidi_status_t structure to free
982 *
983 * Frees the given snd_rawmidi_status_t structure using the standard
984 * free C library function.
985 */
snd_rawmidi_status_free(snd_rawmidi_status_t * status)986 void snd_rawmidi_status_free(snd_rawmidi_status_t *status)
987 {
988 assert(status);
989 free(status);
990 }
991
992 /**
993 * \brief copy one snd_rawmidi_status_t structure to another
994 * \param dst destination snd_rawmidi_status_t structure
995 * \param src source snd_rawmidi_status_t structure
996 */
snd_rawmidi_status_copy(snd_rawmidi_status_t * dst,const snd_rawmidi_status_t * src)997 void snd_rawmidi_status_copy(snd_rawmidi_status_t *dst, const snd_rawmidi_status_t *src)
998 {
999 assert(dst && src);
1000 *dst = *src;
1001 }
1002
1003 /**
1004 * \brief get the start timestamp
1005 * \param status pointer to a snd_rawmidi_status_t structure
1006 * \param tstamp returned timestamp value
1007 */
snd_rawmidi_status_get_tstamp(const snd_rawmidi_status_t * status,snd_htimestamp_t * tstamp)1008 void snd_rawmidi_status_get_tstamp(const snd_rawmidi_status_t *status, snd_htimestamp_t *tstamp)
1009 {
1010 assert(status && tstamp);
1011 *tstamp = status->tstamp;
1012 }
1013
1014 /**
1015 * \brief get current available bytes in the rawmidi I/O ring buffer
1016 * \param status pointer to a snd_rawmidi_status_t structure
1017 * \return current available bytes in the rawmidi I/O ring buffer
1018 */
snd_rawmidi_status_get_avail(const snd_rawmidi_status_t * status)1019 size_t snd_rawmidi_status_get_avail(const snd_rawmidi_status_t *status)
1020 {
1021 assert(status);
1022 return status->avail;
1023 }
1024
1025 /**
1026 * \brief get count of xruns
1027 * \param status pointer to a snd_rawmidi_status_t structure
1028 * \return count of xruns
1029 */
snd_rawmidi_status_get_xruns(const snd_rawmidi_status_t * status)1030 size_t snd_rawmidi_status_get_xruns(const snd_rawmidi_status_t *status)
1031 {
1032 assert(status);
1033 return status->xruns;
1034 }
1035
1036 /**
1037 * \brief get status of rawmidi stream
1038 * \param rawmidi RawMidi handle
1039 * \param status pointer to a snd_rawmidi_status_t structure to be filled
1040 * \return 0 on success otherwise a negative error code
1041 */
snd_rawmidi_status(snd_rawmidi_t * rawmidi,snd_rawmidi_status_t * status)1042 int snd_rawmidi_status(snd_rawmidi_t *rawmidi, snd_rawmidi_status_t * status)
1043 {
1044 assert(rawmidi);
1045 assert(status);
1046 return rawmidi->ops->status(rawmidi, status);
1047 }
1048
1049 /**
1050 * \brief drop all bytes in the rawmidi I/O ring buffer immediately
1051 * \param rawmidi RawMidi handle
1052 * \return 0 on success otherwise a negative error code
1053 */
snd_rawmidi_drop(snd_rawmidi_t * rawmidi)1054 int snd_rawmidi_drop(snd_rawmidi_t *rawmidi)
1055 {
1056 assert(rawmidi);
1057 return rawmidi->ops->drop(rawmidi);
1058 }
1059
1060 /**
1061 * \brief drain all bytes in the rawmidi I/O ring buffer
1062 * \param rawmidi RawMidi handle
1063 * \return 0 on success otherwise a negative error code
1064 *
1065 * Waits until all MIDI bytes are not drained (sent) to the
1066 * hardware device.
1067 */
snd_rawmidi_drain(snd_rawmidi_t * rawmidi)1068 int snd_rawmidi_drain(snd_rawmidi_t *rawmidi)
1069 {
1070 assert(rawmidi);
1071 return rawmidi->ops->drain(rawmidi);
1072 }
1073
1074 /**
1075 * \brief write MIDI bytes to MIDI stream
1076 * \param rawmidi RawMidi handle
1077 * \param buffer buffer containing MIDI bytes
1078 * \param size output buffer size in bytes
1079 */
snd_rawmidi_write(snd_rawmidi_t * rawmidi,const void * buffer,size_t size)1080 ssize_t snd_rawmidi_write(snd_rawmidi_t *rawmidi, const void *buffer, size_t size)
1081 {
1082 assert(rawmidi);
1083 assert(rawmidi->stream == SND_RAWMIDI_STREAM_OUTPUT);
1084 assert(buffer || size == 0);
1085 return rawmidi->ops->write(rawmidi, buffer, size);
1086 }
1087
1088 /**
1089 * \brief read MIDI bytes from MIDI stream
1090 * \param rawmidi RawMidi handle
1091 * \param buffer buffer to store the input MIDI bytes
1092 * \param size input buffer size in bytes
1093 * \retval count of MIDI bytes otherwise a negative error code
1094 */
snd_rawmidi_read(snd_rawmidi_t * rawmidi,void * buffer,size_t size)1095 ssize_t snd_rawmidi_read(snd_rawmidi_t *rawmidi, void *buffer, size_t size)
1096 {
1097 assert(rawmidi);
1098 assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
1099 if ((rawmidi->params_mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
1100 size &= ~(sizeof(struct snd_rawmidi_framing_tstamp) - 1);
1101 assert(buffer || size == 0);
1102 return (rawmidi->ops->read)(rawmidi, buffer, size);
1103 }
1104
1105 /**
1106 * \brief read MIDI bytes from MIDI stream with timestamp
1107 * \param rawmidi RawMidi handle
1108 * \param[out] tstamp timestamp for the returned MIDI bytes
1109 * \param buffer buffer to store the input MIDI bytes
1110 * \param size input buffer size in bytes
1111 * \retval count of MIDI bytes otherwise a negative error code
1112 */
snd_rawmidi_tread(snd_rawmidi_t * rawmidi,struct timespec * tstamp,void * buffer,size_t size)1113 ssize_t snd_rawmidi_tread(snd_rawmidi_t *rawmidi, struct timespec *tstamp, void *buffer, size_t size)
1114 {
1115 assert(rawmidi);
1116 assert(rawmidi->stream == SND_RAWMIDI_STREAM_INPUT);
1117 assert(buffer || size == 0);
1118 if ((rawmidi->params_mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK) != SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)
1119 return -EINVAL;
1120 if (rawmidi->ops->tread == NULL)
1121 return -ENOTSUP;
1122 return (rawmidi->ops->tread)(rawmidi, tstamp, buffer, size);
1123 }
1124
1125 #ifndef DOXYGEN
1126 /*
1127 * internal API functions for obtaining UMP info from rawmidi instance
1128 */
_snd_rawmidi_ump_endpoint_info(snd_rawmidi_t * rmidi,void * info)1129 int _snd_rawmidi_ump_endpoint_info(snd_rawmidi_t *rmidi, void *info)
1130 {
1131 if (!rmidi->ops->ump_endpoint_info)
1132 return -ENXIO;
1133 return rmidi->ops->ump_endpoint_info(rmidi, info);
1134 }
1135
_snd_rawmidi_ump_block_info(snd_rawmidi_t * rmidi,void * info)1136 int _snd_rawmidi_ump_block_info(snd_rawmidi_t *rmidi, void *info)
1137 {
1138 if (!rmidi->ops->ump_block_info)
1139 return -ENXIO;
1140 return rmidi->ops->ump_block_info(rmidi, info);
1141 }
1142 #endif /* DOXYGEN */
1143