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