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