1 /**
2 * \file seq/seq.c
3 * \brief Sequencer Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Takashi Iwai <tiwai@suse.de>
7 * \date 2000-2001
8 *
9 * See \ref seq page for more details.
10 */
11
12 /*
13 * Sequencer Interface - main file
14 *
15 * This library is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as
17 * published by the Free Software Foundation; either version 2.1 of
18 * the License, or (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 *
29 */
30
31 /*! \page seq Sequencer interface
32
33 \section seq_general General
34
35 The ALSA sequencer interface is designed to deliver the MIDI-like
36 events between clients/ports.
37 A typical usage is the MIDI patch-bay. A MIDI application can be
38 connected arbitrarily from/to the other MIDI clients.
39 The routing between clients can be changed dynamically, so the
40 application can handle incoming or outgoing MIDI events regardless of
41 the devices or the application connections.
42
43 The sequencer core stuff only takes care of two things:
44 scheduling events and dispatching them to the destination at the
45 right time. All processing of MIDI events has to be done within the clients.
46 The event can be dispatched immediately without queueing, too.
47 The event scheduling can be done either on a MIDI tempo queue or
48 on a wallclock-time queue.
49
50 \section seq_client Client and Port
51
52 A <i>client</i> is created at each time #snd_seq_open() is called.
53 Later on, the attributes of client such as its name string can be changed
54 via #snd_seq_set_client_info(). There are helper functions for ease of use,
55 e.g. #snd_seq_set_client_name() and #snd_seq_set_client_event_filter().
56 A typical code would be like below:
57 \code
58 // create a new client
59 snd_seq_t *open_client()
60 {
61 snd_seq_t *handle;
62 int err;
63 err = snd_seq_open(&handle, "default", SND_SEQ_OPEN_INPUT, 0);
64 if (err < 0)
65 return NULL;
66 snd_seq_set_client_name(handle, "My Client");
67 return handle;
68 }
69 \endcode
70
71 You'll need to know the id number of the client eventually, for example,
72 when accessing to a certain port (see the section \ref seq_subs).
73 The client id can be obtained by #snd_seq_client_id() function.
74
75 A client can have one or more <i>ports</i> to communicate between other
76 clients. A port is corresponding to the MIDI port in the case of MIDI device,
77 but in general it is nothing but the access point between other clients.
78 Each port may have capability flags, which specify the read/write
79 accessibility and subscription permissions of the port.
80 For creation of a port, call #snd_seq_create_port()
81 with the appropriate port attribute specified in #snd_seq_port_info_t
82 record.
83
84 For creating a port for the normal use, there is a helper function
85 #snd_seq_create_simple_port(). An example with this function is like below.
86 \code
87 // create a new port; return the port id
88 // port will be writable and accept the write-subscription.
89 int my_new_port(snd_seq_t *handle)
90 {
91 return snd_seq_create_simple_port(handle, "my port",
92 SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
93 SND_SEQ_PORT_TYPE_MIDI_GENERIC);
94 }
95 \endcode
96
97 \section seq_memory Memory Pool
98
99 Each client owns memory pools on kernel space
100 for each input and output events.
101 Here, input and output mean
102 input (read) from other clients and output (write) to others, respectively.
103 Since memory pool of each client is independent from others,
104 it avoids such a situation that a client eats the whole events pool
105 and interfere other clients' response.
106
107 The all scheduled output events or input events from dispatcher are stored
108 on these pools until delivered to other clients or extracted to user space.
109 The size of input/output pools can be changed independently.
110 The output pool has also a room size, which is used to wake up the
111 thread when it falls into sleep in blocking write mode.
112
113 Note that ports on the same client share the same memory pool.
114 If a port fills the memory pool, another can't use it any more.
115 For avoiding this, multiple clients can be used.
116
117 For chancing the pool size and the condition, access to #snd_seq_client_pool_t
118 record. There are helper functions, #snd_seq_set_client_pool_output(),
119 #snd_seq_set_client_pool_output_room() and #snd_seq_set_client_pool_input(),
120 for setting the total output-pool size, the output-room size and the input-pool
121 size, respectively.
122
123 \section seq_subs Subscription
124
125 One of the new features in ALSA sequencer system is <i>subscription</i> of ports.
126 In general, subscription is a connection between two sequencer ports.
127 Even though an event can be delivered to a port without subscription
128 using an explicit destination address,
129 the subscription mechanism provides us more abstraction.
130
131 Suppose a MIDI input device which sends events from a keyboard.
132 The port associated with this device has READ capability - which means
133 this port is readable from other ports.
134 If a user program wants to capture events from keyboard and store them
135 as MIDI stream, this program must subscribe itself to the MIDI port
136 for read.
137 Then, a connection from MIDI input port to this program is established.
138 From this time, events from keyboard are automatically sent to this program.
139 Timestamps will be updated according to the subscribed queue.
140 \code
141 MIDI input port (keyboard)
142 |
143 V
144 ALSA sequencer - update timestamp
145 |
146 V
147 application port
148 \endcode
149
150 There is another subscription type for opposite direction:
151 Suppose a MIDI sequencer program which sends events to a MIDI output device.
152 In ALSA system, MIDI device is not opened until the associated MIDI port
153 is accessed. Thus, in order to activate MIDI device, we have to subscribe
154 to MIDI port for write.
155 After this connection is established, events will be properly sent
156 to MIDI output device.
157 \code
158 application port
159 |
160 V
161 ALSA sequencer - events are scheduled
162 |
163 V
164 MIDI output port (WaveTable etc.)
165 \endcode
166
167 From the viewpoint of subscription, the examples above are special cases.
168 Basically, subscription means the connection between two arbitrary ports.
169 For example, imagine a filter application which modifies
170 the MIDI events like program, velocity or chorus effects.
171 This application can accept arbitrary MIDI input
172 and send to arbitrary port, just like a Unix pipe application using
173 stdin and stdout files.
174 We can even connect several filter applications which work individually
175 in order to process the MIDI events.
176 Subscription can be used for this purpose.
177 The connection between ports can be done also by the "third" client.
178 Thus, filter applications have to manage
179 only input and output events regardless of receiver/sender addresses.
180 \code
181 sequencer port #1
182 |
183 V
184 ALSA sequencer (scheduled or real-time)
185 |
186 V
187 sequencer port #2
188 \endcode
189
190 For the detail about subscription, see the section \ref seq_subs_more.
191
192 \section seq_events Sequencer Events
193
194 Messaging between clients is performed by sending events from one client to
195 another. These events contain high-level MIDI oriented messages or sequencer
196 specific messages.
197
198 All the sequencer events are stored in a sequencer event record,
199 #snd_seq_event_t type.
200 Application can send and receive these event records to/from other
201 clients via sequencer.
202 An event has several storage types according to its usage.
203 For example, a SYSEX message is stored on the variable length event,
204 and a large synth sample data is delivered using a user-space data pointer.
205
206
207 \subsection seq_ev_struct Structure of an event
208
209 An event consists of the following items:
210 <ul>
211 <li>The type of the event
212 <li>Event flags. It describes various conditions:
213 <ul>
214 <li>time stamp; "real time" / "song ticks"
215 <li>time mode; "absolute" / "relative to current time"
216 </ul>
217 <li>Timestamp of the event.
218 <li>Scheduling queue id.
219 <li>Source address of the event, given by the combination
220 of client id and port id numbers.
221 <li>Destination address of the event.
222 <li>The actual event data. (up to 12 bytes)
223 </ul>
224
225 The actual record is shown in #snd_seq_event_t.
226 The type field contains the type of the event
227 (1 byte).
228 The flags field consists of bit flags which
229 describe several conditions of the event (1 byte).
230 It includes the time-stamp mode, data storage type, and scheduling priority.
231 The tag field is an arbitrary tag.
232 This tag can used for removing a distinct event from the event queue
233 via #snd_seq_remove_events().
234 The queue field is the queue id for scheduling.
235 The source and dest fields are source and destination addresses.
236 The data field is a union of event data.
237
238 \subsection seq_ev_queue Scheduling queue
239
240 An event can be delivered either on scheduled or direct dispatch mode.
241 On the scheduling mode, an event is once stored on the priority queue
242 and delivered later (or even immediately) to the destination,
243 whereas on the direct dispatch mode, an event is passed to the destination
244 without any queue.
245
246 For a scheduled delivery, a queue to process the event must exist.
247 Usually, a client creates its own queue by
248 #snd_seq_alloc_queue() function.
249 Alternatively, a queue may be shared among several clients.
250 For scheduling an event on the specified queue,
251 a client needs to fill queue field
252 with the preferred queue id.
253
254 Meanwhile, for dispatching an event directly, just
255 use #SND_SEQ_QUEUE_DIRECT as the target queue id.
256 A macro #snd_seq_ev_set_direct() is provided for ease
257 and compatibility.
258
259 Note that scheduling at the current or earlier time is different
260 from the direct dispatch mode even though the event is delivered immediately.
261 On the former scheme, an event is once stored on priority queue, then
262 delivered actually. Thus, it acquires a space from memory pool.
263 On the other hand, the latter is passed without using memory pool.
264 Although the direct dispatched event needs less memory, it means also
265 that the event cannot be resent if the destination is unable to receive it
266 momentarily.
267
268 \subsection seq_ev_time Time stamp
269
270 The timestamp of the event can either specified in
271 <i>real time</i> or in <i>song ticks</i>.
272 The former means the wallclock time while the latter corresponds to
273 the MIDI ticks.
274 Which format is used is determined by the event flags.
275
276 The resolution of real-time value is in nano second.
277 Since 64 bit length is required for the actual time calculation,
278 it is represented by
279 a structure of pair of second and nano second
280 defined as #snd_seq_real_time_t type.
281 The song tick is defined simply as a 32 bit integer,
282 defined as #snd_seq_tick_time_t type.
283 The time stored in an event record is a union of these two different
284 time values.
285
286 Note that the time format used for real time events is very similar to
287 timeval struct used for Unix system time.
288 The absurd resolution of the timestamps allows us to perform very accurate
289 conversions between songposition and real time. Round-off errors can be
290 neglected.
291
292 If a timestamp with a
293 <i>relative</i> timestamp is delivered to ALSA, the
294 specified timestamp will be used as an offset to the current time of the
295 queue the event is sent into.
296 An <i>absolute</i> timestamp is on the contrary the time
297 counted from the moment when the queue started.
298
299 An client that relies on these relative timestamps is the MIDI input port.
300 As each sequencer queue has it's own clock the only way to deliver events at
301 the right time is by using the relative timestamp format. When the event
302 arrives at the queue it is normalized to absolute format.
303
304 The timestamp format is specified in the flag bitfield masked by
305 #SND_SEQ_TIME_STAMP_MASK.
306 To schedule the event in a real-time queue or in a tick queue,
307 macros #snd_seq_ev_schedule_real() and
308 #snd_seq_ev_schedule_tick() are provided, respectively.
309
310 \subsection seq_ev_addr Source and destination addresses
311
312 To identify the source and destination of an event, the addressing field
313 contains a combination of client id and port id numbers, defined as
314 #snd_seq_addr_t type.
315 When an event is passed to sequencer from a client, sequencer fills
316 source.client field
317 with the sender's id automatically.
318 It is the responsibility of sender client to
319 fill the port id of source.port and
320 both client and port of dest field.
321
322 If an existing address is set to the destination,
323 the event is simply delivered to it.
324 When #SND_SEQ_ADDRESS_SUBSCRIBERS is set to the destination client id,
325 the event is delivered to all the clients connected to the source port.
326
327
328 A sequencer core has two pre-defined system ports on the system client
329 #SND_SEQ_CLIENT_SYSTEM: #SND_SEQ_PORT_SYSTEM_TIMER and #SND_SEQ_PORT_SYSTEM_ANNOUNCE.
330 The #SND_SEQ_PORT_SYSTEM_TIMER is the system timer port,
331 and #SND_SEQ_PORT_SYSTEM_ANNOUNCE is the system
332 announce port.
333 In order to control a queue from a client, client should send a
334 queue-control event
335 like start, stop and continue queue, change tempo, etc.
336 to the system timer port.
337 Then the sequencer system handles the queue according to the received event.
338 This port supports subscription. The received timer events are
339 broadcasted to all subscribed clients.
340
341 The latter port does not receive messages but supports subscription.
342 When each client or port is attached, detached or modified,
343 an announcement is sent to subscribers from this port.
344
345 \subsection seq_ev_data Data storage type
346
347 Some events like SYSEX message, however, need larger data space
348 than the standard data.
349 For such events, ALSA sequencer provides several different data storage types.
350 The data type is specified in the flag bits masked by #SND_SEQ_EVENT_LENGTH_MASK.
351 The following data types are available:
352
353 \par Fixed size data
354 Normal events stores their parameters on
355 data field (12 byte).
356 The flag-bit type is #SND_SEQ_EVENT_LENGTH_FIXED.
357 A macro #snd_seq_ev_set_fixed() is provided to set this type.
358
359 \par Variable length data
360 SYSEX or a returned error use this type.
361 The actual data is stored on an extra allocated space.
362 On sequencer kernel, the whole extra-data is duplicated, so that the event
363 can be scheduled on queue.
364 The data contains only the length and the
365 pointer of extra-data.
366 The flag-bit type is #SND_SEQ_EVENT_LENGTH_VARIABLE.
367 A macro #snd_seq_ev_set_variable() is provided to set this type.
368
369 \par User-space data
370 This type refers also an extra data space like variable length data,
371 but the extra-data is not duplicated but
372 but referred as a user-space data on kernel,
373 so that it reduces the time and resource for transferring
374 large bulk of data like synth sample wave.
375 This data type, however, can be used only for direct dispatch mode,
376 and supposed to be used only for a special purpose like a bulk data
377 transfer.
378 The data length and pointer are stored also in
379 data.ext field as well as variable length data.
380 The flag-bit type is #SND_SEQ_EVENT_LENGTH_VARUSR.
381 A macro #snd_seq_ev_set_varusr() is provided to set this type.
382
383 \subsection seq_ev_sched Scheduling priority
384
385 There are two priorities for scheduling:
386 \par Normal priority
387 If an event with the same scheduling time is already present on the queue,
388 the new event is appended to the older.
389 \par High priority
390 If an event with the same scheduling time is already present on the queue,
391 the new event is inserted before others.
392
393 The scheduling priority is set in the flag bitfeld masked by #SND_SEQ_PRIORITY_MASK.
394 A macro #snd_seq_ev_set_priority() is provided to set the mode type.
395
396 \section seq_queue Event Queues
397 \subsection seq_ev_control Creation of a queue
398
399 Creating a queue is done usually by calling #snd_seq_alloc_queue.
400 You can create a queue with a certain name by #snd_seq_alloc_named_queue(), too.
401 \code
402 // create a queue and return its id
403 int my_queue(snd_seq_t *handle)
404 {
405 return snd_seq_alloc_named_queue(handle, "my queue");
406 }
407 \endcode
408 These functions are the wrapper to the function #snd_seq_create_queue().
409 For releasing the allocated queue, call #snd_seq_free_queue() with the
410 obtained queue id.
411
412 Once when a queue is created, the two queues are associated to that
413 queue record in fact: one is the realtime queue and another is the
414 tick queue. These two queues are bound together to work
415 synchronously. Hence, when you schedule an event, you have to choose
416 which queue type is used as described in the section \ref
417 seq_ev_time.
418
419 \subsection seq_ev_tempo Setting queue tempo
420
421 The tempo (or the speed) of the scheduling queue is variable.
422 In the case of <i>tick</i> queue, the tempo is controlled
423 in the manner of MIDI. There are two parameters to define the
424 actual tempo, PPQ (pulse per quarter note) and MIDI tempo.
425 The former defines the base resolution of the ticks, while
426 the latter defines the beat tempo in microseconds.
427 As default, 96 PPQ and 120 BPM are used, respectively.
428 That is, the tempo is set to 500000 (= 60 * 1000000 / 120).
429 Note that PPQ cannot be changed while the queue is running.
430 It must be set before the queue is started.
431
432 On the other hand, in the case of <i>realtime</i> queue, the
433 time resolution is fixed to nanoseconds. There is, however,
434 a parameter to change the speed of this queue, called <i>skew</i>.
435 You can make the queue faster or slower by setting the skew value
436 bigger or smaller. In the API, the skew is defined by two values,
437 the skew base and the skew value. The actual skew is the fraction
438 of them, <i>value/base</i>. As default, the skew base is set to 16bit
439 (0x10000) and the skew value is the identical, so that the queue is
440 processed as well as in the real world.
441
442 When the tempo of realtime queue is changed, the tempo of
443 the associated tick queue is changed together, too.
444 That's the reason why two queues are created always.
445 This feature can be used to synchronize the event queue with
446 the external synchronization source like SMPTE. In such a case,
447 the realtime queue is skewed to match with the external source,
448 so that both the realtime timestamp and the MIDI timestamp are
449 synchronized.
450
451 For setting these tempo parameters, use #snd_seq_queue_tempo_t record.
452 For example, to set the tempo of the queue <code>q</code> to
453 48 PPQ, 60 BPM,
454 \code
455 void set_tempo(snd_seq_t *handle, int queue)
456 {
457 snd_seq_queue_tempo_t *tempo;
458 snd_seq_queue_tempo_alloca(&tempo);
459 snd_seq_queue_tempo_set_tempo(tempo, 1000000); // 60 BPM
460 snd_seq_queue_tempo_set_ppq(tempo, 48); // 48 PPQ
461 snd_seq_set_queue_tempo(handle, queue, tempo);
462 }
463 \endcode
464
465 For changing the (running) queue's tempo on the fly, you can either
466 set the tempo via #snd_seq_set_queue_tempo() or send a MIDI tempo event
467 to the system timer port. For example,
468 \code
469 int change_tempo(snd_seq_t *handle, int q, unsigned int tempo)
470 {
471 snd_seq_event_t ev;
472 snd_seq_ev_clear(&ev);
473 ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
474 ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
475 ev.source.client = my_client_id;
476 ev.source.port = my_port_id;
477 ev.queue = SND_SEQ_QUEUE_DIRECT; // no scheduling
478 ev.data.queue.queue = q; // affected queue id
479 ev.data.queue.value = tempo; // new tempo in microsec.
480 return snd_seq_event_output(handle, &ev);
481 }
482 \endcode
483 There is a helper function to do this easily,
484 #snd_seq_change_queue_tempo().
485 Set NULL to the last argument, if you don't need any
486 special settings.
487
488 In the above example, the tempo is changed immediately after
489 the buffer is flushed by #snd_seq_drain_output() call.
490 You can schedule the event in a certain queue so that the tempo
491 change happens at the scheduled time, too.
492
493 \subsection seq_ev_start Starting and stopping a queue
494
495 To start, stop, or continue a queue, you need to send a queue-control
496 event to the system timer port as well. There are helper functions,
497 #snd_seq_start_queue(), #snd_seq_stop_queue() and
498 #snd_seq_continue_queue().
499 Note that if the last argument of these functions is NULL, the
500 event is sent (i.e. operated) immediately after the buffer flush.
501 If you want to schedule the event at the certain time, set up
502 the event record and provide the pointer of that event record as the
503 argument.
504
505 Only calling these functions doesn't deliver the event to the
506 sequencer core but only put to the output buffer. You'll need to
507 call #snd_seq_drain_output() eventually.
508
509
510 \section seq_subs_more More inside the subscription
511
512 \subsection seq_subs_perm Permissions
513
514 Each ALSA port can have capability flags.
515 The most basic capability flags are
516 #SND_SEQ_PORT_CAP_READ and #SND_SEQ_PORT_CAP_WRITE.
517 The former means that the port allows to send events to other ports,
518 whereas the latter capability means
519 that the port allows to receive events from other ports.
520 You may have noticed that meanings of \c READ and \c WRITE
521 are permissions of the port from the viewpoint of other ports.
522
523 For allowing subscription from/to other clients, another capability
524 flags must be set together with read/write capabilities above.
525 For allowing read and write subscriptions,
526 #SND_SEQ_PORT_CAP_SUBS_READ and
527 #SND_SEQ_PORT_CAP_SUBS_WRITE are used,
528 respectively.
529 For example, the port with MIDI input device always has
530 #SND_SEQ_PORT_CAP_SUBS_READ capability,
531 and the port with MIDI output device always has
532 #SND_SEQ_PORT_CAP_SUBS_WRITE capability together with
533 #SND_SEQ_PORT_CAP_READ and #SND_SEQ_PORT_CAP_WRITE capabilities,
534 respectively.
535 Obviously, these flags have no influence
536 if \c READ or \c WRITE> capability is not set.
537
538 Note that these flags are not necessary if the client subscribes itself
539 to the specified port.
540 For example, when a port makes READ subscription
541 to MIDI input port, this port must have #SND_SEQ_PORT_CAP_WRITE capability,
542 but no #SND_SEQ_PORT_CAP_SUBS_WRITE capability is required.
543 Only MIDI input port must have #SND_SEQ_PORT_CAP_SUBS_READ capability.
544
545 As default, the connection of ports via the third client is always allowed
546 if proper read and write (subscription) capabilities are set both to the
547 source and destination ports.
548 For prohibiting this behavior, set a capability
549 #SND_SEQ_PORT_CAP_NO_EXPORT to the port.
550 If this flag is set, subscription must be done by sender or receiver
551 client itself.
552 It is useful to avoid unexpected disconnection.
553 The ports which won't accept subscription should have this capability
554 for better security.
555
556 \subsection seq_subs_handle Subscription handlers
557
558 In ALSA library, subscription is done via
559 #snd_seq_subscribe_port() function.
560 It takes the argument of #snd_seq_port_subscribe_t record pointer.
561 Suppose that you have a client which will receive data from
562 a MIDI input device. The source and destination addresses
563 are like the below;
564 \code
565 snd_seq_addr_t sender, dest;
566 sender.client = MIDI_input_client;
567 sender.port = MIDI_input_port;
568 dest.client = my_client;
569 dest.port = my_port;
570 \endcode
571 To set these values as the connection call like this.
572 \code
573 snd_seq_port_subscribe_t *subs;
574 snd_seq_port_subscribe_alloca(&subs);
575 snd_seq_port_subscribe_set_sender(subs, &sender);
576 snd_seq_port_subscribe_set_dest(subs, &dest);
577 snd_seq_subscribe_port(handle, subs);
578 \endcode
579
580 When the connection should be exclusively done only between
581 a certain pair, set <i>exclusive</i> attribute to the subscription
582 record before calling #snd_seq_subscribe_port.
583 \code
584 snd_seq_port_subscribe_set_exclusive(subs, 1);
585 \endcode
586 The succeeding subscriptions will be refused.
587
588 The timestamp can be updated independently on each connection.
589 When set up, the timestamp of incoming queue to the destination port
590 is updated automatically to the time of the specified queue.
591 \code
592 snd_seq_port_subscribe_set_time_update(subs, 1);
593 snd_seq_port_subscribe_set_queue(subs, q);
594 \endcode
595 For getting the wallclock time (sec/nsec pair), set <i>real</i> attribute:
596 \code
597 snd_seq_port_subscribe_set_time_real(subs, 1);
598 \endcode
599 Otherwise, the timestamp is stored in tick unit.
600 This feature is useful when receiving events from MIDI input device.
601 The event time is automatically set in the event record.
602
603 Note that an outsider client may connect other ports.
604 In this case, however, the subscription may be refused
605 if #SND_SEQ_PORT_CAP_NO_EXPORT capability is set in either sender or receiver port.
606
607 \section seq_subs_ex Examples of subscription
608
609 \subsection seq_subs_ex_capt Capture from keyboard
610
611 Assume MIDI input port = 64:0, application port = 128:0, and
612 queue for timestamp = 1 with real-time stamp.
613 The application port must have capability #SND_SEQ_PORT_CAP_WRITE.
614 \code
615 void capture_keyboard(snd_seq_t *seq)
616 {
617 snd_seq_addr_t sender, dest;
618 snd_seq_port_subscribe_t *subs;
619 sender.client = 64;
620 sender.port = 0;
621 dest.client = 128;
622 dest.port = 0;
623 snd_seq_port_subscribe_alloca(&subs);
624 snd_seq_port_subscribe_set_sender(subs, &sender);
625 snd_seq_port_subscribe_set_dest(subs, &dest);
626 snd_seq_port_subscribe_set_queue(subs, 1);
627 snd_seq_port_subscribe_set_time_update(subs, 1);
628 snd_seq_port_subscribe_set_time_real(subs, 1);
629 snd_seq_subscribe_port(seq, subs);
630 }
631 \endcode
632
633 \subsection seq_subs_ex_out Output to MIDI device
634
635 Assume MIDI output port = 65:1 and application port = 128:0.
636 The application port must have capability #SND_SEQ_PORT_CAP_READ.
637 \code
638 void subscribe_output(snd_seq_t *seq)
639 {
640 snd_seq_addr_t sender, dest;
641 snd_seq_port_subscribe_t *subs;
642 sender.client = 128;
643 sender.port = 0;
644 dest.client = 65;
645 dest.port = 1;
646 snd_seq_port_subscribe_alloca(&subs);
647 snd_seq_port_subscribe_set_sender(subs, &sender);
648 snd_seq_port_subscribe_set_dest(subs, &dest);
649 snd_seq_subscribe_port(seq, subs);
650 }
651 \endcode
652 This example can be simplified by using #snd_seq_connect_to() function.
653 \code
654 void subscribe_output(snd_seq_t *seq)
655 {
656 snd_seq_connect_to(seq, 0, 65, 1);
657 }
658 \endcode
659
660 \subsection seq_subs_ex_arbit Arbitrary connection
661
662 Assume connection from application 128:0 to 129:0,
663 and that subscription is done by the third application (130:0).
664 The sender must have capabilities both
665 #SND_SEQ_PORT_CAP_READ and
666 #SND_SEQ_PORT_CAP_SUBS_READ,
667 and the receiver
668 #SND_SEQ_PORT_CAP_WRITE and
669 #SND_SEQ_PORT_CAP_SUBS_WRITE, respectively.
670 \code
671 // ..in the third application (130:0) ..
672 void coupling(snd_seq_t *seq)
673 {
674 snd_seq_addr_t sender, dest;
675 snd_seq_port_subscribe_t *subs;
676 sender.client = 128;
677 sender.port = 0;
678 dest.client = 129;
679 dest.port = 0;
680 snd_seq_port_subscribe_alloca(&subs);
681 snd_seq_port_subscribe_set_sender(subs, &sender);
682 snd_seq_port_subscribe_set_dest(subs, &dest);
683 snd_seq_subscribe_port(seq, subs);
684 }
685 \endcode
686
687 \section seq_ex_event Event Processing
688
689 \subsection seq_ex_address Addressing
690
691 Now, two ports are connected by subscription. Then how to send events?
692
693 The subscribed port doesn't have to know the exact sender address.
694 Instead, there is a special address for subscribers,
695 #SND_SEQ_ADDRESS_SUBSCRIBERS.
696 The sender must set this value as the destination client.
697 Destination port is ignored.
698
699 The other values in source and destination addresses are identical with
700 the normal event record.
701 If the event is scheduled, proper queue and timestamp values must be set.
702
703 There is a convenient function to set the address in an event record.
704 In order to set destination as subscribers, use
705 #snd_seq_ev_set_subs().
706
707 \subsection Scheduled Delivery
708
709 If we send an event at the scheduled time <code>t</code> (tick)
710 on the queue <code>Q</code>,
711 the sender must set both schedule queue and time in the
712 event record.
713 The program appears like this:
714 \code
715 void schedule_event(snd_seq_t *seq)
716 {
717 snd_seq_event_t ev;
718
719 snd_seq_ev_clear(&ev);
720 snd_seq_ev_set_source(&ev, my_port);
721 snd_seq_ev_set_subs(&ev);
722 snd_seq_ev_schedule_tick(&ev, Q, 0, t);
723 ... // set event type, data, so on..
724
725 snd_seq_event_output(seq, &ev);
726 ...
727 snd_seq_drain_output(seq); // if necessary
728 }
729 \endcode
730 Of course, you can use realtime stamp, too.
731
732 \subsection seq_ex_direct Direct Delivery
733
734 If the event is sent immediately without enqueued, the sender doesn't take
735 care of queue and timestamp.
736 As well as the case above, there is a function to set the direct delivery,
737 #snd_seq_ev_set_direct().
738 The program can be more simplified as follows:
739 \code
740 void direct_delivery(snd_seq_t *seq)
741 {
742 snd_seq_event_t ev;
743
744 snd_seq_ev_clear(&ev);
745 snd_seq_ev_set_source(&ev, port);
746 snd_seq_ev_set_subs(&ev);
747 snd_seq_ev_set_direct(&ev);
748 ... // set event type, data, so on..
749
750 snd_seq_event_output(seq, &ev);
751 snd_seq_drain_output(seq);
752 }
753 \endcode
754 You should flush event soon after output event.
755 Otherwise, the event is enqueued on output queue of ALSA library
756 (not in the kernel!), and will be never processed until
757 this queue becomes full.
758
759 \subsection seq_ex_filter Filter Application
760
761 A typical filter program, which receives an event and sends it immediately
762 after some modification, will appear as following:
763 \code
764 void event_filter(snd_seq_t *seq, snd_seq_event_t *ev)
765 {
766 while (snd_seq_event_input(seq, &ev) >= 0) {
767 //.. modify input event ..
768
769 snd_seq_ev_set_source(ev, my_port);
770 snd_seq_ev_set_subs(ev);
771 snd_seq_ev_set_direct(ev);
772 snd_seq_event_output(seq, ev);
773 snd_seq_drain_output(seq);
774 }
775 }
776 \endcode
777
778 */
779
780 #include <poll.h>
781 #include "seq_local.h"
782
783 /****************************************************************************
784 * *
785 * seq.h *
786 * Sequencer *
787 * *
788 ****************************************************************************/
789
790 /**
791 * \brief get identifier of sequencer handle
792 * \param seq sequencer handle
793 * \return ASCII identifier of sequencer handle
794 *
795 * Returns the ASCII identifier of the given sequencer handle. It's the same
796 * identifier specified in snd_seq_open().
797 *
798 * \sa snd_seq_open()
799 */
snd_seq_name(snd_seq_t * seq)800 const char *snd_seq_name(snd_seq_t *seq)
801 {
802 assert(seq);
803 return seq->name;
804 }
805
806 /**
807 * \brief get type of sequencer handle
808 * \param seq sequencer handle
809 * \return type of sequencer handle
810 *
811 * Returns the type #snd_seq_type_t of the given sequencer handle.
812 *
813 * \sa snd_seq_open()
814 */
snd_seq_type(snd_seq_t * seq)815 snd_seq_type_t snd_seq_type(snd_seq_t *seq)
816 {
817 assert(seq);
818 return seq->type;
819 }
820
snd_seq_open_conf(snd_seq_t ** seqp,const char * name,snd_config_t * seq_root,snd_config_t * seq_conf,int streams,int mode)821 static int snd_seq_open_conf(snd_seq_t **seqp, const char *name,
822 snd_config_t *seq_root, snd_config_t *seq_conf,
823 int streams, int mode)
824 {
825 const char *str;
826 char buf[256], errbuf[256];
827 int err;
828 snd_config_t *conf, *type_conf = NULL;
829 snd_config_iterator_t i, next;
830 const char *id;
831 const char *lib = NULL, *open_name = NULL;
832 int (*open_func)(snd_seq_t **, const char *,
833 snd_config_t *, snd_config_t *,
834 int, int) = NULL;
835 #ifndef PIC
836 extern void *snd_seq_open_symbols(void);
837 #endif
838 void *h = NULL;
839 if (snd_config_get_type(seq_conf) != SND_CONFIG_TYPE_COMPOUND) {
840 if (name)
841 SNDERR("Invalid type for SEQ %s definition", name);
842 else
843 SNDERR("Invalid type for SEQ definition");
844 return -EINVAL;
845 }
846 err = snd_config_search(seq_conf, "type", &conf);
847 if (err < 0) {
848 SNDERR("type is not defined");
849 return err;
850 }
851 err = snd_config_get_id(conf, &id);
852 if (err < 0) {
853 SNDERR("unable to get id");
854 return err;
855 }
856 err = snd_config_get_string(conf, &str);
857 if (err < 0) {
858 SNDERR("Invalid type for %s", id);
859 return err;
860 }
861 err = snd_config_search_definition(seq_root, "seq_type", str, &type_conf);
862 if (err >= 0) {
863 if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
864 SNDERR("Invalid type for SEQ type %s definition", str);
865 goto _err;
866 }
867 snd_config_for_each(i, next, type_conf) {
868 snd_config_t *n = snd_config_iterator_entry(i);
869 const char *id;
870 if (snd_config_get_id(n, &id) < 0)
871 continue;
872 if (strcmp(id, "comment") == 0)
873 continue;
874 if (strcmp(id, "lib") == 0) {
875 err = snd_config_get_string(n, &lib);
876 if (err < 0) {
877 SNDERR("Invalid type for %s", id);
878 goto _err;
879 }
880 continue;
881 }
882 if (strcmp(id, "open") == 0) {
883 err = snd_config_get_string(n, &open_name);
884 if (err < 0) {
885 SNDERR("Invalid type for %s", id);
886 goto _err;
887 }
888 continue;
889 }
890 SNDERR("Unknown field %s", id);
891 err = -EINVAL;
892 goto _err;
893 }
894 }
895 if (!open_name) {
896 open_name = buf;
897 snprintf(buf, sizeof(buf), "_snd_seq_%s_open", str);
898 }
899 #ifndef PIC
900 snd_seq_open_symbols();
901 #endif
902 h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
903 if (h)
904 open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_SEQ_DLSYM_VERSION));
905 err = 0;
906 if (!h) {
907 SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
908 err = -ENOENT;
909 } else if (!open_func) {
910 SNDERR("symbol %s is not defined inside %s", open_name, lib);
911 snd_dlclose(h);
912 err = -ENXIO;
913 }
914 _err:
915 if (type_conf)
916 snd_config_delete(type_conf);
917 if (! err) {
918 err = open_func(seqp, name, seq_root, seq_conf, streams, mode);
919 if (err < 0)
920 snd_dlclose(h);
921 else
922 (*seqp)->dl_handle = h;
923 }
924 return err;
925 }
926
snd_seq_open_noupdate(snd_seq_t ** seqp,snd_config_t * root,const char * name,int streams,int mode,int hop)927 static int snd_seq_open_noupdate(snd_seq_t **seqp, snd_config_t *root,
928 const char *name, int streams, int mode,
929 int hop)
930 {
931 int err;
932 snd_config_t *seq_conf;
933 err = snd_config_search_definition(root, "seq", name, &seq_conf);
934 if (err < 0) {
935 SNDERR("Unknown SEQ %s", name);
936 return err;
937 }
938 snd_config_set_hop(seq_conf, hop);
939 err = snd_seq_open_conf(seqp, name, root, seq_conf, streams, mode);
940 snd_config_delete(seq_conf);
941 return err;
942 }
943
944
945 /**
946 * \brief Open the ALSA sequencer
947 *
948 * \param seqp Pointer to a snd_seq_t pointer. This pointer must be
949 * kept and passed to most of the other sequencer functions.
950 * \param name The sequencer's "name". This is \em not a name you make
951 * up for your own purposes; it has special significance to the ALSA
952 * library. Usually you need to pass \c "default" here.
953 * \param streams The read/write mode of the sequencer. Can be one of
954 * three values:
955 * - #SND_SEQ_OPEN_OUTPUT - open the sequencer for output only
956 * - #SND_SEQ_OPEN_INPUT - open the sequencer for input only
957 * - #SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input
958 * \note Internally, these are translated to \c O_WRONLY, \c O_RDONLY and
959 * \c O_RDWR respectively and used as the second argument to the C library
960 * open() call.
961 * \param mode Optional modifier. Can be either 0, or
962 * #SND_SEQ_NONBLOCK, which will make read/write operations
963 * non-blocking. This can also be set later using #snd_seq_nonblock().
964 * \return 0 on success otherwise a negative error code
965 *
966 * Creates a new handle and opens a connection to the kernel
967 * sequencer interface.
968 * After a client is created successfully, an event
969 * with #SND_SEQ_EVENT_CLIENT_START is broadcast to announce port.
970 *
971 * \sa snd_seq_open_lconf(), snd_seq_close(), snd_seq_type(), snd_seq_name(),
972 * snd_seq_nonblock(), snd_seq_client_id()
973 */
snd_seq_open(snd_seq_t ** seqp,const char * name,int streams,int mode)974 int snd_seq_open(snd_seq_t **seqp, const char *name,
975 int streams, int mode)
976 {
977 snd_config_t *top;
978 int err;
979
980 assert(seqp && name);
981 err = snd_config_update_ref(&top);
982 if (err < 0)
983 return err;
984 err = snd_seq_open_noupdate(seqp, top, name, streams, mode, 0);
985 snd_config_unref(top);
986 return err;
987 }
988
989 /**
990 * \brief Open the ALSA sequencer using local configuration
991 *
992 * \param seqp Pointer to a snd_seq_t pointer.
993 * \param name The name to open
994 * \param streams The read/write mode of the sequencer.
995 * \param mode Optional modifier
996 * \param lconf Local configuration
997 * \return 0 on success otherwise a negative error code
998 *
999 * See the snd_seq_open() function for further details. The extension
1000 * is that the given configuration is used to resolve abstract name.
1001 *
1002 * \sa snd_seq_open()
1003 */
snd_seq_open_lconf(snd_seq_t ** seqp,const char * name,int streams,int mode,snd_config_t * lconf)1004 int snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
1005 int streams, int mode, snd_config_t *lconf)
1006 {
1007 assert(seqp && name && lconf);
1008 return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, 0);
1009 }
1010
1011 #ifndef DOC_HIDDEN
_snd_seq_open_lconf(snd_seq_t ** seqp,const char * name,int streams,int mode,snd_config_t * lconf,snd_config_t * parent_conf)1012 int _snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
1013 int streams, int mode, snd_config_t *lconf,
1014 snd_config_t *parent_conf)
1015 {
1016 int hop;
1017 assert(seqp && name && lconf);
1018 if ((hop = snd_config_check_hop(parent_conf)) < 0)
1019 return hop;
1020 return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, hop + 1);
1021 }
1022 #endif
1023
1024 /**
1025 * \brief Close the sequencer
1026 * \param seq Handle returned from #snd_seq_open()
1027 * \return 0 on success otherwise a negative error code
1028 *
1029 * Closes the sequencer client and releases its resources.
1030 * After a client is closed, an event with
1031 * #SND_SEQ_EVENT_CLIENT_EXIT is broadcast to announce port.
1032 * The connection between other clients are disconnected.
1033 * Call this just before exiting your program.
1034 *
1035 * \sa snd_seq_close()
1036 */
snd_seq_close(snd_seq_t * seq)1037 int snd_seq_close(snd_seq_t *seq)
1038 {
1039 int err;
1040 assert(seq);
1041 err = seq->ops->close(seq);
1042 if (seq->dl_handle)
1043 snd_dlclose(seq->dl_handle);
1044 free(seq->obuf);
1045 free(seq->ibuf);
1046 free(seq->tmpbuf);
1047 free(seq->name);
1048 free(seq);
1049 return err;
1050 }
1051
1052 /**
1053 * \brief Returns the number of poll descriptors
1054 * \param seq sequencer handle
1055 * \param events the poll events to be checked (\c POLLIN and \c POLLOUT)
1056 * \return the number of poll descriptors.
1057 *
1058 * Get the number of poll descriptors. The polling events to be checked
1059 * can be specified by the second argument. When both input and output
1060 * are checked, pass \c POLLIN|POLLOUT
1061 *
1062 * \sa snd_seq_poll_descriptors()
1063 */
snd_seq_poll_descriptors_count(snd_seq_t * seq,short events)1064 int snd_seq_poll_descriptors_count(snd_seq_t *seq, short events)
1065 {
1066 int result = 0;
1067 assert(seq);
1068 if (events & POLLIN) {
1069 assert(seq->streams & SND_SEQ_OPEN_INPUT);
1070 result++;
1071 }
1072 if (events & POLLOUT) {
1073 assert(seq->streams & SND_SEQ_OPEN_OUTPUT);
1074 result++;
1075 }
1076 return result ? 1 : 0;
1077 }
1078
1079 /**
1080 * \brief Get poll descriptors
1081 * \param seq sequencer handle
1082 * \param pfds array of poll descriptors
1083 * \param space space in the poll descriptor array
1084 * \param events polling events to be checked (\c POLLIN and \c POLLOUT)
1085 * \return count of filled descriptors
1086 *
1087 * Get poll descriptors assigned to the sequencer handle.
1088 * Since a sequencer handle can duplex streams, you need to set which direction(s)
1089 * is/are polled in \a events argument. When \c POLLIN bit is specified,
1090 * the incoming events to the ports are checked.
1091 *
1092 * To check the returned poll-events, call #snd_seq_poll_descriptors_revents()
1093 * instead of reading the pollfd structs directly.
1094 *
1095 * \sa snd_seq_poll_descriptors_count(), snd_seq_poll_descriptors_revents()
1096 */
snd_seq_poll_descriptors(snd_seq_t * seq,struct pollfd * pfds,unsigned int space,short events)1097 int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int space, short events)
1098 {
1099 short revents = 0;
1100
1101 assert(seq);
1102 if ((events & POLLIN) && space >= 1) {
1103 assert(seq->streams & SND_SEQ_OPEN_INPUT);
1104 revents |= POLLIN|POLLERR|POLLNVAL;
1105 }
1106 if ((events & POLLOUT) && space >= 1) {
1107 assert(seq->streams & SND_SEQ_OPEN_OUTPUT);
1108 revents |= POLLOUT|POLLERR|POLLNVAL;
1109 }
1110 if (!revents)
1111 return 0;
1112 pfds->fd = seq->poll_fd;
1113 pfds->events = revents;
1114 return 1;
1115 }
1116
1117 /**
1118 * \brief get returned events from poll descriptors
1119 * \param seq sequencer handle
1120 * \param pfds array of poll descriptors
1121 * \param nfds count of poll descriptors
1122 * \param revents returned events
1123 * \return zero if success, otherwise a negative error code
1124 *
1125 * \sa snd_seq_poll_descriptors()
1126 */
snd_seq_poll_descriptors_revents(snd_seq_t * seq,struct pollfd * pfds,unsigned int nfds,unsigned short * revents)1127 int snd_seq_poll_descriptors_revents(snd_seq_t *seq, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
1128 {
1129 assert(seq && pfds && revents);
1130 if (nfds == 1) {
1131 *revents = pfds->revents;
1132 return 0;
1133 }
1134 return -EINVAL;
1135 }
1136
1137 /**
1138 * \brief Set nonblock mode
1139 * \param seq sequencer handle
1140 * \param nonblock 0 = block, 1 = nonblock mode
1141 * \return 0 on success otherwise a negative error code
1142 *
1143 * Change the blocking mode of the given client.
1144 * In block mode, the client falls into sleep when it fills the
1145 * output memory pool with full events. The client will be woken up
1146 * after a certain amount of free space becomes available.
1147 *
1148 * \sa snd_seq_open()
1149 */
snd_seq_nonblock(snd_seq_t * seq,int nonblock)1150 int snd_seq_nonblock(snd_seq_t *seq, int nonblock)
1151 {
1152 int err;
1153 assert(seq);
1154 err = seq->ops->nonblock(seq, nonblock);
1155 if (err < 0)
1156 return err;
1157 if (nonblock)
1158 seq->mode |= SND_SEQ_NONBLOCK;
1159 else
1160 seq->mode &= ~SND_SEQ_NONBLOCK;
1161 return 0;
1162 }
1163
1164 /**
1165 * \brief Get the client id
1166 * \param seq sequencer handle
1167 * \return the client id
1168 *
1169 * Returns the id of the specified client.
1170 * If an error occurs, function returns the negative error code.
1171 * A client id is necessary to inquiry or to set the client information.
1172 * A user client is assigned from 128 to 191.
1173 *
1174 * \sa snd_seq_open()
1175 */
snd_seq_client_id(snd_seq_t * seq)1176 int snd_seq_client_id(snd_seq_t *seq)
1177 {
1178 assert(seq);
1179 return seq->client;
1180 }
1181
1182 /**
1183 * \brief Return the size of output buffer
1184 * \param seq sequencer handle
1185 * \return the size of output buffer in bytes
1186 *
1187 * Obtains the size of output buffer.
1188 * This buffer is used to store decoded byte-stream of output events
1189 * before transferring to sequencer.
1190 *
1191 * \sa snd_seq_set_output_buffer_size()
1192 */
snd_seq_get_output_buffer_size(snd_seq_t * seq)1193 size_t snd_seq_get_output_buffer_size(snd_seq_t *seq)
1194 {
1195 assert(seq);
1196 if (!seq->obuf)
1197 return 0;
1198 return seq->obufsize;
1199 }
1200
1201 /**
1202 * \brief Return the size of input buffer
1203 * \param seq sequencer handle
1204 * \return the size of input buffer in bytes
1205 *
1206 * Obtains the size of input buffer.
1207 * This buffer is used to read byte-stream of input events from sequencer.
1208 *
1209 * \sa snd_seq_set_input_buffer_size()
1210 */
snd_seq_get_input_buffer_size(snd_seq_t * seq)1211 size_t snd_seq_get_input_buffer_size(snd_seq_t *seq)
1212 {
1213 assert(seq);
1214 if (!seq->ibuf)
1215 return 0;
1216 return seq->ibufsize * sizeof(snd_seq_event_t);
1217 }
1218
1219 /**
1220 * \brief Change the size of output buffer
1221 * \param seq sequencer handle
1222 * \param size the size of output buffer to be changed in bytes
1223 * \return 0 on success otherwise a negative error code
1224 *
1225 * Changes the size of output buffer.
1226 *
1227 * \sa snd_seq_get_output_buffer_size()
1228 */
snd_seq_set_output_buffer_size(snd_seq_t * seq,size_t size)1229 int snd_seq_set_output_buffer_size(snd_seq_t *seq, size_t size)
1230 {
1231 assert(seq && seq->obuf);
1232 assert(size >= sizeof(snd_seq_event_t));
1233 snd_seq_drop_output(seq);
1234 if (size != seq->obufsize) {
1235 char *newbuf;
1236 newbuf = calloc(1, size);
1237 if (newbuf == NULL)
1238 return -ENOMEM;
1239 free(seq->obuf);
1240 seq->obuf = newbuf;
1241 seq->obufsize = size;
1242 }
1243 return 0;
1244 }
1245
1246 /**
1247 * \brief Resize the input buffer
1248 * \param seq sequencer handle
1249 * \param size the size of input buffer to be changed in bytes
1250 * \return 0 on success otherwise a negative error code
1251 *
1252 * Changes the size of input buffer.
1253 *
1254 * \sa snd_seq_get_input_buffer_size()
1255 */
snd_seq_set_input_buffer_size(snd_seq_t * seq,size_t size)1256 int snd_seq_set_input_buffer_size(snd_seq_t *seq, size_t size)
1257 {
1258 assert(seq && seq->ibuf);
1259 assert(size >= sizeof(snd_seq_event_t));
1260 snd_seq_drop_input(seq);
1261 size = (size + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
1262 if (size != seq->ibufsize) {
1263 snd_seq_event_t *newbuf;
1264 newbuf = calloc(sizeof(snd_seq_event_t), size);
1265 if (newbuf == NULL)
1266 return -ENOMEM;
1267 free(seq->ibuf);
1268 seq->ibuf = newbuf;
1269 seq->ibufsize = size;
1270 }
1271 return 0;
1272 }
1273
1274
1275 /**
1276 * \brief Get size of #snd_seq_system_info_t
1277 * \return size in bytes
1278 */
snd_seq_system_info_sizeof()1279 size_t snd_seq_system_info_sizeof()
1280 {
1281 return sizeof(snd_seq_system_info_t);
1282 }
1283
1284 /**
1285 * \brief Allocate an empty #snd_seq_system_info_t using standard malloc
1286 * \param ptr returned pointer
1287 * \return 0 on success otherwise negative error code
1288 */
snd_seq_system_info_malloc(snd_seq_system_info_t ** ptr)1289 int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr)
1290 {
1291 assert(ptr);
1292 *ptr = calloc(1, sizeof(snd_seq_system_info_t));
1293 if (!*ptr)
1294 return -ENOMEM;
1295 return 0;
1296 }
1297
1298 /**
1299 * \brief Frees a previously allocated #snd_seq_system_info_t
1300 * \param obj pointer to object to free
1301 */
snd_seq_system_info_free(snd_seq_system_info_t * obj)1302 void snd_seq_system_info_free(snd_seq_system_info_t *obj)
1303 {
1304 free(obj);
1305 }
1306
1307 /**
1308 * \brief Copy one #snd_seq_system_info_t to another
1309 * \param dst pointer to destination
1310 * \param src pointer to source
1311 */
snd_seq_system_info_copy(snd_seq_system_info_t * dst,const snd_seq_system_info_t * src)1312 void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src)
1313 {
1314 assert(dst && src);
1315 *dst = *src;
1316 }
1317
1318
1319 /**
1320 * \brief Get maximum number of queues
1321 * \param info #snd_seq_system_info_t container
1322 * \return maximum number of queues
1323 *
1324 * \sa snd_seq_system_info()
1325 */
snd_seq_system_info_get_queues(const snd_seq_system_info_t * info)1326 int snd_seq_system_info_get_queues(const snd_seq_system_info_t *info)
1327 {
1328 assert(info);
1329 return info->queues;
1330 }
1331
1332 /**
1333 * \brief Get maximum number of clients
1334 * \param info #snd_seq_system_info_t container
1335 * \return maximum number of clients
1336 *
1337 * \sa snd_seq_system_info()
1338 */
snd_seq_system_info_get_clients(const snd_seq_system_info_t * info)1339 int snd_seq_system_info_get_clients(const snd_seq_system_info_t *info)
1340 {
1341 assert(info);
1342 return info->clients;
1343 }
1344
1345 /**
1346 * \brief Get maximum number of ports
1347 * \param info #snd_seq_system_info_t container
1348 * \return maximum number of ports
1349 *
1350 * \sa snd_seq_system_info()
1351 */
snd_seq_system_info_get_ports(const snd_seq_system_info_t * info)1352 int snd_seq_system_info_get_ports(const snd_seq_system_info_t *info)
1353 {
1354 assert(info);
1355 return info->ports;
1356 }
1357
1358 /**
1359 * \brief Get maximum number of channels
1360 * \param info #snd_seq_system_info_t container
1361 * \return maximum number of channels
1362 *
1363 * \sa snd_seq_system_info()
1364 */
snd_seq_system_info_get_channels(const snd_seq_system_info_t * info)1365 int snd_seq_system_info_get_channels(const snd_seq_system_info_t *info)
1366 {
1367 assert(info);
1368 return info->channels;
1369 }
1370
1371 /**
1372 * \brief Get the current number of clients
1373 * \param info #snd_seq_system_info_t container
1374 * \return current number of clients
1375 *
1376 * \sa snd_seq_system_info()
1377 */
snd_seq_system_info_get_cur_clients(const snd_seq_system_info_t * info)1378 int snd_seq_system_info_get_cur_clients(const snd_seq_system_info_t *info)
1379 {
1380 assert(info);
1381 return info->cur_clients;
1382 }
1383
1384 /**
1385 * \brief Get the current number of queues
1386 * \param info #snd_seq_system_info_t container
1387 * \return current number of queues
1388 *
1389 * \sa snd_seq_system_info()
1390 */
snd_seq_system_info_get_cur_queues(const snd_seq_system_info_t * info)1391 int snd_seq_system_info_get_cur_queues(const snd_seq_system_info_t *info)
1392 {
1393 assert(info);
1394 return info->cur_queues;
1395 }
1396
1397 /**
1398 * \brief obtain the sequencer system information
1399 * \param seq sequencer handle
1400 * \param info the pointer to be stored
1401 * \return 0 on success otherwise a negative error code
1402 *
1403 * Stores the global system information of ALSA sequencer system.
1404 * The returned data contains
1405 * the maximum available numbers of queues, clients, ports and channels.
1406 */
snd_seq_system_info(snd_seq_t * seq,snd_seq_system_info_t * info)1407 int snd_seq_system_info(snd_seq_t *seq, snd_seq_system_info_t * info)
1408 {
1409 assert(seq && info);
1410 return seq->ops->system_info(seq, info);
1411 }
1412
1413
1414 /*----------------------------------------------------------------*/
1415
1416 /**
1417 * \brief get size of #snd_seq_client_info_t
1418 * \return size in bytes
1419 */
snd_seq_client_info_sizeof()1420 size_t snd_seq_client_info_sizeof()
1421 {
1422 return sizeof(snd_seq_client_info_t);
1423 }
1424
1425 /**
1426 * \brief allocate an empty #snd_seq_client_info_t using standard malloc
1427 * \param ptr returned pointer
1428 * \return 0 on success otherwise negative error code
1429 */
snd_seq_client_info_malloc(snd_seq_client_info_t ** ptr)1430 int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr)
1431 {
1432 assert(ptr);
1433 *ptr = calloc(1, sizeof(snd_seq_client_info_t));
1434 if (!*ptr)
1435 return -ENOMEM;
1436 return 0;
1437 }
1438
1439 /**
1440 * \brief frees a previously allocated #snd_seq_client_info_t
1441 * \param obj pointer to object to free
1442 */
snd_seq_client_info_free(snd_seq_client_info_t * obj)1443 void snd_seq_client_info_free(snd_seq_client_info_t *obj)
1444 {
1445 free(obj);
1446 }
1447
1448 /**
1449 * \brief copy one #snd_seq_client_info_t to another
1450 * \param dst pointer to destination
1451 * \param src pointer to source
1452 */
snd_seq_client_info_copy(snd_seq_client_info_t * dst,const snd_seq_client_info_t * src)1453 void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src)
1454 {
1455 assert(dst && src);
1456 *dst = *src;
1457 }
1458
1459
1460 /**
1461 * \brief Get client id of a client_info container
1462 * \param info client_info container
1463 * \return client id
1464 *
1465 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_client(), snd_seq_client_id()
1466 */
snd_seq_client_info_get_client(const snd_seq_client_info_t * info)1467 int snd_seq_client_info_get_client(const snd_seq_client_info_t *info)
1468 {
1469 assert(info);
1470 return info->client;
1471 }
1472
1473 /**
1474 * \brief Get client type of a client_info container
1475 * \param info client_info container
1476 * \return client type
1477 *
1478 * The client type is either #SND_SEQ_KERNEL_CLIENT or #SND_SEQ_USER_CLIENT
1479 * for kernel or user client respectively.
1480 *
1481 * \sa snd_seq_get_client_info()
1482 */
snd_seq_client_info_get_type(const snd_seq_client_info_t * info)1483 snd_seq_client_type_t snd_seq_client_info_get_type(const snd_seq_client_info_t *info)
1484 {
1485 assert(info);
1486 return info->type;
1487 }
1488
1489 /**
1490 * \brief Get the name of a client_info container
1491 * \param info client_info container
1492 * \return name string
1493 *
1494 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_name()
1495 */
snd_seq_client_info_get_name(snd_seq_client_info_t * info)1496 const char *snd_seq_client_info_get_name(snd_seq_client_info_t *info)
1497 {
1498 assert(info);
1499 return info->name;
1500 }
1501
1502 /**
1503 * \brief Get the broadcast filter usage of a client_info container
1504 * \param info client_info container
1505 * \return 1 if broadcast is accepted
1506 *
1507 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_broadcast_filter()
1508 */
snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t * info)1509 int snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t *info)
1510 {
1511 assert(info);
1512 return (info->filter & SNDRV_SEQ_FILTER_BROADCAST) ? 1 : 0;
1513 }
1514
1515 /**
1516 * \brief Get the error-bounce usage of a client_info container
1517 * \param info client_info container
1518 * \return 1 if error-bounce is enabled
1519 *
1520 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_error_bounce()
1521 */
snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t * info)1522 int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info)
1523 {
1524 assert(info);
1525 return (info->filter & SNDRV_SEQ_FILTER_BOUNCE) ? 1 : 0;
1526 }
1527
1528 /**
1529 * \brief Get the sound card number.
1530 * \param info client_info container
1531 * \return card number or -1 if value is not available.
1532 *
1533 * Only available for #SND_SEQ_KERNEL_CLIENT clients.
1534 *
1535 * The card number can be used to query state about the hardware
1536 * device providing this client, by concatenating <code>"hw:CARD="</code>
1537 * with the card number and using it as the <code>name</code> parameter
1538 * to #snd_ctl_open().
1539 *
1540 * \note
1541 * The return value of -1 is returned for two different conditions: when the
1542 * running kernel does not support this operation, and when the client
1543 * does not have a hardware card attached. See
1544 * #snd_seq_client_info_get_pid() for a way to determine if the
1545 * currently running kernel has support for this operation.
1546 *
1547 * \sa snd_seq_client_info_get_pid(),
1548 * snd_card_get_name(),
1549 * snd_card_get_longname(),
1550 * snd_ctl_open(),
1551 * snd_ctl_card_info()
1552 */
snd_seq_client_info_get_card(const snd_seq_client_info_t * info)1553 int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
1554 {
1555 assert(info);
1556 return info->card;
1557 }
1558
1559 /**
1560 * \brief Get the owning PID.
1561 * \param info client_info container
1562 * \return pid or -1 if value is not available.
1563 *
1564 * Only available for #SND_SEQ_USER_CLIENT clients.
1565 *
1566 * \note
1567 * The functionality for getting a client's PID and getting a
1568 * client's card was added to the kernel at the same time, so you can
1569 * use this function to determine if the running kernel
1570 * supports reporting these values. If your own client has a valid
1571 * PID as reported by this function, then the running kernel supports
1572 * both #snd_seq_client_info_get_card() and #snd_seq_client_info_get_pid().
1573 *
1574 * \note
1575 * Example code for determining kernel support:
1576 * \code
1577 * int is_get_card_or_pid_supported(snd_seq_t *seq)
1578 * {
1579 * snd_seq_client_info_t *my_client_info;
1580 * snd_seq_client_info_alloca(&my_client_info);
1581 * snd_seq_get_client_info(seq, my_client_info);
1582 * return snd_seq_client_info_get_pid(my_client_info) != -1;
1583 * }
1584 * \endcode
1585 *
1586 * \sa snd_seq_client_info_get_card()
1587 */
snd_seq_client_info_get_pid(const snd_seq_client_info_t * info)1588 int snd_seq_client_info_get_pid(const snd_seq_client_info_t *info)
1589 {
1590 assert(info);
1591 return info->pid;
1592 }
1593
1594 /**
1595 * \brief (DEPRECATED) Get the event filter bitmap of a client_info container
1596 * \param info client_info container
1597 * \return NULL if no event filter, or pointer to event filter bitmap
1598 *
1599 * Use #snd_seq_client_info_event_filter_check() instead.
1600 *
1601 * \sa snd_seq_client_info_event_filter_add(),
1602 * snd_seq_client_info_event_filter_del(),
1603 * snd_seq_client_info_event_filter_check(),
1604 * snd_seq_client_info_event_filter_clear(),
1605 * snd_seq_get_client_info()
1606 */
snd_seq_client_info_get_event_filter(const snd_seq_client_info_t * info)1607 const unsigned char *snd_seq_client_info_get_event_filter(const snd_seq_client_info_t *info)
1608 {
1609 assert(info);
1610 if (info->filter & SNDRV_SEQ_FILTER_USE_EVENT)
1611 return info->event_filter;
1612 else
1613 return NULL;
1614 }
1615
1616 /**
1617 * \brief Disable event filtering of a client_info container
1618 * \param info client_info container
1619 *
1620 * Remove all event types added with #snd_seq_client_info_event_filter_add and clear
1621 * the event filtering flag of this client_info container.
1622 *
1623 * \sa snd_seq_client_info_event_filter_add(),
1624 * snd_seq_client_info_event_filter_del(),
1625 * snd_seq_client_info_event_filter_check(),
1626 * snd_seq_get_client_info(),
1627 * snd_seq_set_client_info()
1628 */
snd_seq_client_info_event_filter_clear(snd_seq_client_info_t * info)1629 void snd_seq_client_info_event_filter_clear(snd_seq_client_info_t *info)
1630 {
1631 assert(info);
1632 info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT;
1633 memset(info->event_filter, 0, sizeof(info->event_filter));
1634 }
1635
1636 /**
1637 * \brief Add an event type to the event filtering of a client_info container
1638 * \param info client_info container
1639 * \param event_type event type to be added
1640 *
1641 * Set the event filtering flag of this client_info and add the specified event type to the
1642 * filter bitmap of this client_info container.
1643 *
1644 * \sa snd_seq_get_client_info(),
1645 * snd_seq_set_client_info(),
1646 * snd_seq_client_info_event_filter_del(),
1647 * snd_seq_client_info_event_filter_check(),
1648 * snd_seq_client_info_event_filter_clear()
1649 */
snd_seq_client_info_event_filter_add(snd_seq_client_info_t * info,int event_type)1650 void snd_seq_client_info_event_filter_add(snd_seq_client_info_t *info, int event_type)
1651 {
1652 assert(info);
1653 info->filter |= SNDRV_SEQ_FILTER_USE_EVENT;
1654 snd_seq_set_bit(event_type, info->event_filter);
1655 }
1656
1657 /**
1658 * \brief Remove an event type from the event filtering of a client_info container
1659 * \param info client_info container
1660 * \param event_type event type to be removed
1661 *
1662 * Removes the specified event from the filter bitmap of this client_info container. It will
1663 * not clear the event filtering flag, use #snd_seq_client_info_event_filter_clear instead.
1664 *
1665 * \sa snd_seq_get_client_info(),
1666 * snd_seq_set_client_info(),
1667 * snd_seq_client_info_event_filter_add(),
1668 * snd_seq_client_info_event_filter_check(),
1669 * snd_seq_client_info_event_filter_clear()
1670 */
snd_seq_client_info_event_filter_del(snd_seq_client_info_t * info,int event_type)1671 void snd_seq_client_info_event_filter_del(snd_seq_client_info_t *info, int event_type)
1672 {
1673 assert(info);
1674 snd_seq_unset_bit(event_type, info->event_filter);
1675 }
1676
1677 /**
1678 * \brief Check if an event type is present in the event filtering of a client_info container
1679 * \param info client_info container
1680 * \param event_type event type to be checked
1681 * \return 1 if the event type is present, 0 otherwise
1682 *
1683 * Test if the event type is in the filter bitmap of this client_info container.
1684 *
1685 * \sa snd_seq_get_client_info(),
1686 * snd_seq_set_client_info(),
1687 * snd_seq_client_info_event_filter_add(),
1688 * snd_seq_client_info_event_filter_del(),
1689 * snd_seq_client_info_event_filter_clear()
1690 */
snd_seq_client_info_event_filter_check(snd_seq_client_info_t * info,int event_type)1691 int snd_seq_client_info_event_filter_check(snd_seq_client_info_t *info, int event_type)
1692 {
1693 assert(info);
1694 return snd_seq_get_bit(event_type, info->event_filter);
1695 }
1696
1697 /**
1698 * \brief Get the number of opened ports of a client_info container
1699 * \param info client_info container
1700 * \return number of opened ports
1701 *
1702 * \sa snd_seq_get_client_info()
1703 */
snd_seq_client_info_get_num_ports(const snd_seq_client_info_t * info)1704 int snd_seq_client_info_get_num_ports(const snd_seq_client_info_t *info)
1705 {
1706 assert(info);
1707 return info->num_ports;
1708 }
1709
1710 /**
1711 * \brief Get the number of lost events of a client_info container
1712 * \param info client_info container
1713 * \return number of lost events
1714 *
1715 * \sa snd_seq_get_client_info()
1716 */
snd_seq_client_info_get_event_lost(const snd_seq_client_info_t * info)1717 int snd_seq_client_info_get_event_lost(const snd_seq_client_info_t *info)
1718 {
1719 assert(info);
1720 return info->event_lost;
1721 }
1722
1723 /**
1724 * \brief Set the client id of a client_info container
1725 * \param info client_info container
1726 * \param client client id
1727 *
1728 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_client()
1729 */
snd_seq_client_info_set_client(snd_seq_client_info_t * info,int client)1730 void snd_seq_client_info_set_client(snd_seq_client_info_t *info, int client)
1731 {
1732 assert(info);
1733 info->client = client;
1734 }
1735
1736 /**
1737 * \brief Set the name of a client_info container
1738 * \param info client_info container
1739 * \param name name string
1740 *
1741 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_name(),
1742 * snd_seq_set_client_name()
1743 */
snd_seq_client_info_set_name(snd_seq_client_info_t * info,const char * name)1744 void snd_seq_client_info_set_name(snd_seq_client_info_t *info, const char *name)
1745 {
1746 assert(info && name);
1747 snd_strlcpy(info->name, name, sizeof(info->name));
1748 }
1749
1750 /**
1751 * \brief Set the broadcast filter usage of a client_info container
1752 * \param info client_info container
1753 * \param val non-zero if broadcast is accepted
1754 *
1755 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_broadcast_filter()
1756 */
snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t * info,int val)1757 void snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t *info, int val)
1758 {
1759 assert(info);
1760 if (val)
1761 info->filter |= SNDRV_SEQ_FILTER_BROADCAST;
1762 else
1763 info->filter &= ~SNDRV_SEQ_FILTER_BROADCAST;
1764 }
1765
1766 /**
1767 * \brief Set the error-bounce usage of a client_info container
1768 * \param info client_info container
1769 * \param val non-zero if error is bounced
1770 *
1771 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_error_bounce()
1772 */
snd_seq_client_info_set_error_bounce(snd_seq_client_info_t * info,int val)1773 void snd_seq_client_info_set_error_bounce(snd_seq_client_info_t *info, int val)
1774 {
1775 assert(info);
1776 if (val)
1777 info->filter |= SNDRV_SEQ_FILTER_BOUNCE;
1778 else
1779 info->filter &= ~SNDRV_SEQ_FILTER_BOUNCE;
1780 }
1781
1782 /**
1783 * \brief (DEPRECATED) Set the event filter bitmap of a client_info container
1784 * \param info client_info container
1785 * \param filter event filter bitmap, pass NULL for no event filtering
1786 *
1787 * Use #snd_seq_client_info_event_filter_add instead.
1788 *
1789 * \sa snd_seq_client_info_event_filter_add(),
1790 * snd_seq_client_info_event_filter_del(),
1791 * snd_seq_client_info_event_filter_check(),
1792 * snd_seq_client_info_event_filter_clear(),
1793 * snd_seq_set_client_info()
1794 */
snd_seq_client_info_set_event_filter(snd_seq_client_info_t * info,unsigned char * filter)1795 void snd_seq_client_info_set_event_filter(snd_seq_client_info_t *info, unsigned char *filter)
1796 {
1797 assert(info);
1798 if (! filter)
1799 info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT;
1800 else {
1801 info->filter |= SNDRV_SEQ_FILTER_USE_EVENT;
1802 memcpy(info->event_filter, filter, sizeof(info->event_filter));
1803 }
1804 }
1805
1806
1807 /**
1808 * \brief obtain the information of the given client
1809 * \param seq sequencer handle
1810 * \param client client id
1811 * \param info the pointer to be stored
1812 * \return 0 on success otherwise a negative error code
1813 *
1814 * Obtains the information of the client with a client id specified by
1815 * info argument.
1816 * The obtained information is written on info parameter.
1817 *
1818 * \sa snd_seq_get_client_info()
1819 */
snd_seq_get_any_client_info(snd_seq_t * seq,int client,snd_seq_client_info_t * info)1820 int snd_seq_get_any_client_info(snd_seq_t *seq, int client, snd_seq_client_info_t *info)
1821 {
1822 assert(seq && info && client >= 0);
1823 memset(info, 0, sizeof(snd_seq_client_info_t));
1824 info->client = client;
1825 return seq->ops->get_client_info(seq, info);
1826 }
1827
1828 /**
1829 * \brief obtain the current client information
1830 * \param seq sequencer handle
1831 * \param info the pointer to be stored
1832 * \return 0 on success otherwise a negative error code
1833 *
1834 * Obtains the information of the current client stored on info.
1835 * client and type fields are ignored.
1836 *
1837 * \sa snd_seq_get_any_client_info(), snd_seq_set_client_info(),
1838 * snd_seq_query_next_client()
1839 */
snd_seq_get_client_info(snd_seq_t * seq,snd_seq_client_info_t * info)1840 int snd_seq_get_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
1841 {
1842 return snd_seq_get_any_client_info(seq, seq->client, info);
1843 }
1844
1845 /**
1846 * \brief set the current client information
1847 * \param seq sequencer handle
1848 * \param info the client info data to set
1849 * \return 0 on success otherwise a negative error code
1850 *
1851 * Obtains the information of the current client stored on info.
1852 * client and type fields are ignored.
1853 *
1854 * \sa snd_seq_get_client_info()
1855 */
snd_seq_set_client_info(snd_seq_t * seq,snd_seq_client_info_t * info)1856 int snd_seq_set_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
1857 {
1858 assert(seq && info);
1859 info->client = seq->client;
1860 info->type = USER_CLIENT;
1861 return seq->ops->set_client_info(seq, info);
1862 }
1863
1864 /**
1865 * \brief query the next client
1866 * \param seq sequencer handle
1867 * \param info query pattern and result
1868 *
1869 * Queries the next client.
1870 * The search begins at the client with an id one greater than
1871 * client field in info.
1872 * If a client is found, its attributes are stored in info,
1873 * and zero is returned.
1874 * Otherwise returns a negative error code.
1875 *
1876 * \sa snd_seq_get_any_client_info()
1877 */
snd_seq_query_next_client(snd_seq_t * seq,snd_seq_client_info_t * info)1878 int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info)
1879 {
1880 assert(seq && info);
1881 return seq->ops->query_next_client(seq, info);
1882 }
1883
1884
1885 /*----------------------------------------------------------------*/
1886
1887
1888 /*
1889 * Port
1890 */
1891
1892 /**
1893 * \brief get size of #snd_seq_port_info_t
1894 * \return size in bytes
1895 */
snd_seq_port_info_sizeof()1896 size_t snd_seq_port_info_sizeof()
1897 {
1898 return sizeof(snd_seq_port_info_t);
1899 }
1900
1901 /**
1902 * \brief allocate an empty #snd_seq_port_info_t using standard malloc
1903 * \param ptr returned pointer
1904 * \return 0 on success otherwise negative error code
1905 */
snd_seq_port_info_malloc(snd_seq_port_info_t ** ptr)1906 int snd_seq_port_info_malloc(snd_seq_port_info_t **ptr)
1907 {
1908 assert(ptr);
1909 *ptr = calloc(1, sizeof(snd_seq_port_info_t));
1910 if (!*ptr)
1911 return -ENOMEM;
1912 return 0;
1913 }
1914
1915 /**
1916 * \brief frees a previously allocated #snd_seq_port_info_t
1917 * \param obj pointer to object to free
1918 */
snd_seq_port_info_free(snd_seq_port_info_t * obj)1919 void snd_seq_port_info_free(snd_seq_port_info_t *obj)
1920 {
1921 free(obj);
1922 }
1923
1924 /**
1925 * \brief copy one #snd_seq_port_info_t to another
1926 * \param dst pointer to destination
1927 * \param src pointer to source
1928 */
snd_seq_port_info_copy(snd_seq_port_info_t * dst,const snd_seq_port_info_t * src)1929 void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src)
1930 {
1931 assert(dst && src);
1932 *dst = *src;
1933 }
1934
1935
1936 /**
1937 * \brief Get client id of a port_info container
1938 * \param info port_info container
1939 * \return client id
1940 *
1941 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_client()
1942 */
snd_seq_port_info_get_client(const snd_seq_port_info_t * info)1943 int snd_seq_port_info_get_client(const snd_seq_port_info_t *info)
1944 {
1945 assert(info);
1946 return info->addr.client;
1947 }
1948
1949 /**
1950 * \brief Get port id of a port_info container
1951 * \param info port_info container
1952 * \return port id
1953 *
1954 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port()
1955 */
snd_seq_port_info_get_port(const snd_seq_port_info_t * info)1956 int snd_seq_port_info_get_port(const snd_seq_port_info_t *info)
1957 {
1958 assert(info);
1959 return info->addr.port;
1960 }
1961
1962 /**
1963 * \brief Get client/port address of a port_info container
1964 * \param info port_info container
1965 * \return client/port address pointer
1966 *
1967 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_addr()
1968 */
snd_seq_port_info_get_addr(const snd_seq_port_info_t * info)1969 const snd_seq_addr_t *snd_seq_port_info_get_addr(const snd_seq_port_info_t *info)
1970 {
1971 assert(info);
1972 return (const snd_seq_addr_t *) &info->addr;
1973 }
1974
1975 /**
1976 * \brief Get the name of a port_info container
1977 * \param info port_info container
1978 * \return name string
1979 *
1980 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_name()
1981 */
snd_seq_port_info_get_name(const snd_seq_port_info_t * info)1982 const char *snd_seq_port_info_get_name(const snd_seq_port_info_t *info)
1983 {
1984 assert(info);
1985 return info->name;
1986 }
1987
1988 /**
1989 * \brief Get the capability bits of a port_info container
1990 * \param info port_info container
1991 * \return capability bits
1992 *
1993 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_capability()
1994 */
snd_seq_port_info_get_capability(const snd_seq_port_info_t * info)1995 unsigned int snd_seq_port_info_get_capability(const snd_seq_port_info_t *info)
1996 {
1997 assert(info);
1998 return info->capability;
1999 }
2000
2001 /**
2002 * \brief Get the type bits of a port_info container
2003 * \param info port_info container
2004 * \return port type bits
2005 *
2006 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_type()
2007 */
snd_seq_port_info_get_type(const snd_seq_port_info_t * info)2008 unsigned int snd_seq_port_info_get_type(const snd_seq_port_info_t *info)
2009 {
2010 assert(info);
2011 return info->type;
2012 }
2013
2014 /**
2015 * \brief Get the number of read subscriptions of a port_info container
2016 * \param info port_info container
2017 * \return number of read subscriptions
2018 *
2019 * \sa snd_seq_get_port_info()
2020 */
snd_seq_port_info_get_read_use(const snd_seq_port_info_t * info)2021 int snd_seq_port_info_get_read_use(const snd_seq_port_info_t *info)
2022 {
2023 assert(info);
2024 return info->read_use;
2025 }
2026
2027 /**
2028 * \brief Get the number of write subscriptions of a port_info container
2029 * \param info port_info container
2030 * \return number of write subscriptions
2031 *
2032 * \sa snd_seq_get_port_info()
2033 */
snd_seq_port_info_get_write_use(const snd_seq_port_info_t * info)2034 int snd_seq_port_info_get_write_use(const snd_seq_port_info_t *info)
2035 {
2036 assert(info);
2037 return info->write_use;
2038 }
2039
2040 /**
2041 * \brief Get the midi channels of a port_info container
2042 * \param info port_info container
2043 * \return number of midi channels (default 0)
2044 *
2045 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_midi_channels()
2046 */
snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t * info)2047 int snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t *info)
2048 {
2049 assert(info);
2050 return info->midi_channels;
2051 }
2052
2053 /**
2054 * \brief Get the midi voices of a port_info container
2055 * \param info port_info container
2056 * \return number of midi voices (default 0)
2057 *
2058 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_midi_voices()
2059 */
snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t * info)2060 int snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t *info)
2061 {
2062 assert(info);
2063 return info->midi_voices;
2064 }
2065
2066 /**
2067 * \brief Get the synth voices of a port_info container
2068 * \param info port_info container
2069 * \return number of synth voices (default 0)
2070 *
2071 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_synth_voices()
2072 */
snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t * info)2073 int snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t *info)
2074 {
2075 assert(info);
2076 return info->synth_voices;
2077 }
2078
2079 /**
2080 * \brief Get the port-specified mode of a port_info container
2081 * \param info port_info container
2082 * \return 1 if port id is specified at creation
2083 *
2084 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port_specified()
2085 */
snd_seq_port_info_get_port_specified(const snd_seq_port_info_t * info)2086 int snd_seq_port_info_get_port_specified(const snd_seq_port_info_t *info)
2087 {
2088 assert(info);
2089 return (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? 1 : 0;
2090 }
2091
2092 /**
2093 * \brief Get the time-stamping mode of the given port in a port_info container
2094 * \param info port_info container
2095 * \return 1 if the port updates timestamps of incoming events
2096 *
2097 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamping()
2098 */
snd_seq_port_info_get_timestamping(const snd_seq_port_info_t * info)2099 int snd_seq_port_info_get_timestamping(const snd_seq_port_info_t *info)
2100 {
2101 assert(info);
2102 return (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
2103 }
2104
2105 /**
2106 * \brief Get whether the time-stamping of the given port is real-time mode
2107 * \param info port_info container
2108 * \return 1 if the time-stamping is in the real-time mode
2109 *
2110 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_real()
2111 */
snd_seq_port_info_get_timestamp_real(const snd_seq_port_info_t * info)2112 int snd_seq_port_info_get_timestamp_real(const snd_seq_port_info_t *info)
2113 {
2114 assert(info);
2115 return (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
2116 }
2117
2118 /**
2119 * \brief Get the queue id to update timestamps
2120 * \param info port_info container
2121 * \return the queue id to get the timestamps
2122 *
2123 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_queue()
2124 */
snd_seq_port_info_get_timestamp_queue(const snd_seq_port_info_t * info)2125 int snd_seq_port_info_get_timestamp_queue(const snd_seq_port_info_t *info)
2126 {
2127 assert(info);
2128 return info->time_queue;
2129 }
2130
2131 /**
2132 * \brief Set the client id of a port_info container
2133 * \param info port_info container
2134 * \param client client id
2135 *
2136 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_client()
2137 */
snd_seq_port_info_set_client(snd_seq_port_info_t * info,int client)2138 void snd_seq_port_info_set_client(snd_seq_port_info_t *info, int client)
2139 {
2140 assert(info);
2141 info->addr.client = client;
2142 }
2143
2144 /**
2145 * \brief Set the port id of a port_info container
2146 * \param info port_info container
2147 * \param port port id
2148 *
2149 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port()
2150 */
snd_seq_port_info_set_port(snd_seq_port_info_t * info,int port)2151 void snd_seq_port_info_set_port(snd_seq_port_info_t *info, int port)
2152 {
2153 assert(info);
2154 info->addr.port = port;
2155 }
2156
2157 /**
2158 * \brief Set the client/port address of a port_info container
2159 * \param info port_info container
2160 * \param addr client/port address
2161 *
2162 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_addr()
2163 */
snd_seq_port_info_set_addr(snd_seq_port_info_t * info,const snd_seq_addr_t * addr)2164 void snd_seq_port_info_set_addr(snd_seq_port_info_t *info, const snd_seq_addr_t *addr)
2165 {
2166 assert(info);
2167 info->addr = *(const struct sndrv_seq_addr *)addr;
2168 }
2169
2170 /**
2171 * \brief Set the name of a port_info container
2172 * \param info port_info container
2173 * \param name name string
2174 *
2175 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_name()
2176 */
snd_seq_port_info_set_name(snd_seq_port_info_t * info,const char * name)2177 void snd_seq_port_info_set_name(snd_seq_port_info_t *info, const char *name)
2178 {
2179 assert(info && name);
2180 snd_strlcpy(info->name, name, sizeof(info->name));
2181 }
2182
2183 /**
2184 * \brief set the capability bits of a port_info container
2185 * \param info port_info container
2186 * \param capability capability bits
2187 *
2188 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_capability()
2189 */
snd_seq_port_info_set_capability(snd_seq_port_info_t * info,unsigned int capability)2190 void snd_seq_port_info_set_capability(snd_seq_port_info_t *info, unsigned int capability)
2191 {
2192 assert(info);
2193 info->capability = capability;
2194 }
2195
2196 /**
2197 * \brief Get the type bits of a port_info container
2198 * \param info port_info container
2199 * \param type port type bits
2200 *
2201 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_type()
2202 */
snd_seq_port_info_set_type(snd_seq_port_info_t * info,unsigned int type)2203 void snd_seq_port_info_set_type(snd_seq_port_info_t *info, unsigned int type)
2204 {
2205 assert(info);
2206 info->type = type;
2207 }
2208
2209 /**
2210 * \brief set the midi channels of a port_info container
2211 * \param info port_info container
2212 * \param channels midi channels (default 0)
2213 *
2214 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_midi_channels()
2215 */
snd_seq_port_info_set_midi_channels(snd_seq_port_info_t * info,int channels)2216 void snd_seq_port_info_set_midi_channels(snd_seq_port_info_t *info, int channels)
2217 {
2218 assert(info);
2219 info->midi_channels = channels;
2220 }
2221
2222 /**
2223 * \brief set the midi voices of a port_info container
2224 * \param info port_info container
2225 * \param voices midi voices (default 0)
2226 *
2227 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_midi_voices()
2228 */
snd_seq_port_info_set_midi_voices(snd_seq_port_info_t * info,int voices)2229 void snd_seq_port_info_set_midi_voices(snd_seq_port_info_t *info, int voices)
2230 {
2231 assert(info);
2232 info->midi_voices = voices;
2233 }
2234
2235 /**
2236 * \brief set the synth voices of a port_info container
2237 * \param info port_info container
2238 * \param voices synth voices (default 0)
2239 *
2240 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_synth_voice()
2241 */
snd_seq_port_info_set_synth_voices(snd_seq_port_info_t * info,int voices)2242 void snd_seq_port_info_set_synth_voices(snd_seq_port_info_t *info, int voices)
2243 {
2244 assert(info);
2245 info->synth_voices = voices;
2246 }
2247
2248 /**
2249 * \brief Set the port-specified mode of a port_info container
2250 * \param info port_info container
2251 * \param val non-zero if specifying the port id at creation
2252 *
2253 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port_specified()
2254 */
snd_seq_port_info_set_port_specified(snd_seq_port_info_t * info,int val)2255 void snd_seq_port_info_set_port_specified(snd_seq_port_info_t *info, int val)
2256 {
2257 assert(info);
2258 if (val)
2259 info->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
2260 else
2261 info->flags &= ~SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
2262 }
2263
2264 /**
2265 * \brief Set the time-stamping mode of the given port
2266 * \param info port_info container
2267 * \param enable non-zero if updating the timestamps of incoming events
2268 *
2269 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamping()
2270 */
snd_seq_port_info_set_timestamping(snd_seq_port_info_t * info,int enable)2271 void snd_seq_port_info_set_timestamping(snd_seq_port_info_t *info, int enable)
2272 {
2273 assert(info);
2274 if (enable)
2275 info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
2276 else
2277 info->flags &= ~SNDRV_SEQ_PORT_FLG_TIMESTAMP;
2278 }
2279
2280 /**
2281 * \brief Set whether the timestime is updated in the real-time mode
2282 * \param info port_info container
2283 * \param enable non-zero if updating the timestamps in real-time mode
2284 *
2285 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_real()
2286 */
snd_seq_port_info_set_timestamp_real(snd_seq_port_info_t * info,int enable)2287 void snd_seq_port_info_set_timestamp_real(snd_seq_port_info_t *info, int enable)
2288 {
2289 assert(info);
2290 if (enable)
2291 info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
2292 else
2293 info->flags &= ~SNDRV_SEQ_PORT_FLG_TIME_REAL;
2294 }
2295
2296 /**
2297 * \brief Set the queue id for timestamping
2298 * \param info port_info container
2299 * \param queue the queue id to get timestamps
2300 *
2301 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_queue()
2302 */
snd_seq_port_info_set_timestamp_queue(snd_seq_port_info_t * info,int queue)2303 void snd_seq_port_info_set_timestamp_queue(snd_seq_port_info_t *info, int queue)
2304 {
2305 assert(info);
2306 info->time_queue = queue;
2307 }
2308
2309
2310 /**
2311 * \brief create a sequencer port on the current client
2312 * \param seq sequencer handle
2313 * \param port port information for the new port
2314 * \return 0 on success otherwise a negative error code
2315 *
2316 * Creates a sequencer port on the current client.
2317 * The attributes of created port is specified in \a info argument.
2318 *
2319 * The client field in \a info argument is overwritten with the current client id.
2320 * The port id to be created can be specified via #snd_seq_port_info_set_port_specified.
2321 * You can get the created port id by reading the port pointer via #snd_seq_port_info_get_port.
2322 *
2323 * Each port has the capability bit-masks to specify the access capability
2324 * of the port from other clients.
2325 * The capability bit flags are defined as follows:
2326 * - #SND_SEQ_PORT_CAP_READ Readable from this port
2327 * - #SND_SEQ_PORT_CAP_WRITE Writable to this port.
2328 * - #SND_SEQ_PORT_CAP_SYNC_READ For synchronization (not implemented)
2329 * - #SND_SEQ_PORT_CAP_SYNC_WRITE For synchronization (not implemented)
2330 * - #SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported
2331 * - #SND_SEQ_PORT_CAP_SUBS_READ Read subscription is allowed
2332 * - #SND_SEQ_PORT_CAP_SUBS_WRITE Write subscription is allowed
2333 * - #SND_SEQ_PORT_CAP_NO_EXPORT Subscription management from 3rd client is disallowed
2334 *
2335 * Each port has also the type bitmasks defined as follows:
2336 * - #SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port
2337 * - #SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device
2338 * - #SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device
2339 * - #SND_SEQ_PORT_TYPE_MIDI_GM2 General MIDI 2 compatible device
2340 * - #SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device
2341 * - #SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device
2342 * - #SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device
2343 * - #SND_SEQ_PORT_TYPE_HARDWARE Implemented in hardware
2344 * - #SND_SEQ_PORT_TYPE_SOFTWARE Implemented in software
2345 * - #SND_SEQ_PORT_TYPE_SYNTHESIZER Generates sound
2346 * - #SND_SEQ_PORT_TYPE_PORT Connects to other device(s)
2347 * - #SND_SEQ_PORT_TYPE_APPLICATION Application (sequencer/editor)
2348 *
2349 * A port may contain specific midi channels, midi voices and synth voices.
2350 * These values could be zero as default.
2351 *
2352 * \sa snd_seq_delete_port(), snd_seq_get_port_info(),
2353 * snd_seq_create_simple_port()
2354 */
snd_seq_create_port(snd_seq_t * seq,snd_seq_port_info_t * port)2355 int snd_seq_create_port(snd_seq_t *seq, snd_seq_port_info_t * port)
2356 {
2357 assert(seq && port);
2358 port->addr.client = seq->client;
2359 return seq->ops->create_port(seq, port);
2360 }
2361
2362 /**
2363 * \brief delete a sequencer port on the current client
2364 * \param seq sequencer handle
2365 * \param port port to be deleted
2366 * \return 0 on success otherwise a negative error code
2367 *
2368 * Deletes the existing sequencer port on the current client.
2369 *
2370 * \sa snd_seq_create_port(), snd_seq_delete_simple_port()
2371 */
snd_seq_delete_port(snd_seq_t * seq,int port)2372 int snd_seq_delete_port(snd_seq_t *seq, int port)
2373 {
2374 snd_seq_port_info_t pinfo;
2375 assert(seq);
2376 memset(&pinfo, 0, sizeof(pinfo));
2377 pinfo.addr.client = seq->client;
2378 pinfo.addr.port = port;
2379 return seq->ops->delete_port(seq, &pinfo);
2380 }
2381
2382 /**
2383 * \brief obtain the information of a port on an arbitrary client
2384 * \param seq sequencer handle
2385 * \param client client id to get
2386 * \param port port id to get
2387 * \param info pointer information returns
2388 * \return 0 on success otherwise a negative error code
2389 *
2390 * \sa snd_seq_get_port_info()
2391 */
snd_seq_get_any_port_info(snd_seq_t * seq,int client,int port,snd_seq_port_info_t * info)2392 int snd_seq_get_any_port_info(snd_seq_t *seq, int client, int port, snd_seq_port_info_t * info)
2393 {
2394 assert(seq && info && client >= 0 && port >= 0);
2395 memset(info, 0, sizeof(snd_seq_port_info_t));
2396 info->addr.client = client;
2397 info->addr.port = port;
2398 return seq->ops->get_port_info(seq, info);
2399 }
2400
2401 /**
2402 * \brief obtain the information of a port on the current client
2403 * \param seq sequencer handle
2404 * \param port port id to get
2405 * \param info pointer information returns
2406 * \return 0 on success otherwise a negative error code
2407 *
2408 * \sa snd_seq_create_port(), snd_seq_get_any_port_info(), snd_seq_set_port_info(),
2409 * snd_seq_query_next_port()
2410 */
snd_seq_get_port_info(snd_seq_t * seq,int port,snd_seq_port_info_t * info)2411 int snd_seq_get_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
2412 {
2413 return snd_seq_get_any_port_info(seq, seq->client, port, info);
2414 }
2415
2416 /**
2417 * \brief set the information of a port on the current client
2418 * \param seq sequencer handle
2419 * \param port port to be set
2420 * \param info port information to be set
2421 * \return 0 on success otherwise a negative error code
2422 *
2423 * \sa snd_seq_set_port_info()
2424 */
snd_seq_set_port_info(snd_seq_t * seq,int port,snd_seq_port_info_t * info)2425 int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
2426 {
2427 assert(seq && info && port >= 0);
2428 info->addr.client = seq->client;
2429 info->addr.port = port;
2430 return seq->ops->set_port_info(seq, info);
2431 }
2432
2433 /**
2434 * \brief query the next matching port
2435 * \param seq sequencer handle
2436 * \param info query pattern and result
2437
2438 * Queries the next matching port on the client specified in
2439 * \a info argument.
2440 * The search begins at the next port specified in
2441 * port field of \a info argument.
2442 * For finding the first port at a certain client, give -1.
2443 *
2444 * If a matching port is found, its attributes are stored on
2445 * \a info and function returns zero.
2446 * Otherwise, a negative error code is returned.
2447 *
2448 * \sa snd_seq_get_port_info()
2449 */
snd_seq_query_next_port(snd_seq_t * seq,snd_seq_port_info_t * info)2450 int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info)
2451 {
2452 assert(seq && info);
2453 return seq->ops->query_next_port(seq, info);
2454 }
2455
2456
2457 /*----------------------------------------------------------------*/
2458
2459 /*
2460 * subscription
2461 */
2462
2463
2464 /**
2465 * \brief get size of #snd_seq_port_subscribe_t
2466 * \return size in bytes
2467 */
snd_seq_port_subscribe_sizeof()2468 size_t snd_seq_port_subscribe_sizeof()
2469 {
2470 return sizeof(snd_seq_port_subscribe_t);
2471 }
2472
2473 /**
2474 * \brief allocate an empty #snd_seq_port_subscribe_t using standard malloc
2475 * \param ptr returned pointer
2476 * \return 0 on success otherwise negative error code
2477 */
snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t ** ptr)2478 int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr)
2479 {
2480 assert(ptr);
2481 *ptr = calloc(1, sizeof(snd_seq_port_subscribe_t));
2482 if (!*ptr)
2483 return -ENOMEM;
2484 return 0;
2485 }
2486
2487 /**
2488 * \brief frees a previously allocated #snd_seq_port_subscribe_t
2489 * \param obj pointer to object to free
2490 */
snd_seq_port_subscribe_free(snd_seq_port_subscribe_t * obj)2491 void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *obj)
2492 {
2493 free(obj);
2494 }
2495
2496 /**
2497 * \brief copy one #snd_seq_port_subscribe_t to another
2498 * \param dst pointer to destination
2499 * \param src pointer to source
2500 */
snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t * dst,const snd_seq_port_subscribe_t * src)2501 void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src)
2502 {
2503 assert(dst && src);
2504 *dst = *src;
2505 }
2506
2507
2508 /**
2509 * \brief Get sender address of a port_subscribe container
2510 * \param info port_subscribe container
2511 *
2512 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_sender()
2513 */
snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t * info)2514 const snd_seq_addr_t *snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t *info)
2515 {
2516 assert(info);
2517 return (const snd_seq_addr_t *)&info->sender;
2518 }
2519
2520 /**
2521 * \brief Get destination address of a port_subscribe container
2522 * \param info port_subscribe container
2523 *
2524 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_dest()
2525 */
snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t * info)2526 const snd_seq_addr_t *snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t *info)
2527 {
2528 assert(info);
2529 return (const snd_seq_addr_t *)&info->dest;
2530 }
2531
2532 /**
2533 * \brief Get the queue id of a port_subscribe container
2534 * \param info port_subscribe container
2535 * \return queue id
2536 *
2537 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_queue()
2538 */
snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t * info)2539 int snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t *info)
2540 {
2541 assert(info);
2542 return info->queue;
2543 }
2544
2545 /**
2546 * \brief Get the exclusive mode of a port_subscribe container
2547 * \param info port_subscribe container
2548 * \return 1 if exclusive mode
2549 *
2550 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_exclusive()
2551 */
snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t * info)2552 int snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t *info)
2553 {
2554 assert(info);
2555 return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
2556 }
2557
2558 /**
2559 * \brief Get the time-update mode of a port_subscribe container
2560 * \param info port_subscribe container
2561 * \return 1 if update timestamp
2562 *
2563 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_time_update()
2564 */
snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t * info)2565 int snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t *info)
2566 {
2567 assert(info);
2568 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2569 }
2570
2571 /**
2572 * \brief Get the real-time update mode of a port_subscribe container
2573 * \param info port_subscribe container
2574 * \return 1 if real-time update mode
2575 *
2576 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_time_real()
2577 */
snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t * info)2578 int snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t *info)
2579 {
2580 assert(info);
2581 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 1 : 0;
2582 }
2583
2584 /**
2585 * \brief Set sender address of a port_subscribe container
2586 * \param info port_subscribe container
2587 * \param addr sender address
2588 *
2589 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_sender()
2590 */
snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t * info,const snd_seq_addr_t * addr)2591 void snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
2592 {
2593 assert(info);
2594 memcpy(&info->sender, addr, sizeof(*addr));
2595 }
2596
2597 /**
2598 * \brief Set destination address of a port_subscribe container
2599 * \param info port_subscribe container
2600 * \param addr destination address
2601 *
2602 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_dest()
2603 */
snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t * info,const snd_seq_addr_t * addr)2604 void snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
2605 {
2606 assert(info);
2607 memcpy(&info->dest, addr, sizeof(*addr));
2608 }
2609
2610 /**
2611 * \brief Set the queue id of a port_subscribe container
2612 * \param info port_subscribe container
2613 * \param q queue id
2614 *
2615 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_queue()
2616 */
snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t * info,int q)2617 void snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t *info, int q)
2618 {
2619 assert(info);
2620 info->queue = q;
2621 }
2622
2623 /**
2624 * \brief Set the exclusive mode of a port_subscribe container
2625 * \param info port_subscribe container
2626 * \param val non-zero to enable
2627 *
2628 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_exclusive()
2629 */
snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t * info,int val)2630 void snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t *info, int val)
2631 {
2632 assert(info);
2633 if (val)
2634 info->flags |= SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
2635 else
2636 info->flags &= ~SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
2637 }
2638
2639 /**
2640 * \brief Set the time-update mode of a port_subscribe container
2641 * \param info port_subscribe container
2642 * \param val non-zero to enable
2643 *
2644 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_update()
2645 */
snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t * info,int val)2646 void snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t *info, int val)
2647 {
2648 assert(info);
2649 if (val)
2650 info->flags |= SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
2651 else
2652 info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
2653 }
2654
2655 /**
2656 * \brief Set the real-time mode of a port_subscribe container
2657 * \param info port_subscribe container
2658 * \param val non-zero to enable
2659 *
2660 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_real()
2661 */
snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t * info,int val)2662 void snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t *info, int val)
2663 {
2664 assert(info);
2665 if (val)
2666 info->flags |= SNDRV_SEQ_PORT_SUBS_TIME_REAL;
2667 else
2668 info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIME_REAL;
2669 }
2670
2671
2672 /**
2673 * \brief obtain subscription information
2674 * \param seq sequencer handle
2675 * \param sub pointer to return the subscription information
2676 * \return 0 on success otherwise a negative error code
2677 *
2678 * \sa snd_seq_subscribe_port(), snd_seq_query_port_subscribers()
2679 */
snd_seq_get_port_subscription(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2680 int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2681 {
2682 assert(seq && sub);
2683 return seq->ops->get_port_subscription(seq, sub);
2684 }
2685
2686 /**
2687 * \brief subscribe a port connection
2688 * \param seq sequencer handle
2689 * \param sub subscription information
2690 * \return 0 on success otherwise a negative error code
2691 *
2692 * Subscribes a connection between two ports.
2693 * The subscription information is stored in sub argument.
2694 *
2695 * \sa snd_seq_get_port_subscription(), snd_seq_unsubscribe_port(),
2696 * snd_seq_connect_from(), snd_seq_connect_to()
2697 */
snd_seq_subscribe_port(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2698 int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2699 {
2700 assert(seq && sub);
2701 return seq->ops->subscribe_port(seq, sub);
2702 }
2703
2704 /**
2705 * \brief unsubscribe a connection between ports
2706 * \param seq sequencer handle
2707 * \param sub subscription information to disconnect
2708 * \return 0 on success otherwise a negative error code
2709 *
2710 * Unsubscribes a connection between two ports,
2711 * described in sender and dest fields in sub argument.
2712 *
2713 * \sa snd_seq_subscribe_port(), snd_seq_disconnect_from(), snd_seq_disconnect_to()
2714 */
snd_seq_unsubscribe_port(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2715 int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2716 {
2717 assert(seq && sub);
2718 return seq->ops->unsubscribe_port(seq, sub);
2719 }
2720
2721
2722 /**
2723 * \brief get size of #snd_seq_query_subscribe_t
2724 * \return size in bytes
2725 */
snd_seq_query_subscribe_sizeof()2726 size_t snd_seq_query_subscribe_sizeof()
2727 {
2728 return sizeof(snd_seq_query_subscribe_t);
2729 }
2730
2731 /**
2732 * \brief allocate an empty #snd_seq_query_subscribe_t using standard malloc
2733 * \param ptr returned pointer
2734 * \return 0 on success otherwise negative error code
2735 */
snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t ** ptr)2736 int snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t **ptr)
2737 {
2738 assert(ptr);
2739 *ptr = calloc(1, sizeof(snd_seq_query_subscribe_t));
2740 if (!*ptr)
2741 return -ENOMEM;
2742 return 0;
2743 }
2744
2745 /**
2746 * \brief frees a previously allocated #snd_seq_query_subscribe_t
2747 * \param obj pointer to object to free
2748 */
snd_seq_query_subscribe_free(snd_seq_query_subscribe_t * obj)2749 void snd_seq_query_subscribe_free(snd_seq_query_subscribe_t *obj)
2750 {
2751 free(obj);
2752 }
2753
2754 /**
2755 * \brief copy one #snd_seq_query_subscribe_t to another
2756 * \param dst pointer to destination
2757 * \param src pointer to source
2758 */
snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t * dst,const snd_seq_query_subscribe_t * src)2759 void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src)
2760 {
2761 assert(dst && src);
2762 *dst = *src;
2763 }
2764
2765
2766 /**
2767 * \brief Get the client id of a query_subscribe container
2768 * \param info query_subscribe container
2769 * \return client id
2770 *
2771 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_client()
2772 */
snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t * info)2773 int snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t *info)
2774 {
2775 assert(info);
2776 return info->root.client;
2777 }
2778
2779 /**
2780 * \brief Get the port id of a query_subscribe container
2781 * \param info query_subscribe container
2782 * \return port id
2783 *
2784 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_port()
2785 */
snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t * info)2786 int snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t *info)
2787 {
2788 assert(info);
2789 return info->root.port;
2790 }
2791
2792 /**
2793 * \brief Get the client/port address of a query_subscribe container
2794 * \param info query_subscribe container
2795 * \return client/port address pointer
2796 *
2797 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_root()
2798 */
snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t * info)2799 const snd_seq_addr_t *snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t *info)
2800 {
2801 assert(info);
2802 return (const snd_seq_addr_t *)&info->root;
2803 }
2804
2805 /**
2806 * \brief Get the query type of a query_subscribe container
2807 * \param info query_subscribe container
2808 * \return query type
2809 *
2810 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_type()
2811 */
snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t * info)2812 snd_seq_query_subs_type_t snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t *info)
2813 {
2814 assert(info);
2815 return info->type;
2816 }
2817
2818 /**
2819 * \brief Get the index of subscriber of a query_subscribe container
2820 * \param info query_subscribe container
2821 * \return subscriber's index
2822 *
2823 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_index()
2824 */
snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t * info)2825 int snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t *info)
2826 {
2827 assert(info);
2828 return info->index;
2829 }
2830
2831 /**
2832 * \brief Get the number of subscriptions of a query_subscribe container
2833 * \param info query_subscribe container
2834 * \return number of subscriptions
2835 *
2836 * \sa snd_seq_query_port_subscribers()
2837 */
snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t * info)2838 int snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t *info)
2839 {
2840 assert(info);
2841 return info->num_subs;
2842 }
2843
2844 /**
2845 * \brief Get the address of subscriber of a query_subscribe container
2846 * \param info query_subscribe container
2847 * \return subscriber's address pointer
2848 *
2849 * \sa snd_seq_query_port_subscribers()
2850 */
snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t * info)2851 const snd_seq_addr_t *snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t *info)
2852 {
2853 assert(info);
2854 return (const snd_seq_addr_t *)&info->addr;
2855 }
2856
2857 /**
2858 * \brief Get the queue id of subscriber of a query_subscribe container
2859 * \param info query_subscribe container
2860 * \return subscriber's queue id
2861 *
2862 * \sa snd_seq_query_port_subscribers()
2863 */
snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t * info)2864 int snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t *info)
2865 {
2866 assert(info);
2867 return info->queue;
2868 }
2869
2870 /**
2871 * \brief Get the exclusive mode of a query_subscribe container
2872 * \param info query_subscribe container
2873 * \return 1 if exclusive mode
2874 *
2875 * \sa snd_seq_query_port_subscribers()
2876 */
snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t * info)2877 int snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t *info)
2878 {
2879 assert(info);
2880 return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
2881 }
2882
2883 /**
2884 * \brief Get the time-update mode of a query_subscribe container
2885 * \param info query_subscribe container
2886 * \return 1 if update timestamp
2887 *
2888 * \sa snd_seq_query_port_subscribers()
2889 */
snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t * info)2890 int snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t *info)
2891 {
2892 assert(info);
2893 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2894 }
2895
2896 /**
2897 * \brief Get the real-time update mode of a query_subscribe container
2898 * \param info query_subscribe container
2899 * \return 1 if real-time update mode
2900 *
2901 * \sa snd_seq_query_port_subscribers()
2902 */
snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t * info)2903 int snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t *info)
2904 {
2905 assert(info);
2906 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2907 }
2908
2909 /**
2910 * \brief Set the client id of a query_subscribe container
2911 * \param info query_subscribe container
2912 * \param client client id
2913 *
2914 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_client()
2915 */
snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t * info,int client)2916 void snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t *info, int client)
2917 {
2918 assert(info);
2919 info->root.client = client;
2920 }
2921
2922 /**
2923 * \brief Set the port id of a query_subscribe container
2924 * \param info query_subscribe container
2925 * \param port port id
2926 *
2927 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_port()
2928 */
snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t * info,int port)2929 void snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t *info, int port)
2930 {
2931 assert(info);
2932 info->root.port = port;
2933 }
2934
2935 /**
2936 * \brief Set the client/port address of a query_subscribe container
2937 * \param info query_subscribe container
2938 * \param addr client/port address pointer
2939 *
2940 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_root()
2941 */
snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t * info,const snd_seq_addr_t * addr)2942 void snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t *info, const snd_seq_addr_t *addr)
2943 {
2944 assert(info);
2945 info->root = *(const struct snd_seq_addr *)addr;
2946 }
2947
2948 /**
2949 * \brief Set the query type of a query_subscribe container
2950 * \param info query_subscribe container
2951 * \param type query type
2952 *
2953 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_type()
2954 */
snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t * info,snd_seq_query_subs_type_t type)2955 void snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t *info, snd_seq_query_subs_type_t type)
2956 {
2957 assert(info);
2958 info->type = type;
2959 }
2960
2961 /**
2962 * \brief Set the subscriber's index to be queried
2963 * \param info query_subscribe container
2964 * \param index index to be queried
2965 *
2966 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_index()
2967 */
snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t * info,int index)2968 void snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t *info, int index)
2969 {
2970 assert(info);
2971 info->index = index;
2972 }
2973
2974
2975 /**
2976 * \brief query port subscriber list
2977 * \param seq sequencer handle
2978 * \param subs subscription to query
2979 * \return 0 on success otherwise a negative error code
2980 *
2981 * Queries the subscribers accessing to a port.
2982 * The query information is specified in subs argument.
2983 *
2984 * At least, the client id, the port id, the index number and
2985 * the query type must be set to perform a proper query.
2986 * As the query type, #SND_SEQ_QUERY_SUBS_READ or #SND_SEQ_QUERY_SUBS_WRITE
2987 * can be specified to check whether the readers or the writers to the port.
2988 * To query the first subscription, set 0 to the index number. To list up
2989 * all the subscriptions, call this function with the index numbers from 0
2990 * until this returns a negative value.
2991 *
2992 * \sa snd_seq_get_port_subscription()
2993 */
snd_seq_query_port_subscribers(snd_seq_t * seq,snd_seq_query_subscribe_t * subs)2994 int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs)
2995 {
2996 assert(seq && subs);
2997 return seq->ops->query_port_subscribers(seq, subs);
2998 }
2999
3000 /*----------------------------------------------------------------*/
3001
3002 /*
3003 * queue handlers
3004 */
3005
3006 /**
3007 * \brief get size of #snd_seq_queue_info_t
3008 * \return size in bytes
3009 */
snd_seq_queue_info_sizeof()3010 size_t snd_seq_queue_info_sizeof()
3011 {
3012 return sizeof(snd_seq_queue_info_t);
3013 }
3014
3015 /**
3016 * \brief allocate an empty #snd_seq_queue_info_t using standard malloc
3017 * \param ptr returned pointer
3018 * \return 0 on success otherwise negative error code
3019 */
snd_seq_queue_info_malloc(snd_seq_queue_info_t ** ptr)3020 int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr)
3021 {
3022 assert(ptr);
3023 *ptr = calloc(1, sizeof(snd_seq_queue_info_t));
3024 if (!*ptr)
3025 return -ENOMEM;
3026 return 0;
3027 }
3028
3029 /**
3030 * \brief frees a previously allocated #snd_seq_queue_info_t
3031 * \param obj pointer to object to free
3032 */
snd_seq_queue_info_free(snd_seq_queue_info_t * obj)3033 void snd_seq_queue_info_free(snd_seq_queue_info_t *obj)
3034 {
3035 free(obj);
3036 }
3037
3038 /**
3039 * \brief copy one #snd_seq_queue_info_t to another
3040 * \param dst pointer to destination
3041 * \param src pointer to source
3042 */
snd_seq_queue_info_copy(snd_seq_queue_info_t * dst,const snd_seq_queue_info_t * src)3043 void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src)
3044 {
3045 assert(dst && src);
3046 *dst = *src;
3047 }
3048
3049
3050 /**
3051 * \brief Get the queue id of a queue_info container
3052 * \param info queue_info container
3053 * \return queue id
3054 *
3055 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_queue()
3056 */
snd_seq_queue_info_get_queue(const snd_seq_queue_info_t * info)3057 int snd_seq_queue_info_get_queue(const snd_seq_queue_info_t *info)
3058 {
3059 assert(info);
3060 return info->queue;
3061 }
3062
3063 /**
3064 * \brief Get the name of a queue_info container
3065 * \param info queue_info container
3066 * \return name string
3067 *
3068 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_name()
3069 */
snd_seq_queue_info_get_name(const snd_seq_queue_info_t * info)3070 const char *snd_seq_queue_info_get_name(const snd_seq_queue_info_t *info)
3071 {
3072 assert(info);
3073 return info->name;
3074 }
3075
3076 /**
3077 * \brief Get the owner client id of a queue_info container
3078 * \param info queue_info container
3079 * \return owner client id
3080 *
3081 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_owner()
3082 */
snd_seq_queue_info_get_owner(const snd_seq_queue_info_t * info)3083 int snd_seq_queue_info_get_owner(const snd_seq_queue_info_t *info)
3084 {
3085 assert(info);
3086 return info->owner;
3087 }
3088
3089 /**
3090 * \brief Get the lock status of a queue_info container
3091 * \param info queue_info container
3092 * \return lock status --- non-zero = locked
3093 *
3094 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_locked()
3095 */
snd_seq_queue_info_get_locked(const snd_seq_queue_info_t * info)3096 int snd_seq_queue_info_get_locked(const snd_seq_queue_info_t *info)
3097 {
3098 assert(info);
3099 return info->locked;
3100 }
3101
3102 /**
3103 * \brief Get the conditional bit flags of a queue_info container
3104 * \param info queue_info container
3105 * \return conditional bit flags
3106 *
3107 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_flags()
3108 */
snd_seq_queue_info_get_flags(const snd_seq_queue_info_t * info)3109 unsigned int snd_seq_queue_info_get_flags(const snd_seq_queue_info_t *info)
3110 {
3111 assert(info);
3112 return info->flags;
3113 }
3114
3115 /**
3116 * \brief Set the name of a queue_info container
3117 * \param info queue_info container
3118 * \param name name string
3119 *
3120 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_name()
3121 */
snd_seq_queue_info_set_name(snd_seq_queue_info_t * info,const char * name)3122 void snd_seq_queue_info_set_name(snd_seq_queue_info_t *info, const char *name)
3123 {
3124 assert(info && name);
3125 snd_strlcpy(info->name, name, sizeof(info->name));
3126 }
3127
3128 /**
3129 * \brief Set the owner client id of a queue_info container
3130 * \param info queue_info container
3131 * \param owner client id
3132 *
3133 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_owner()
3134 */
snd_seq_queue_info_set_owner(snd_seq_queue_info_t * info,int owner)3135 void snd_seq_queue_info_set_owner(snd_seq_queue_info_t *info, int owner)
3136 {
3137 assert(info);
3138 info->owner = owner;
3139 }
3140
3141 /**
3142 * \brief Set the lock status of a queue_info container
3143 * \param info queue_info container
3144 * \param locked lock status
3145 *
3146 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_locked()
3147 */
snd_seq_queue_info_set_locked(snd_seq_queue_info_t * info,int locked)3148 void snd_seq_queue_info_set_locked(snd_seq_queue_info_t *info, int locked)
3149 {
3150 assert(info);
3151 info->locked = locked;
3152 }
3153
3154 /**
3155 * \brief Set the conditional bit flags of a queue_info container
3156 * \param info queue_info container
3157 * \param flags conditional bit flags
3158 *
3159 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_flags()
3160 */
snd_seq_queue_info_set_flags(snd_seq_queue_info_t * info,unsigned int flags)3161 void snd_seq_queue_info_set_flags(snd_seq_queue_info_t *info, unsigned int flags)
3162 {
3163 assert(info);
3164 info->flags = flags;
3165 }
3166
3167
3168 /**
3169 * \brief create a queue
3170 * \param seq sequencer handle
3171 * \param info queue information to initialize
3172 * \return the queue id (zero or positive) on success otherwise a negative error code
3173 *
3174 * \sa snd_seq_alloc_queue()
3175 */
snd_seq_create_queue(snd_seq_t * seq,snd_seq_queue_info_t * info)3176 int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
3177 {
3178 int err;
3179 assert(seq && info);
3180 info->owner = seq->client;
3181 err = seq->ops->create_queue(seq, info);
3182 if (err < 0)
3183 return err;
3184 return info->queue;
3185 }
3186
3187 /**
3188 * \brief allocate a queue with the specified name
3189 * \param seq sequencer handle
3190 * \param name the name of the new queue
3191 * \return the queue id (zero or positive) on success otherwise a negative error code
3192 *
3193 * \sa snd_seq_alloc_queue()
3194 */
snd_seq_alloc_named_queue(snd_seq_t * seq,const char * name)3195 int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name)
3196 {
3197 snd_seq_queue_info_t info;
3198 memset(&info, 0, sizeof(info));
3199 info.locked = 1;
3200 if (name)
3201 snd_strlcpy(info.name, name, sizeof(info.name));
3202 return snd_seq_create_queue(seq, &info);
3203 }
3204
3205 /**
3206 * \brief allocate a queue
3207 * \param seq sequencer handle
3208 * \return the queue id (zero or positive) on success otherwise a negative error code
3209 *
3210 * \sa snd_seq_alloc_named_queue(), snd_seq_create_queue(), snd_seq_free_queue(),
3211 * snd_seq_get_queue_info()
3212 */
snd_seq_alloc_queue(snd_seq_t * seq)3213 int snd_seq_alloc_queue(snd_seq_t *seq)
3214 {
3215 return snd_seq_alloc_named_queue(seq, NULL);
3216 }
3217
3218 /**
3219 * \brief delete the specified queue
3220 * \param seq sequencer handle
3221 * \param q queue id to delete
3222 * \return 0 on success otherwise a negative error code
3223 *
3224 * \sa snd_seq_alloc_queue()
3225 */
snd_seq_free_queue(snd_seq_t * seq,int q)3226 int snd_seq_free_queue(snd_seq_t *seq, int q)
3227 {
3228 snd_seq_queue_info_t info;
3229 assert(seq);
3230 memset(&info, 0, sizeof(info));
3231 info.queue = q;
3232 return seq->ops->delete_queue(seq, &info);
3233 }
3234
3235 /**
3236 * \brief obtain queue attributes
3237 * \param seq sequencer handle
3238 * \param q queue id to query
3239 * \param info information returned
3240 * \return 0 on success otherwise a negative error code
3241 *
3242 * \sa snd_seq_alloc_queue(), snd_seq_set_queue_info(), snd_seq_query_named_queue()
3243 */
snd_seq_get_queue_info(snd_seq_t * seq,int q,snd_seq_queue_info_t * info)3244 int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
3245 {
3246 assert(seq && info);
3247 info->queue = q;
3248 return seq->ops->get_queue_info(seq, info);
3249 }
3250
3251 /**
3252 * \brief change the queue attributes
3253 * \param seq sequencer handle
3254 * \param q queue id to change
3255 * \param info information changed
3256 * \return 0 on success otherwise a negative error code
3257 *
3258 * \sa snd_seq_get_queue_info()
3259 */
snd_seq_set_queue_info(snd_seq_t * seq,int q,snd_seq_queue_info_t * info)3260 int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
3261 {
3262 assert(seq && info);
3263 info->queue = q;
3264 return seq->ops->set_queue_info(seq, info);
3265 }
3266
3267 /**
3268 * \brief query the matching queue with the specified name
3269 * \param seq sequencer handle
3270 * \param name the name string to query
3271 * \return the queue id if found or negative error code
3272 *
3273 * Searches the matching queue with the specified name string.
3274 *
3275 * \sa snd_seq_get_queue_info()
3276 */
snd_seq_query_named_queue(snd_seq_t * seq,const char * name)3277 int snd_seq_query_named_queue(snd_seq_t *seq, const char *name)
3278 {
3279 int err;
3280 snd_seq_queue_info_t info;
3281 assert(seq && name);
3282 snd_strlcpy(info.name, name, sizeof(info.name));
3283 err = seq->ops->get_named_queue(seq, &info);
3284 if (err < 0)
3285 return err;
3286 return info.queue;
3287 }
3288
3289 /**
3290 * \brief Get the queue usage flag to the client
3291 * \param seq sequencer handle
3292 * \param q queue id
3293 * \return 1 = client is allowed to access the queue, 0 = not allowed,
3294 * otherwise a negative error code
3295 *
3296 * \sa snd_seq_get_queue_info(), snd_seq_set_queue_usage()
3297 */
snd_seq_get_queue_usage(snd_seq_t * seq,int q)3298 int snd_seq_get_queue_usage(snd_seq_t *seq, int q)
3299 {
3300 struct snd_seq_queue_client info;
3301 int err;
3302 assert(seq);
3303 memset(&info, 0, sizeof(info));
3304 info.queue = q;
3305 info.client = seq->client;
3306 if ((err = seq->ops->get_queue_client(seq, &info)) < 0)
3307 return err;
3308 return info.used;
3309 }
3310
3311 /**
3312 * \brief Set the queue usage flag to the client
3313 * \param seq sequencer handle
3314 * \param q queue id
3315 * \param used non-zero if the client is allowed
3316 * \return 0 on success otherwise a negative error code
3317 *
3318 * \sa snd_seq_get_queue_info(), snd_seq_set_queue_usage()
3319 */
snd_seq_set_queue_usage(snd_seq_t * seq,int q,int used)3320 int snd_seq_set_queue_usage(snd_seq_t *seq, int q, int used)
3321 {
3322 struct snd_seq_queue_client info;
3323 assert(seq);
3324 memset(&info, 0, sizeof(info));
3325 info.queue = q;
3326 info.client = seq->client;
3327 info.used = used ? 1 : 0;
3328 return seq->ops->set_queue_client(seq, &info);
3329 }
3330
3331
3332 /**
3333 * \brief get size of #snd_seq_queue_status_t
3334 * \return size in bytes
3335 */
snd_seq_queue_status_sizeof()3336 size_t snd_seq_queue_status_sizeof()
3337 {
3338 return sizeof(snd_seq_queue_status_t);
3339 }
3340
3341 /**
3342 * \brief allocate an empty #snd_seq_queue_status_t using standard malloc
3343 * \param ptr returned pointer
3344 * \return 0 on success otherwise negative error code
3345 */
snd_seq_queue_status_malloc(snd_seq_queue_status_t ** ptr)3346 int snd_seq_queue_status_malloc(snd_seq_queue_status_t **ptr)
3347 {
3348 assert(ptr);
3349 *ptr = calloc(1, sizeof(snd_seq_queue_status_t));
3350 if (!*ptr)
3351 return -ENOMEM;
3352 return 0;
3353 }
3354
3355 /**
3356 * \brief frees a previously allocated #snd_seq_queue_status_t
3357 * \param obj pointer to object to free
3358 */
snd_seq_queue_status_free(snd_seq_queue_status_t * obj)3359 void snd_seq_queue_status_free(snd_seq_queue_status_t *obj)
3360 {
3361 free(obj);
3362 }
3363
3364 /**
3365 * \brief copy one #snd_seq_queue_status_t to another
3366 * \param dst pointer to destination
3367 * \param src pointer to source
3368 */
snd_seq_queue_status_copy(snd_seq_queue_status_t * dst,const snd_seq_queue_status_t * src)3369 void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src)
3370 {
3371 assert(dst && src);
3372 *dst = *src;
3373 }
3374
3375
3376 /**
3377 * \brief Get the queue id of a queue_status container
3378 * \param info queue_status container
3379 * \return queue id
3380 *
3381 * \sa snd_seq_get_queue_status()
3382 */
snd_seq_queue_status_get_queue(const snd_seq_queue_status_t * info)3383 int snd_seq_queue_status_get_queue(const snd_seq_queue_status_t *info)
3384 {
3385 assert(info);
3386 return info->queue;
3387 }
3388
3389 /**
3390 * \brief Get the number of events of a queue_status container
3391 * \param info queue_status container
3392 * \return number of events
3393 *
3394 * \sa snd_seq_get_queue_status()
3395 */
snd_seq_queue_status_get_events(const snd_seq_queue_status_t * info)3396 int snd_seq_queue_status_get_events(const snd_seq_queue_status_t *info)
3397 {
3398 assert(info);
3399 return info->events;
3400 }
3401
3402 /**
3403 * \brief Get the tick time of a queue_status container
3404 * \param info queue_status container
3405 * \return tick time
3406 *
3407 * \sa snd_seq_get_queue_status()
3408 */
snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t * info)3409 snd_seq_tick_time_t snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t *info)
3410 {
3411 assert(info);
3412 return info->tick;
3413 }
3414
3415 /**
3416 * \brief Get the real time of a queue_status container
3417 * \param info queue_status container
3418 *
3419 * \sa snd_seq_get_queue_status()
3420 */
snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t * info)3421 const snd_seq_real_time_t *snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t *info)
3422 {
3423 assert(info);
3424 return (const snd_seq_real_time_t *)&info->time;
3425 }
3426
3427 /**
3428 * \brief Get the running status bits of a queue_status container
3429 * \param info queue_status container
3430 * \return running status bits
3431 *
3432 * \sa snd_seq_get_queue_status()
3433 */
snd_seq_queue_status_get_status(const snd_seq_queue_status_t * info)3434 unsigned int snd_seq_queue_status_get_status(const snd_seq_queue_status_t *info)
3435 {
3436 assert(info);
3437 return info->running;
3438 }
3439
3440
3441 /**
3442 * \brief obtain the running state of the queue
3443 * \param seq sequencer handle
3444 * \param q queue id to query
3445 * \param status pointer to store the current status
3446 * \return 0 on success otherwise a negative error code
3447 *
3448 * Obtains the running state of the specified queue q.
3449 */
snd_seq_get_queue_status(snd_seq_t * seq,int q,snd_seq_queue_status_t * status)3450 int snd_seq_get_queue_status(snd_seq_t *seq, int q, snd_seq_queue_status_t * status)
3451 {
3452 assert(seq && status);
3453 memset(status, 0, sizeof(snd_seq_queue_status_t));
3454 status->queue = q;
3455 return seq->ops->get_queue_status(seq, status);
3456 }
3457
3458
3459 /**
3460 * \brief get size of #snd_seq_queue_tempo_t
3461 * \return size in bytes
3462 */
snd_seq_queue_tempo_sizeof()3463 size_t snd_seq_queue_tempo_sizeof()
3464 {
3465 return sizeof(snd_seq_queue_tempo_t);
3466 }
3467
3468 /**
3469 * \brief allocate an empty #snd_seq_queue_tempo_t using standard malloc
3470 * \param ptr returned pointer
3471 * \return 0 on success otherwise negative error code
3472 */
snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t ** ptr)3473 int snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t **ptr)
3474 {
3475 assert(ptr);
3476 *ptr = calloc(1, sizeof(snd_seq_queue_tempo_t));
3477 if (!*ptr)
3478 return -ENOMEM;
3479 return 0;
3480 }
3481
3482 /**
3483 * \brief frees a previously allocated #snd_seq_queue_tempo_t
3484 * \param obj pointer to object to free
3485 */
snd_seq_queue_tempo_free(snd_seq_queue_tempo_t * obj)3486 void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *obj)
3487 {
3488 free(obj);
3489 }
3490
3491 /**
3492 * \brief copy one #snd_seq_queue_tempo_t to another
3493 * \param dst pointer to destination
3494 * \param src pointer to source
3495 */
snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t * dst,const snd_seq_queue_tempo_t * src)3496 void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src)
3497 {
3498 assert(dst && src);
3499 *dst = *src;
3500 }
3501
3502
3503 /**
3504 * \brief Get the queue id of a queue_status container
3505 * \param info queue_status container
3506 * \return queue id
3507 *
3508 * \sa snd_seq_get_queue_tempo()
3509 */
snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t * info)3510 int snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t *info)
3511 {
3512 assert(info);
3513 return info->queue;
3514 }
3515
3516 /**
3517 * \brief Get the tempo of a queue_status container
3518 * \param info queue_status container
3519 * \return tempo value
3520 *
3521 * \sa snd_seq_get_queue_tempo()
3522 */
snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t * info)3523 unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info)
3524 {
3525 assert(info);
3526 return info->tempo;
3527 }
3528
3529 /**
3530 * \brief Get the ppq of a queue_status container
3531 * \param info queue_status container
3532 * \return ppq value
3533 *
3534 * \sa snd_seq_get_queue_tempo()
3535 */
snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t * info)3536 int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info)
3537 {
3538 assert(info);
3539 return info->ppq;
3540 }
3541
3542 /**
3543 * \brief Get the timer skew value of a queue_status container
3544 * \param info queue_status container
3545 * \return timer skew value
3546 *
3547 * \sa snd_seq_get_queue_tempo()
3548 */
snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t * info)3549 unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info)
3550 {
3551 assert(info);
3552 return info->skew_value;
3553 }
3554
3555 /**
3556 * \brief Get the timer skew base value of a queue_status container
3557 * \param info queue_status container
3558 * \return timer skew base value
3559 *
3560 * \sa snd_seq_get_queue_tempo()
3561 */
snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t * info)3562 unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info)
3563 {
3564 assert(info);
3565 return info->skew_base;
3566 }
3567
3568 /**
3569 * \brief Set the tempo of a queue_status container
3570 * \param info queue_status container
3571 * \param tempo tempo value
3572 *
3573 * \sa snd_seq_get_queue_tempo()
3574 */
snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t * info,unsigned int tempo)3575 void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo)
3576 {
3577 assert(info);
3578 info->tempo = tempo;
3579 }
3580
3581 /**
3582 * \brief Set the ppq of a queue_status container
3583 * \param info queue_status container
3584 * \param ppq ppq value
3585 *
3586 * \sa snd_seq_get_queue_tempo()
3587 */
snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t * info,int ppq)3588 void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq)
3589 {
3590 assert(info);
3591 info->ppq = ppq;
3592 }
3593
3594 /**
3595 * \brief Set the timer skew value of a queue_status container
3596 * \param info queue_status container
3597 * \param skew timer skew value
3598 *
3599 * The skew of timer is calculated as skew / base.
3600 * For example, to play with double speed, pass base * 2 as the skew value.
3601 *
3602 * \sa snd_seq_get_queue_tempo()
3603 */
snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t * info,unsigned int skew)3604 void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew)
3605 {
3606 assert(info);
3607 info->skew_value = skew;
3608 }
3609
3610 /**
3611 * \brief Set the timer skew base value of a queue_status container
3612 * \param info queue_status container
3613 * \param base timer skew base value
3614 *
3615 * \sa snd_seq_get_queue_tempo()
3616 */
snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t * info,unsigned int base)3617 void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base)
3618 {
3619 assert(info);
3620 info->skew_base = base;
3621 }
3622
3623 /**
3624 * \brief obtain the current tempo of the queue
3625 * \param seq sequencer handle
3626 * \param q queue id to be queried
3627 * \param tempo pointer to store the current tempo
3628 * \return 0 on success otherwise a negative error code
3629 *
3630 * \sa snd_seq_set_queue_tempo()
3631 */
snd_seq_get_queue_tempo(snd_seq_t * seq,int q,snd_seq_queue_tempo_t * tempo)3632 int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
3633 {
3634 assert(seq && tempo);
3635 memset(tempo, 0, sizeof(snd_seq_queue_tempo_t));
3636 tempo->queue = q;
3637 return seq->ops->get_queue_tempo(seq, tempo);
3638 }
3639
3640 /**
3641 * \brief set the tempo of the queue
3642 * \param seq sequencer handle
3643 * \param q queue id to change the tempo
3644 * \param tempo tempo information
3645 * \return 0 on success otherwise a negative error code
3646 *
3647 * \sa snd_seq_get_queue_tempo()
3648 */
snd_seq_set_queue_tempo(snd_seq_t * seq,int q,snd_seq_queue_tempo_t * tempo)3649 int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
3650 {
3651 assert(seq && tempo);
3652 tempo->queue = q;
3653 return seq->ops->set_queue_tempo(seq, tempo);
3654 }
3655
3656
3657 /*----------------------------------------------------------------*/
3658
3659 /**
3660 * \brief get size of #snd_seq_queue_timer_t
3661 * \return size in bytes
3662 */
snd_seq_queue_timer_sizeof()3663 size_t snd_seq_queue_timer_sizeof()
3664 {
3665 return sizeof(snd_seq_queue_timer_t);
3666 }
3667
3668 /**
3669 * \brief allocate an empty #snd_seq_queue_timer_t using standard malloc
3670 * \param ptr returned pointer
3671 * \return 0 on success otherwise negative error code
3672 */
snd_seq_queue_timer_malloc(snd_seq_queue_timer_t ** ptr)3673 int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr)
3674 {
3675 assert(ptr);
3676 *ptr = calloc(1, sizeof(snd_seq_queue_timer_t));
3677 if (!*ptr)
3678 return -ENOMEM;
3679 return 0;
3680 }
3681
3682 /**
3683 * \brief frees a previously allocated #snd_seq_queue_timer_t
3684 * \param obj pointer to object to free
3685 */
snd_seq_queue_timer_free(snd_seq_queue_timer_t * obj)3686 void snd_seq_queue_timer_free(snd_seq_queue_timer_t *obj)
3687 {
3688 free(obj);
3689 }
3690
3691 /**
3692 * \brief copy one #snd_seq_queue_timer_t to another
3693 * \param dst pointer to destination
3694 * \param src pointer to source
3695 */
snd_seq_queue_timer_copy(snd_seq_queue_timer_t * dst,const snd_seq_queue_timer_t * src)3696 void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src)
3697 {
3698 assert(dst && src);
3699 *dst = *src;
3700 }
3701
3702
3703 /**
3704 * \brief Get the queue id of a queue_timer container
3705 * \param info queue_timer container
3706 * \return queue id
3707 *
3708 * \sa snd_seq_get_queue_timer()
3709 */
snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t * info)3710 int snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t *info)
3711 {
3712 assert(info);
3713 return info->queue;
3714 }
3715
3716 /**
3717 * \brief Get the timer type of a queue_timer container
3718 * \param info queue_timer container
3719 * \return timer type
3720 *
3721 * \sa snd_seq_get_queue_timer()
3722 */
snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t * info)3723 snd_seq_queue_timer_type_t snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t *info)
3724 {
3725 assert(info);
3726 return (snd_seq_queue_timer_type_t)info->type;
3727 }
3728
3729 /**
3730 * \brief Get the timer id of a queue_timer container
3731 * \param info queue_timer container
3732 * \return timer id pointer
3733 *
3734 * \sa snd_seq_get_queue_timer()
3735 */
snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t * info)3736 const snd_timer_id_t *snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t *info)
3737 {
3738 assert(info);
3739 return &info->u.alsa.id;
3740 }
3741
3742 /**
3743 * \brief Get the timer resolution of a queue_timer container
3744 * \param info queue_timer container
3745 * \return timer resolution
3746 *
3747 * \sa snd_seq_get_queue_timer()
3748 */
snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t * info)3749 unsigned int snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t *info)
3750 {
3751 assert(info);
3752 return info->u.alsa.resolution;
3753 }
3754
3755 /**
3756 * \brief Set the timer type of a queue_timer container
3757 * \param info queue_timer container
3758 * \param type timer type
3759 *
3760 * \sa snd_seq_get_queue_timer()
3761 */
snd_seq_queue_timer_set_type(snd_seq_queue_timer_t * info,snd_seq_queue_timer_type_t type)3762 void snd_seq_queue_timer_set_type(snd_seq_queue_timer_t *info, snd_seq_queue_timer_type_t type)
3763 {
3764 assert(info);
3765 info->type = (int)type;
3766 }
3767
3768 /**
3769 * \brief Set the timer id of a queue_timer container
3770 * \param info queue_timer container
3771 * \param id timer id pointer
3772 *
3773 * \sa snd_seq_get_queue_timer()
3774 */
snd_seq_queue_timer_set_id(snd_seq_queue_timer_t * info,const snd_timer_id_t * id)3775 void snd_seq_queue_timer_set_id(snd_seq_queue_timer_t *info, const snd_timer_id_t *id)
3776 {
3777 assert(info && id);
3778 info->u.alsa.id = *id;
3779 }
3780
3781 /**
3782 * \brief Set the timer resolution of a queue_timer container
3783 * \param info queue_timer container
3784 * \param resolution timer resolution
3785 *
3786 * \sa snd_seq_get_queue_timer()
3787 */
snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t * info,unsigned int resolution)3788 void snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t *info, unsigned int resolution)
3789 {
3790 assert(info);
3791 info->u.alsa.resolution = resolution;
3792 }
3793
3794
3795 /**
3796 * \brief obtain the queue timer information
3797 * \param seq sequencer handle
3798 * \param q queue id to query
3799 * \param timer pointer to store the timer information
3800 * \return 0 on success otherwise a negative error code
3801 *
3802 * \sa snd_seq_set_queue_timer()
3803 */
snd_seq_get_queue_timer(snd_seq_t * seq,int q,snd_seq_queue_timer_t * timer)3804 int snd_seq_get_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
3805 {
3806 assert(seq && timer);
3807 memset(timer, 0, sizeof(snd_seq_queue_timer_t));
3808 timer->queue = q;
3809 return seq->ops->get_queue_timer(seq, timer);
3810 }
3811
3812 /**
3813 * \brief set the queue timer information
3814 * \param seq sequencer handle
3815 * \param q queue id to change the timer
3816 * \param timer timer information
3817 * \return 0 on success otherwise a negative error code
3818 *
3819 * \sa snd_seq_get_queue_timer()
3820 */
snd_seq_set_queue_timer(snd_seq_t * seq,int q,snd_seq_queue_timer_t * timer)3821 int snd_seq_set_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
3822 {
3823 assert(seq && timer);
3824 timer->queue = q;
3825 return seq->ops->set_queue_timer(seq, timer);
3826 }
3827
3828 /*----------------------------------------------------------------*/
3829
3830 #ifndef DOC_HIDDEN
3831 /**
3832 * \brief (DEPRECATED) create an event cell
3833 * \return the cell pointer allocated
3834 *
3835 * create an event cell via malloc. the returned pointer must be released
3836 * by the application itself via normal free() call,
3837 * not via snd_seq_free_event().
3838 */
snd_seq_create_event(void)3839 snd_seq_event_t *snd_seq_create_event(void)
3840 {
3841 return (snd_seq_event_t *) calloc(1, sizeof(snd_seq_event_t));
3842 }
3843 #endif
3844
3845 /**
3846 * \brief (DEPRECATED) free an event
3847 *
3848 * In the former version, this function was used to
3849 * release the event pointer which was allocated by snd_seq_event_input().
3850 * In the current version, the event record is not allocated, so
3851 * you don't have to call this function any more.
3852 */
3853 #ifndef DOXYGEN
snd_seq_free_event(snd_seq_event_t * ev ATTRIBUTE_UNUSED)3854 int snd_seq_free_event(snd_seq_event_t *ev ATTRIBUTE_UNUSED)
3855 #else
3856 int snd_seq_free_event(snd_seq_event_t *ev)
3857 #endif
3858 {
3859 return 0;
3860 }
3861
3862 /**
3863 * \brief calculates the (encoded) byte-stream size of the event
3864 * \param ev the event
3865 * \return the size of decoded bytes
3866 */
snd_seq_event_length(snd_seq_event_t * ev)3867 ssize_t snd_seq_event_length(snd_seq_event_t *ev)
3868 {
3869 ssize_t len = sizeof(snd_seq_event_t);
3870 assert(ev);
3871 if (snd_seq_ev_is_variable(ev))
3872 len += ev->data.ext.len;
3873 return len;
3874 }
3875
3876 /*----------------------------------------------------------------*/
3877
3878 /*
3879 * output to sequencer
3880 */
3881
3882 /**
3883 * \brief output an event
3884 * \param seq sequencer handle
3885 * \param ev event to be output
3886 * \return the number of remaining events or a negative error code
3887 *
3888 * An event is once expanded on the output buffer.
3889 * The output buffer will be drained automatically if it becomes full.
3890 *
3891 * If events remain unprocessed on output buffer before drained,
3892 * the size of total byte data on output buffer is returned.
3893 * If the output buffer is empty, this returns zero.
3894 *
3895 * \sa snd_seq_event_output_direct(), snd_seq_event_output_buffer(),
3896 * snd_seq_event_output_pending(), snd_seq_drain_output(),
3897 * snd_seq_drop_output(), snd_seq_extract_output(),
3898 * snd_seq_remove_events()
3899 */
snd_seq_event_output(snd_seq_t * seq,snd_seq_event_t * ev)3900 int snd_seq_event_output(snd_seq_t *seq, snd_seq_event_t *ev)
3901 {
3902 int result;
3903
3904 result = snd_seq_event_output_buffer(seq, ev);
3905 if (result == -EAGAIN) {
3906 result = snd_seq_drain_output(seq);
3907 if (result < 0)
3908 return result;
3909 return snd_seq_event_output_buffer(seq, ev);
3910 }
3911 return result;
3912 }
3913
3914 /**
3915 * \brief output an event onto the lib buffer without draining buffer
3916 * \param seq sequencer handle
3917 * \param ev event to be output
3918 * \return the byte size of remaining events. \c -EAGAIN if the buffer becomes full.
3919 *
3920 * This function doesn't drain buffer unlike snd_seq_event_output().
3921 *
3922 * \sa snd_seq_event_output()
3923 */
snd_seq_event_output_buffer(snd_seq_t * seq,snd_seq_event_t * ev)3924 int snd_seq_event_output_buffer(snd_seq_t *seq, snd_seq_event_t *ev)
3925 {
3926 int len;
3927 assert(seq && ev);
3928 len = snd_seq_event_length(ev);
3929 if (len < 0)
3930 return -EINVAL;
3931 if ((size_t) len >= seq->obufsize)
3932 return -EINVAL;
3933 if ((seq->obufsize - seq->obufused) < (size_t) len)
3934 return -EAGAIN;
3935 memcpy(seq->obuf + seq->obufused, ev, sizeof(snd_seq_event_t));
3936 seq->obufused += sizeof(snd_seq_event_t);
3937 if (snd_seq_ev_is_variable(ev)) {
3938 memcpy(seq->obuf + seq->obufused, ev->data.ext.ptr, ev->data.ext.len);
3939 seq->obufused += ev->data.ext.len;
3940 }
3941 return seq->obufused;
3942 }
3943
3944 /*
3945 * allocate the temporary buffer
3946 */
alloc_tmpbuf(snd_seq_t * seq,size_t len)3947 static int alloc_tmpbuf(snd_seq_t *seq, size_t len)
3948 {
3949 size_t size = ((len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t));
3950 if (seq->tmpbuf == NULL) {
3951 if (size > DEFAULT_TMPBUF_SIZE)
3952 seq->tmpbufsize = size;
3953 else
3954 seq->tmpbufsize = DEFAULT_TMPBUF_SIZE;
3955 seq->tmpbuf = malloc(seq->tmpbufsize * sizeof(snd_seq_event_t));
3956 if (seq->tmpbuf == NULL)
3957 return -ENOMEM;
3958 } else if (len > seq->tmpbufsize) {
3959 seq->tmpbuf = realloc(seq->tmpbuf, size * sizeof(snd_seq_event_t));
3960 if (seq->tmpbuf == NULL)
3961 return -ENOMEM;
3962 seq->tmpbufsize = size;
3963 }
3964 return 0;
3965 }
3966
3967 /**
3968 * \brief output an event directly to the sequencer NOT through output buffer
3969 * \param seq sequencer handle
3970 * \param ev event to be output
3971 * \return the byte size sent to sequencer or a negative error code
3972 *
3973 * This function sends an event to the sequencer directly not through the
3974 * output buffer. When the event is a variable length event, a temporary
3975 * buffer is allocated inside alsa-lib and the data is copied there before
3976 * actually sent.
3977 *
3978 * \sa snd_seq_event_output()
3979 */
snd_seq_event_output_direct(snd_seq_t * seq,snd_seq_event_t * ev)3980 int snd_seq_event_output_direct(snd_seq_t *seq, snd_seq_event_t *ev)
3981 {
3982 ssize_t len;
3983 void *buf;
3984
3985 len = snd_seq_event_length(ev);
3986 if (len < 0)
3987 return len;
3988 else if (len == sizeof(*ev)) {
3989 buf = ev;
3990 } else {
3991 if (alloc_tmpbuf(seq, (size_t)len) < 0)
3992 return -ENOMEM;
3993 *seq->tmpbuf = *ev;
3994 memcpy(seq->tmpbuf + 1, ev->data.ext.ptr, ev->data.ext.len);
3995 buf = seq->tmpbuf;
3996 }
3997 return seq->ops->write(seq, buf, (size_t) len);
3998 }
3999
4000 /**
4001 * \brief return the size of pending events on output buffer
4002 * \param seq sequencer handle
4003 * \return the byte size of total of pending events
4004 *
4005 * \sa snd_seq_event_output()
4006 */
snd_seq_event_output_pending(snd_seq_t * seq)4007 int snd_seq_event_output_pending(snd_seq_t *seq)
4008 {
4009 assert(seq);
4010 return seq->obufused;
4011 }
4012
4013 /**
4014 * \brief drain output buffer to sequencer
4015 * \param seq sequencer handle
4016 * \return 0 when all events are drained and sent to sequencer.
4017 * When events still remain on the buffer, the byte size of remaining
4018 * events are returned. On error a negative error code is returned.
4019 *
4020 * This function drains all pending events on the output buffer.
4021 * The function returns immediately after the events are sent to the queues
4022 * regardless whether the events are processed or not.
4023 * To get synchronization with the all event processes, use
4024 * #snd_seq_sync_output_queue() after calling this function.
4025 *
4026 * \sa snd_seq_event_output(), snd_seq_sync_output_queue()
4027 */
snd_seq_drain_output(snd_seq_t * seq)4028 int snd_seq_drain_output(snd_seq_t *seq)
4029 {
4030 ssize_t result, processed = 0;
4031 assert(seq);
4032 while (seq->obufused > 0) {
4033 result = seq->ops->write(seq, seq->obuf, seq->obufused);
4034 if (result < 0) {
4035 if (result == -EAGAIN && processed)
4036 return seq->obufused;
4037 return result;
4038 }
4039 if ((size_t)result < seq->obufused)
4040 memmove(seq->obuf, seq->obuf + result, seq->obufused - result);
4041 seq->obufused -= result;
4042 }
4043 return 0;
4044 }
4045
4046 /**
4047 * \brief extract the first event in output buffer
4048 * \param seq sequencer handle
4049 * \param ev_res event pointer to be extracted
4050 * \return 0 on success otherwise a negative error code
4051 *
4052 * Extracts the first event in output buffer.
4053 * If ev_res is NULL, just remove the event.
4054 *
4055 * \sa snd_seq_event_output()
4056 */
snd_seq_extract_output(snd_seq_t * seq,snd_seq_event_t ** ev_res)4057 int snd_seq_extract_output(snd_seq_t *seq, snd_seq_event_t **ev_res)
4058 {
4059 size_t len, olen;
4060 snd_seq_event_t ev;
4061 assert(seq);
4062 if (ev_res)
4063 *ev_res = NULL;
4064 if ((olen = seq->obufused) < sizeof(snd_seq_event_t))
4065 return -ENOENT;
4066 memcpy(&ev, seq->obuf, sizeof(snd_seq_event_t));
4067 len = snd_seq_event_length(&ev);
4068 if (ev_res) {
4069 /* extract the event */
4070 if (alloc_tmpbuf(seq, len) < 0)
4071 return -ENOMEM;
4072 memcpy(seq->tmpbuf, seq->obuf, len);
4073 *ev_res = seq->tmpbuf;
4074 }
4075 seq->obufused = olen - len;
4076 memmove(seq->obuf, seq->obuf + len, seq->obufused);
4077 return 0;
4078 }
4079
4080 /*----------------------------------------------------------------*/
4081
4082 /*
4083 * input from sequencer
4084 */
4085
4086 /*
4087 * read from sequencer to input buffer
4088 */
snd_seq_event_read_buffer(snd_seq_t * seq)4089 static ssize_t snd_seq_event_read_buffer(snd_seq_t *seq)
4090 {
4091 ssize_t len;
4092 len = (seq->ops->read)(seq, seq->ibuf, seq->ibufsize * sizeof(snd_seq_event_t));
4093 if (len < 0)
4094 return len;
4095 seq->ibuflen = len / sizeof(snd_seq_event_t);
4096 seq->ibufptr = 0;
4097 return seq->ibuflen;
4098 }
4099
snd_seq_event_retrieve_buffer(snd_seq_t * seq,snd_seq_event_t ** retp)4100 static int snd_seq_event_retrieve_buffer(snd_seq_t *seq, snd_seq_event_t **retp)
4101 {
4102 size_t ncells;
4103 snd_seq_event_t *ev;
4104
4105 *retp = ev = &seq->ibuf[seq->ibufptr];
4106 seq->ibufptr++;
4107 seq->ibuflen--;
4108 if (! snd_seq_ev_is_variable(ev))
4109 return 1;
4110 ncells = (ev->data.ext.len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
4111 if (seq->ibuflen < ncells) {
4112 seq->ibuflen = 0; /* clear buffer */
4113 *retp = NULL;
4114 return -EINVAL;
4115 }
4116 ev->data.ext.ptr = ev + 1;
4117 seq->ibuflen -= ncells;
4118 seq->ibufptr += ncells;
4119 return 1;
4120 }
4121
4122 /**
4123 * \brief retrieve an event from sequencer
4124 * \param seq sequencer handle
4125 * \param ev event pointer to be stored
4126 * \return
4127 *
4128 * Obtains an input event from sequencer.
4129 * The event is created via snd_seq_create_event(), and its pointer is stored on
4130 * ev argument.
4131 *
4132 * This function firstly receives the event byte-stream data from sequencer
4133 * as much as possible at once. Then it retrieves the first event record
4134 * and store the pointer on ev.
4135 * By calling this function sequentially, events are extracted from the input buffer.
4136 *
4137 * If there is no input from sequencer, function falls into sleep
4138 * in blocking mode until an event is received,
4139 * or returns \c -EAGAIN error in non-blocking mode.
4140 * Occasionally, this function may return \c -ENOSPC error.
4141 * This means that the input FIFO of sequencer overran, and some events are
4142 * lost.
4143 * Once this error is returned, the input FIFO is cleared automatically.
4144 *
4145 * Function returns the byte size of remaining events on the input buffer
4146 * if an event is successfully received.
4147 * Application can determine from the returned value whether to call
4148 * input once more or not.
4149 *
4150 * \sa snd_seq_event_input_pending(), snd_seq_drop_input()
4151 */
snd_seq_event_input(snd_seq_t * seq,snd_seq_event_t ** ev)4152 int snd_seq_event_input(snd_seq_t *seq, snd_seq_event_t **ev)
4153 {
4154 int err;
4155 assert(seq);
4156 *ev = NULL;
4157 if (seq->ibuflen <= 0) {
4158 if ((err = snd_seq_event_read_buffer(seq)) < 0)
4159 return err;
4160 }
4161
4162 return snd_seq_event_retrieve_buffer(seq, ev);
4163 }
4164
4165 /*
4166 * read input data from sequencer if available
4167 */
snd_seq_event_input_feed(snd_seq_t * seq,int timeout)4168 static int snd_seq_event_input_feed(snd_seq_t *seq, int timeout)
4169 {
4170 struct pollfd pfd;
4171 int err;
4172 pfd.fd = seq->poll_fd;
4173 pfd.events = POLLIN;
4174 err = poll(&pfd, 1, timeout);
4175 if (err < 0) {
4176 SYSERR("poll");
4177 return -errno;
4178 }
4179 if (pfd.revents & POLLIN)
4180 return snd_seq_event_read_buffer(seq);
4181 return seq->ibuflen;
4182 }
4183
4184 /**
4185 * \brief check events in input buffer
4186 * \return the byte size of remaining input events on input buffer.
4187 *
4188 * If events remain on the input buffer of user-space, function returns
4189 * the total byte size of events on it.
4190 * If fetch_sequencer argument is non-zero,
4191 * this function checks the presence of events on sequencer FIFO
4192 * When events exist, they are transferred to the input buffer,
4193 * and the number of received events are returned.
4194 * If fetch_sequencer argument is zero and
4195 * no events remain on the input buffer, function simply returns zero.
4196 *
4197 * \sa snd_seq_event_input()
4198 */
snd_seq_event_input_pending(snd_seq_t * seq,int fetch_sequencer)4199 int snd_seq_event_input_pending(snd_seq_t *seq, int fetch_sequencer)
4200 {
4201 if (seq->ibuflen == 0 && fetch_sequencer) {
4202 return snd_seq_event_input_feed(seq, 0);
4203 }
4204 return seq->ibuflen;
4205 }
4206
4207 /*----------------------------------------------------------------*/
4208
4209 /*
4210 * clear event buffers
4211 */
4212
4213 /**
4214 * \brief remove all events on user-space output buffer
4215 * \param seq sequencer handle
4216 *
4217 * Removes all events on user-space output buffer.
4218 * Unlike snd_seq_drain_output(), this function doesn't remove
4219 * events on output memory pool of sequencer.
4220 *
4221 * \sa snd_seq_drop_output()
4222 */
snd_seq_drop_output_buffer(snd_seq_t * seq)4223 int snd_seq_drop_output_buffer(snd_seq_t *seq)
4224 {
4225 assert(seq);
4226 seq->obufused = 0;
4227 return 0;
4228 }
4229
4230 /**
4231 * \brief remove all events on user-space input FIFO
4232 * \param seq sequencer handle
4233 *
4234 * \sa snd_seq_drop_input()
4235 */
snd_seq_drop_input_buffer(snd_seq_t * seq)4236 int snd_seq_drop_input_buffer(snd_seq_t *seq)
4237 {
4238 assert(seq);
4239 seq->ibufptr = 0;
4240 seq->ibuflen = 0;
4241 return 0;
4242 }
4243
4244 /**
4245 * \brief remove all events on output buffer
4246 * \param seq sequencer handle
4247 *
4248 * Removes all events on both user-space output buffer and
4249 * output memory pool on kernel.
4250 *
4251 * \sa snd_seq_drain_output(), snd_seq_drop_output_buffer(), snd_seq_remove_events()
4252 */
snd_seq_drop_output(snd_seq_t * seq)4253 int snd_seq_drop_output(snd_seq_t *seq)
4254 {
4255 snd_seq_remove_events_t rminfo;
4256 assert(seq);
4257
4258 memset(&rminfo, 0, sizeof(rminfo));
4259 rminfo.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT;
4260
4261 return snd_seq_remove_events(seq, &rminfo);
4262 }
4263
4264 /**
4265 * \brief clear input buffer and and remove events in sequencer queue
4266 * \param seq sequencer handle
4267 *
4268 * \sa snd_seq_drop_input_buffer(), snd_seq_remove_events()
4269 */
snd_seq_drop_input(snd_seq_t * seq)4270 int snd_seq_drop_input(snd_seq_t *seq)
4271 {
4272 snd_seq_remove_events_t rminfo;
4273 assert(seq);
4274
4275 memset(&rminfo, 0, sizeof(rminfo));
4276 rminfo.remove_mode = SNDRV_SEQ_REMOVE_INPUT;
4277
4278 return snd_seq_remove_events(seq, &rminfo);
4279 }
4280
4281
4282 /**
4283 * \brief get size of #snd_seq_remove_events_t
4284 * \return size in bytes
4285 */
snd_seq_remove_events_sizeof()4286 size_t snd_seq_remove_events_sizeof()
4287 {
4288 return sizeof(snd_seq_remove_events_t);
4289 }
4290
4291 /**
4292 * \brief allocate an empty #snd_seq_remove_events_t using standard malloc
4293 * \param ptr returned pointer
4294 * \return 0 on success otherwise negative error code
4295 */
snd_seq_remove_events_malloc(snd_seq_remove_events_t ** ptr)4296 int snd_seq_remove_events_malloc(snd_seq_remove_events_t **ptr)
4297 {
4298 assert(ptr);
4299 *ptr = calloc(1, sizeof(snd_seq_remove_events_t));
4300 if (!*ptr)
4301 return -ENOMEM;
4302 return 0;
4303 }
4304
4305 /**
4306 * \brief frees a previously allocated #snd_seq_remove_events_t
4307 * \param obj pointer to object to free
4308 */
snd_seq_remove_events_free(snd_seq_remove_events_t * obj)4309 void snd_seq_remove_events_free(snd_seq_remove_events_t *obj)
4310 {
4311 free(obj);
4312 }
4313
4314 /**
4315 * \brief copy one #snd_seq_remove_events_t to another
4316 * \param dst pointer to destination
4317 * \param src pointer to source
4318 */
snd_seq_remove_events_copy(snd_seq_remove_events_t * dst,const snd_seq_remove_events_t * src)4319 void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src)
4320 {
4321 assert(dst && src);
4322 *dst = *src;
4323 }
4324
4325
4326 /**
4327 * \brief Get the removal condition bits
4328 * \param info remove_events container
4329 * \return removal condition bits
4330 *
4331 * \sa snd_seq_remove_events()
4332 */
snd_seq_remove_events_get_condition(const snd_seq_remove_events_t * info)4333 unsigned int snd_seq_remove_events_get_condition(const snd_seq_remove_events_t *info)
4334 {
4335 assert(info);
4336 return info->remove_mode;
4337 }
4338
4339 /**
4340 * \brief Get the queue as removal condition
4341 * \param info remove_events container
4342 * \return queue id
4343 *
4344 * \sa snd_seq_remove_events()
4345 */
snd_seq_remove_events_get_queue(const snd_seq_remove_events_t * info)4346 int snd_seq_remove_events_get_queue(const snd_seq_remove_events_t *info)
4347 {
4348 assert(info);
4349 return info->queue;
4350 }
4351
4352 /**
4353 * \brief Get the event timestamp as removal condition
4354 * \param info remove_events container
4355 * \return time stamp
4356 *
4357 * \sa snd_seq_remove_events()
4358 */
snd_seq_remove_events_get_time(const snd_seq_remove_events_t * info)4359 const snd_seq_timestamp_t *snd_seq_remove_events_get_time(const snd_seq_remove_events_t *info)
4360 {
4361 assert(info);
4362 return (const snd_seq_timestamp_t *)&info->time;
4363 }
4364
4365 /**
4366 * \brief Get the event destination address as removal condition
4367 * \param info remove_events container
4368 * \return destination address
4369 *
4370 * \sa snd_seq_remove_events()
4371 */
snd_seq_remove_events_get_dest(const snd_seq_remove_events_t * info)4372 const snd_seq_addr_t *snd_seq_remove_events_get_dest(const snd_seq_remove_events_t *info)
4373 {
4374 assert(info);
4375 return (const snd_seq_addr_t *)&info->dest;
4376 }
4377
4378 /**
4379 * \brief Get the event channel as removal condition
4380 * \param info remove_events container
4381 * \return channel number
4382 *
4383 * \sa snd_seq_remove_events()
4384 */
snd_seq_remove_events_get_channel(const snd_seq_remove_events_t * info)4385 int snd_seq_remove_events_get_channel(const snd_seq_remove_events_t *info)
4386 {
4387 assert(info);
4388 return info->channel;
4389 }
4390
4391 /**
4392 * \brief Get the event type as removal condition
4393 * \param info remove_events container
4394 * \return event type
4395 *
4396 * \sa snd_seq_remove_events()
4397 */
snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t * info)4398 int snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t *info)
4399 {
4400 assert(info);
4401 return info->type;
4402 }
4403
4404 /**
4405 * \brief Get the event tag id as removal condition
4406 * \param info remove_events container
4407 * \return tag id
4408 *
4409 * \sa snd_seq_remove_events()
4410 */
snd_seq_remove_events_get_tag(const snd_seq_remove_events_t * info)4411 int snd_seq_remove_events_get_tag(const snd_seq_remove_events_t *info)
4412 {
4413 assert(info);
4414 return info->tag;
4415 }
4416
4417 /**
4418 * \brief Set the removal condition bits
4419 * \param info remove_events container
4420 * \param flags removal condition bits
4421 *
4422 * \sa snd_seq_remove_events()
4423 */
snd_seq_remove_events_set_condition(snd_seq_remove_events_t * info,unsigned int flags)4424 void snd_seq_remove_events_set_condition(snd_seq_remove_events_t *info, unsigned int flags)
4425 {
4426 assert(info);
4427 info->remove_mode = flags;
4428 }
4429
4430 /**
4431 * \brief Set the queue as removal condition
4432 * \param info remove_events container
4433 * \param queue queue id
4434 *
4435 * \sa snd_seq_remove_events()
4436 */
snd_seq_remove_events_set_queue(snd_seq_remove_events_t * info,int queue)4437 void snd_seq_remove_events_set_queue(snd_seq_remove_events_t *info, int queue)
4438 {
4439 assert(info);
4440 info->queue = queue;
4441 }
4442
4443 /**
4444 * \brief Set the timestamp as removal condition
4445 * \param info remove_events container
4446 * \param time timestamp pointer
4447 *
4448 * \sa snd_seq_remove_events()
4449 */
snd_seq_remove_events_set_time(snd_seq_remove_events_t * info,const snd_seq_timestamp_t * time)4450 void snd_seq_remove_events_set_time(snd_seq_remove_events_t *info, const snd_seq_timestamp_t *time)
4451 {
4452 assert(info);
4453 info->time = *(const union sndrv_seq_timestamp *)time;
4454 }
4455
4456 /**
4457 * \brief Set the destination address as removal condition
4458 * \param info remove_events container
4459 * \param addr destination address
4460 *
4461 * \sa snd_seq_remove_events()
4462 */
snd_seq_remove_events_set_dest(snd_seq_remove_events_t * info,const snd_seq_addr_t * addr)4463 void snd_seq_remove_events_set_dest(snd_seq_remove_events_t *info, const snd_seq_addr_t *addr)
4464 {
4465 assert(info);
4466 info->dest = *(const struct sndrv_seq_addr *)addr;
4467 }
4468
4469 /**
4470 * \brief Set the channel as removal condition
4471 * \param info remove_events container
4472 * \param channel channel number
4473 *
4474 * \sa snd_seq_remove_events()
4475 */
snd_seq_remove_events_set_channel(snd_seq_remove_events_t * info,int channel)4476 void snd_seq_remove_events_set_channel(snd_seq_remove_events_t *info, int channel)
4477 {
4478 assert(info);
4479 info->channel = channel;
4480 }
4481
4482 /**
4483 * \brief Set the event type as removal condition
4484 * \param info remove_events container
4485 * \param type event type
4486 *
4487 * \sa snd_seq_remove_events()
4488 */
snd_seq_remove_events_set_event_type(snd_seq_remove_events_t * info,int type)4489 void snd_seq_remove_events_set_event_type(snd_seq_remove_events_t *info, int type)
4490 {
4491 assert(info);
4492 info->type = type;
4493 }
4494
4495 /**
4496 * \brief Set the event tag as removal condition
4497 * \param info remove_events container
4498 * \param tag tag id
4499 *
4500 * \sa snd_seq_remove_events()
4501 */
snd_seq_remove_events_set_tag(snd_seq_remove_events_t * info,int tag)4502 void snd_seq_remove_events_set_tag(snd_seq_remove_events_t *info, int tag)
4503 {
4504 assert(info);
4505 info->tag = tag;
4506 }
4507
4508
4509 /* compare timestamp between events */
4510 /* return 1 if a >= b; otherwise return 0 */
snd_seq_compare_tick_time(snd_seq_tick_time_t * a,snd_seq_tick_time_t * b)4511 static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
4512 {
4513 /* compare ticks */
4514 return (*a >= *b);
4515 }
4516
snd_seq_compare_real_time(snd_seq_real_time_t * a,snd_seq_real_time_t * b)4517 static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
4518 {
4519 /* compare real time */
4520 if (a->tv_sec > b->tv_sec)
4521 return 1;
4522 if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
4523 return 1;
4524 return 0;
4525 }
4526
4527 /* Routine to match events to be removed */
remove_match(snd_seq_remove_events_t * info,snd_seq_event_t * ev)4528 static int remove_match(snd_seq_remove_events_t *info, snd_seq_event_t *ev)
4529 {
4530 int res;
4531
4532 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
4533 if (ev->dest.client != info->dest.client ||
4534 ev->dest.port != info->dest.port)
4535 return 0;
4536 }
4537 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
4538 if (! snd_seq_ev_is_channel_type(ev))
4539 return 0;
4540 /* data.note.channel and data.control.channel are identical */
4541 if (ev->data.note.channel != info->channel)
4542 return 0;
4543 }
4544 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
4545 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
4546 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
4547 else
4548 res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
4549 if (!res)
4550 return 0;
4551 }
4552 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
4553 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
4554 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
4555 else
4556 res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
4557 if (res)
4558 return 0;
4559 }
4560 if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
4561 if (ev->type != info->type)
4562 return 0;
4563 }
4564 if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
4565 /* Do not remove off events */
4566 switch (ev->type) {
4567 case SND_SEQ_EVENT_NOTEOFF:
4568 /* case SND_SEQ_EVENT_SAMPLE_STOP: */
4569 return 0;
4570 default:
4571 break;
4572 }
4573 }
4574 if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
4575 if (info->tag != ev->tag)
4576 return 0;
4577 }
4578
4579 return 1;
4580 }
4581
4582 /**
4583 * \brief remove events on input/output buffers and pools
4584 * \param seq sequencer handle
4585 * \param rmp remove event container
4586 *
4587 * Removes matching events with the given condition from input/output buffers
4588 * and pools.
4589 * The removal condition is specified in \a rmp argument.
4590 *
4591 * \sa snd_seq_event_output(), snd_seq_drop_output(), snd_seq_reset_pool_output()
4592 */
snd_seq_remove_events(snd_seq_t * seq,snd_seq_remove_events_t * rmp)4593 int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp)
4594 {
4595 if (rmp->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
4596 /*
4597 * First deal with any events that are still buffered
4598 * in the library.
4599 */
4600 snd_seq_drop_input_buffer(seq);
4601 }
4602
4603 if (rmp->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) {
4604 /*
4605 * First deal with any events that are still buffered
4606 * in the library.
4607 */
4608 if (! (rmp->remove_mode & ~(SNDRV_SEQ_REMOVE_INPUT|SNDRV_SEQ_REMOVE_OUTPUT))) {
4609 /* The simple case - remove all */
4610 snd_seq_drop_output_buffer(seq);
4611 } else {
4612 char *ep;
4613 size_t len;
4614 snd_seq_event_t *ev;
4615
4616 ep = seq->obuf;
4617 while (ep - seq->obuf < (ssize_t)seq->obufused) {
4618
4619 ev = (snd_seq_event_t *)ep;
4620 len = snd_seq_event_length(ev);
4621
4622 if (remove_match(rmp, ev)) {
4623 /* Remove event */
4624 seq->obufused -= len;
4625 memmove(ep, ep + len, seq->obufused - (ep - seq->obuf));
4626 } else {
4627 ep += len;
4628 }
4629 }
4630 }
4631 }
4632
4633 return seq->ops->remove_events(seq, rmp);
4634 }
4635
4636 /*----------------------------------------------------------------*/
4637
4638 /*
4639 * client memory pool
4640 */
4641
4642 /**
4643 * \brief get size of #snd_seq_client_pool_t
4644 * \return size in bytes
4645 */
snd_seq_client_pool_sizeof()4646 size_t snd_seq_client_pool_sizeof()
4647 {
4648 return sizeof(snd_seq_client_pool_t);
4649 }
4650
4651 /**
4652 * \brief allocate an empty #snd_seq_client_pool_t using standard malloc
4653 * \param ptr returned pointer
4654 * \return 0 on success otherwise negative error code
4655 */
snd_seq_client_pool_malloc(snd_seq_client_pool_t ** ptr)4656 int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr)
4657 {
4658 assert(ptr);
4659 *ptr = calloc(1, sizeof(snd_seq_client_pool_t));
4660 if (!*ptr)
4661 return -ENOMEM;
4662 return 0;
4663 }
4664
4665 /**
4666 * \brief frees a previously allocated #snd_seq_client_pool_t
4667 * \param obj pointer to object to free
4668 */
snd_seq_client_pool_free(snd_seq_client_pool_t * obj)4669 void snd_seq_client_pool_free(snd_seq_client_pool_t *obj)
4670 {
4671 free(obj);
4672 }
4673
4674 /**
4675 * \brief copy one #snd_seq_client_pool_t to another
4676 * \param dst pointer to destination
4677 * \param src pointer to source
4678 */
snd_seq_client_pool_copy(snd_seq_client_pool_t * dst,const snd_seq_client_pool_t * src)4679 void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src)
4680 {
4681 assert(dst && src);
4682 *dst = *src;
4683 }
4684
4685
4686 /**
4687 * \brief Get the client id of a queue_info container
4688 * \param info client_pool container
4689 * \return client id
4690 */
snd_seq_client_pool_get_client(const snd_seq_client_pool_t * info)4691 int snd_seq_client_pool_get_client(const snd_seq_client_pool_t *info)
4692 {
4693 assert(info);
4694 return info->client;
4695 }
4696
4697 /**
4698 * \brief Get the output pool size of a queue_info container
4699 * \param info client_pool container
4700 * \return output pool size
4701 */
snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t * info)4702 size_t snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t *info)
4703 {
4704 assert(info);
4705 return info->output_pool;
4706 }
4707
4708 /**
4709 * \brief Get the input pool size of a queue_info container
4710 * \param info client_pool container
4711 * \return input pool size
4712 */
snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t * info)4713 size_t snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t *info)
4714 {
4715 assert(info);
4716 return info->input_pool;
4717 }
4718
4719 /**
4720 * \brief Get the output room size of a queue_info container
4721 * \param info client_pool container
4722 * \return output room size
4723 */
snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t * info)4724 size_t snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t *info)
4725 {
4726 assert(info);
4727 return info->output_room;
4728 }
4729
4730 /**
4731 * \brief Get the available size on output pool of a queue_info container
4732 * \param info client_pool container
4733 * \return available output size
4734 */
snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t * info)4735 size_t snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t *info)
4736 {
4737 assert(info);
4738 return info->output_free;
4739 }
4740
4741 /**
4742 * \brief Get the available size on input pool of a queue_info container
4743 * \param info client_pool container
4744 * \return available input size
4745 */
snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t * info)4746 size_t snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t *info)
4747 {
4748 assert(info);
4749 return info->input_free;
4750 }
4751
4752 /**
4753 * \brief Set the output pool size of a queue_info container
4754 * \param info client_pool container
4755 * \param size output pool size
4756 */
snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t * info,size_t size)4757 void snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t *info, size_t size)
4758 {
4759 assert(info);
4760 info->output_pool = size;
4761 }
4762
4763 /**
4764 * \brief Set the input pool size of a queue_info container
4765 * \param info client_pool container
4766 * \param size input pool size
4767 */
snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t * info,size_t size)4768 void snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t *info, size_t size)
4769 {
4770 assert(info);
4771 info->input_pool = size;
4772 }
4773
4774 /**
4775 * \brief Set the output room size of a queue_info container
4776 * \param info client_pool container
4777 * \param size output room size
4778 */
snd_seq_client_pool_set_output_room(snd_seq_client_pool_t * info,size_t size)4779 void snd_seq_client_pool_set_output_room(snd_seq_client_pool_t *info, size_t size)
4780 {
4781 assert(info);
4782 info->output_room = size;
4783 }
4784
4785
4786 /**
4787 * \brief obtain the pool information of the current client
4788 * \param seq sequencer handle
4789 * \param info information to be stored
4790 */
snd_seq_get_client_pool(snd_seq_t * seq,snd_seq_client_pool_t * info)4791 int snd_seq_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
4792 {
4793 assert(seq && info);
4794 info->client = seq->client;
4795 return seq->ops->get_client_pool(seq, info);
4796 }
4797
4798 /**
4799 * \brief set the pool information
4800 * \param seq sequencer handle
4801 * \param info information to update
4802 *
4803 * Sets the pool information of the current client.
4804 * The client field in \a info is replaced automatically with the current id.
4805 */
snd_seq_set_client_pool(snd_seq_t * seq,snd_seq_client_pool_t * info)4806 int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
4807 {
4808 assert(seq && info);
4809 info->client = seq->client;
4810 return seq->ops->set_client_pool(seq, info);
4811 }
4812
4813 /*----------------------------------------------------------------*/
4814
4815 /*
4816 * misc.
4817 */
4818
4819 /**
4820 * \brief set a bit flag
4821 */
snd_seq_set_bit(int nr,void * array)4822 void snd_seq_set_bit(int nr, void *array)
4823 {
4824 ((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
4825 }
4826
4827 /**
4828 * \brief unset a bit flag
4829 */
snd_seq_unset_bit(int nr,void * array)4830 void snd_seq_unset_bit(int nr, void *array)
4831 {
4832 ((unsigned int *)array)[nr >> 5] &= ~(1UL << (nr & 31));
4833 }
4834
4835 /**
4836 * \brief change a bit flag
4837 */
snd_seq_change_bit(int nr,void * array)4838 int snd_seq_change_bit(int nr, void *array)
4839 {
4840 int result;
4841
4842 result = ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
4843 ((unsigned int *)array)[nr >> 5] ^= 1UL << (nr & 31);
4844 return result;
4845 }
4846
4847 /**
4848 * \brief get a bit flag state
4849 */
snd_seq_get_bit(int nr,void * array)4850 int snd_seq_get_bit(int nr, void *array)
4851 {
4852 return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
4853 }
4854