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