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 if (_snd_is_ucm_device(name)) {
982 name = uc_mgr_alibcfg_by_device(&top, name);
983 if (name == NULL)
984 return -ENODEV;
985 } else {
986 err = snd_config_update_ref(&top);
987 if (err < 0)
988 return err;
989 }
990 err = snd_seq_open_noupdate(seqp, top, name, streams, mode, 0);
991 snd_config_unref(top);
992 return err;
993 }
994
995 /**
996 * \brief Open the ALSA sequencer using local configuration
997 *
998 * \param seqp Pointer to a snd_seq_t pointer.
999 * \param name The name to open
1000 * \param streams The read/write mode of the sequencer.
1001 * \param mode Optional modifier
1002 * \param lconf Local configuration
1003 * \return 0 on success otherwise a negative error code
1004 *
1005 * See the snd_seq_open() function for further details. The extension
1006 * is that the given configuration is used to resolve abstract name.
1007 *
1008 * \sa snd_seq_open()
1009 */
snd_seq_open_lconf(snd_seq_t ** seqp,const char * name,int streams,int mode,snd_config_t * lconf)1010 int snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
1011 int streams, int mode, snd_config_t *lconf)
1012 {
1013 assert(seqp && name && lconf);
1014 return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, 0);
1015 }
1016
1017 #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)1018 int _snd_seq_open_lconf(snd_seq_t **seqp, const char *name,
1019 int streams, int mode, snd_config_t *lconf,
1020 snd_config_t *parent_conf)
1021 {
1022 int hop;
1023 assert(seqp && name && lconf);
1024 if ((hop = snd_config_check_hop(parent_conf)) < 0)
1025 return hop;
1026 return snd_seq_open_noupdate(seqp, lconf, name, streams, mode, hop + 1);
1027 }
1028 #endif
1029
1030 /**
1031 * \brief Close the sequencer
1032 * \param seq Handle returned from #snd_seq_open()
1033 * \return 0 on success otherwise a negative error code
1034 *
1035 * Closes the sequencer client and releases its resources.
1036 * After a client is closed, an event with
1037 * #SND_SEQ_EVENT_CLIENT_EXIT is broadcast to announce port.
1038 * The connection between other clients are disconnected.
1039 * Call this just before exiting your program.
1040 *
1041 * \sa snd_seq_close()
1042 */
snd_seq_close(snd_seq_t * seq)1043 int snd_seq_close(snd_seq_t *seq)
1044 {
1045 int err;
1046 assert(seq);
1047 err = seq->ops->close(seq);
1048 if (seq->dl_handle)
1049 snd_dlclose(seq->dl_handle);
1050 free(seq->obuf);
1051 free(seq->ibuf);
1052 free(seq->tmpbuf);
1053 free(seq->name);
1054 free(seq);
1055 return err;
1056 }
1057
1058 /**
1059 * \brief Returns the number of poll descriptors
1060 * \param seq sequencer handle
1061 * \param events the poll events to be checked (\c POLLIN and \c POLLOUT)
1062 * \return the number of poll descriptors.
1063 *
1064 * Get the number of poll descriptors. The polling events to be checked
1065 * can be specified by the second argument. When both input and output
1066 * are checked, pass \c POLLIN|POLLOUT
1067 *
1068 * \sa snd_seq_poll_descriptors()
1069 */
snd_seq_poll_descriptors_count(snd_seq_t * seq,short events)1070 int snd_seq_poll_descriptors_count(snd_seq_t *seq, short events)
1071 {
1072 int result = 0;
1073 assert(seq);
1074 if (events & POLLIN) {
1075 assert(seq->streams & SND_SEQ_OPEN_INPUT);
1076 result++;
1077 }
1078 if (events & POLLOUT) {
1079 assert(seq->streams & SND_SEQ_OPEN_OUTPUT);
1080 result++;
1081 }
1082 return result ? 1 : 0;
1083 }
1084
1085 /**
1086 * \brief Get poll descriptors
1087 * \param seq sequencer handle
1088 * \param pfds array of poll descriptors
1089 * \param space space in the poll descriptor array
1090 * \param events polling events to be checked (\c POLLIN and \c POLLOUT)
1091 * \return count of filled descriptors
1092 *
1093 * Get poll descriptors assigned to the sequencer handle.
1094 * Since a sequencer handle can duplex streams, you need to set which direction(s)
1095 * is/are polled in \a events argument. When \c POLLIN bit is specified,
1096 * the incoming events to the ports are checked.
1097 *
1098 * To check the returned poll-events, call #snd_seq_poll_descriptors_revents()
1099 * instead of reading the pollfd structs directly.
1100 *
1101 * \sa snd_seq_poll_descriptors_count(), snd_seq_poll_descriptors_revents()
1102 */
snd_seq_poll_descriptors(snd_seq_t * seq,struct pollfd * pfds,unsigned int space,short events)1103 int snd_seq_poll_descriptors(snd_seq_t *seq, struct pollfd *pfds, unsigned int space, short events)
1104 {
1105 short revents = 0;
1106
1107 assert(seq);
1108 if ((events & POLLIN) && space >= 1) {
1109 assert(seq->streams & SND_SEQ_OPEN_INPUT);
1110 revents |= POLLIN|POLLERR|POLLNVAL;
1111 }
1112 if ((events & POLLOUT) && space >= 1) {
1113 assert(seq->streams & SND_SEQ_OPEN_OUTPUT);
1114 revents |= POLLOUT|POLLERR|POLLNVAL;
1115 }
1116 if (!revents)
1117 return 0;
1118 pfds->fd = seq->poll_fd;
1119 pfds->events = revents;
1120 return 1;
1121 }
1122
1123 /**
1124 * \brief get returned events from poll descriptors
1125 * \param seq sequencer handle
1126 * \param pfds array of poll descriptors
1127 * \param nfds count of poll descriptors
1128 * \param revents returned events
1129 * \return zero if success, otherwise a negative error code
1130 *
1131 * \sa snd_seq_poll_descriptors()
1132 */
snd_seq_poll_descriptors_revents(snd_seq_t * seq,struct pollfd * pfds,unsigned int nfds,unsigned short * revents)1133 int snd_seq_poll_descriptors_revents(snd_seq_t *seq, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
1134 {
1135 assert(seq && pfds && revents);
1136 if (nfds == 1) {
1137 *revents = pfds->revents;
1138 return 0;
1139 }
1140 return -EINVAL;
1141 }
1142
1143 /**
1144 * \brief Set nonblock mode
1145 * \param seq sequencer handle
1146 * \param nonblock 0 = block, 1 = nonblock mode
1147 * \return 0 on success otherwise a negative error code
1148 *
1149 * Change the blocking mode of the given client.
1150 * In block mode, the client falls into sleep when it fills the
1151 * output memory pool with full events. The client will be woken up
1152 * after a certain amount of free space becomes available.
1153 *
1154 * \sa snd_seq_open()
1155 */
snd_seq_nonblock(snd_seq_t * seq,int nonblock)1156 int snd_seq_nonblock(snd_seq_t *seq, int nonblock)
1157 {
1158 int err;
1159 assert(seq);
1160 err = seq->ops->nonblock(seq, nonblock);
1161 if (err < 0)
1162 return err;
1163 if (nonblock)
1164 seq->mode |= SND_SEQ_NONBLOCK;
1165 else
1166 seq->mode &= ~SND_SEQ_NONBLOCK;
1167 return 0;
1168 }
1169
1170 /**
1171 * \brief Get the client id
1172 * \param seq sequencer handle
1173 * \return the client id
1174 *
1175 * Returns the id of the specified client.
1176 * If an error occurs, function returns the negative error code.
1177 * A client id is necessary to inquiry or to set the client information.
1178 * A user client is assigned from 128 to 191.
1179 *
1180 * \sa snd_seq_open()
1181 */
snd_seq_client_id(snd_seq_t * seq)1182 int snd_seq_client_id(snd_seq_t *seq)
1183 {
1184 assert(seq);
1185 return seq->client;
1186 }
1187
1188 /**
1189 * \brief Return the size of output buffer
1190 * \param seq sequencer handle
1191 * \return the size of output buffer in bytes
1192 *
1193 * Obtains the size of output buffer.
1194 * This buffer is used to store decoded byte-stream of output events
1195 * before transferring to sequencer.
1196 *
1197 * \sa snd_seq_set_output_buffer_size()
1198 */
snd_seq_get_output_buffer_size(snd_seq_t * seq)1199 size_t snd_seq_get_output_buffer_size(snd_seq_t *seq)
1200 {
1201 assert(seq);
1202 if (!seq->obuf)
1203 return 0;
1204 return seq->obufsize;
1205 }
1206
1207 /**
1208 * \brief Return the size of input buffer
1209 * \param seq sequencer handle
1210 * \return the size of input buffer in bytes
1211 *
1212 * Obtains the size of input buffer.
1213 * This buffer is used to read byte-stream of input events from sequencer.
1214 *
1215 * \sa snd_seq_set_input_buffer_size()
1216 */
snd_seq_get_input_buffer_size(snd_seq_t * seq)1217 size_t snd_seq_get_input_buffer_size(snd_seq_t *seq)
1218 {
1219 assert(seq);
1220 if (!seq->ibuf)
1221 return 0;
1222 return seq->ibufsize * sizeof(snd_seq_event_t);
1223 }
1224
1225 /**
1226 * \brief Change the size of output buffer
1227 * \param seq sequencer handle
1228 * \param size the size of output buffer to be changed in bytes
1229 * \return 0 on success otherwise a negative error code
1230 *
1231 * Changes the size of output buffer.
1232 *
1233 * \sa snd_seq_get_output_buffer_size()
1234 */
snd_seq_set_output_buffer_size(snd_seq_t * seq,size_t size)1235 int snd_seq_set_output_buffer_size(snd_seq_t *seq, size_t size)
1236 {
1237 assert(seq && seq->obuf);
1238 assert(size >= sizeof(snd_seq_event_t));
1239 snd_seq_drop_output(seq);
1240 if (size != seq->obufsize) {
1241 char *newbuf;
1242 newbuf = calloc(1, size);
1243 if (newbuf == NULL)
1244 return -ENOMEM;
1245 free(seq->obuf);
1246 seq->obuf = newbuf;
1247 seq->obufsize = size;
1248 }
1249 return 0;
1250 }
1251
1252 /**
1253 * \brief Resize the input buffer
1254 * \param seq sequencer handle
1255 * \param size the size of input buffer to be changed in bytes
1256 * \return 0 on success otherwise a negative error code
1257 *
1258 * Changes the size of input buffer.
1259 *
1260 * \sa snd_seq_get_input_buffer_size()
1261 */
snd_seq_set_input_buffer_size(snd_seq_t * seq,size_t size)1262 int snd_seq_set_input_buffer_size(snd_seq_t *seq, size_t size)
1263 {
1264 assert(seq && seq->ibuf);
1265 assert(size >= sizeof(snd_seq_event_t));
1266 snd_seq_drop_input(seq);
1267 size = (size + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
1268 if (size != seq->ibufsize) {
1269 snd_seq_event_t *newbuf;
1270 newbuf = calloc(sizeof(snd_seq_event_t), size);
1271 if (newbuf == NULL)
1272 return -ENOMEM;
1273 free(seq->ibuf);
1274 seq->ibuf = newbuf;
1275 seq->ibufsize = size;
1276 }
1277 return 0;
1278 }
1279
1280
1281 /**
1282 * \brief Get size of #snd_seq_system_info_t
1283 * \return size in bytes
1284 */
snd_seq_system_info_sizeof()1285 size_t snd_seq_system_info_sizeof()
1286 {
1287 return sizeof(snd_seq_system_info_t);
1288 }
1289
1290 /**
1291 * \brief Allocate an empty #snd_seq_system_info_t using standard malloc
1292 * \param ptr returned pointer
1293 * \return 0 on success otherwise negative error code
1294 */
snd_seq_system_info_malloc(snd_seq_system_info_t ** ptr)1295 int snd_seq_system_info_malloc(snd_seq_system_info_t **ptr)
1296 {
1297 assert(ptr);
1298 *ptr = calloc(1, sizeof(snd_seq_system_info_t));
1299 if (!*ptr)
1300 return -ENOMEM;
1301 return 0;
1302 }
1303
1304 /**
1305 * \brief Frees a previously allocated #snd_seq_system_info_t
1306 * \param obj pointer to object to free
1307 */
snd_seq_system_info_free(snd_seq_system_info_t * obj)1308 void snd_seq_system_info_free(snd_seq_system_info_t *obj)
1309 {
1310 free(obj);
1311 }
1312
1313 /**
1314 * \brief Copy one #snd_seq_system_info_t to another
1315 * \param dst pointer to destination
1316 * \param src pointer to source
1317 */
snd_seq_system_info_copy(snd_seq_system_info_t * dst,const snd_seq_system_info_t * src)1318 void snd_seq_system_info_copy(snd_seq_system_info_t *dst, const snd_seq_system_info_t *src)
1319 {
1320 assert(dst && src);
1321 *dst = *src;
1322 }
1323
1324
1325 /**
1326 * \brief Get maximum number of queues
1327 * \param info #snd_seq_system_info_t container
1328 * \return maximum number of queues
1329 *
1330 * \sa snd_seq_system_info()
1331 */
snd_seq_system_info_get_queues(const snd_seq_system_info_t * info)1332 int snd_seq_system_info_get_queues(const snd_seq_system_info_t *info)
1333 {
1334 assert(info);
1335 return info->queues;
1336 }
1337
1338 /**
1339 * \brief Get maximum number of clients
1340 * \param info #snd_seq_system_info_t container
1341 * \return maximum number of clients
1342 *
1343 * \sa snd_seq_system_info()
1344 */
snd_seq_system_info_get_clients(const snd_seq_system_info_t * info)1345 int snd_seq_system_info_get_clients(const snd_seq_system_info_t *info)
1346 {
1347 assert(info);
1348 return info->clients;
1349 }
1350
1351 /**
1352 * \brief Get maximum number of ports
1353 * \param info #snd_seq_system_info_t container
1354 * \return maximum number of ports
1355 *
1356 * \sa snd_seq_system_info()
1357 */
snd_seq_system_info_get_ports(const snd_seq_system_info_t * info)1358 int snd_seq_system_info_get_ports(const snd_seq_system_info_t *info)
1359 {
1360 assert(info);
1361 return info->ports;
1362 }
1363
1364 /**
1365 * \brief Get maximum number of channels
1366 * \param info #snd_seq_system_info_t container
1367 * \return maximum number of channels
1368 *
1369 * \sa snd_seq_system_info()
1370 */
snd_seq_system_info_get_channels(const snd_seq_system_info_t * info)1371 int snd_seq_system_info_get_channels(const snd_seq_system_info_t *info)
1372 {
1373 assert(info);
1374 return info->channels;
1375 }
1376
1377 /**
1378 * \brief Get the current number of clients
1379 * \param info #snd_seq_system_info_t container
1380 * \return current number of clients
1381 *
1382 * \sa snd_seq_system_info()
1383 */
snd_seq_system_info_get_cur_clients(const snd_seq_system_info_t * info)1384 int snd_seq_system_info_get_cur_clients(const snd_seq_system_info_t *info)
1385 {
1386 assert(info);
1387 return info->cur_clients;
1388 }
1389
1390 /**
1391 * \brief Get the current number of queues
1392 * \param info #snd_seq_system_info_t container
1393 * \return current number of queues
1394 *
1395 * \sa snd_seq_system_info()
1396 */
snd_seq_system_info_get_cur_queues(const snd_seq_system_info_t * info)1397 int snd_seq_system_info_get_cur_queues(const snd_seq_system_info_t *info)
1398 {
1399 assert(info);
1400 return info->cur_queues;
1401 }
1402
1403 /**
1404 * \brief obtain the sequencer system information
1405 * \param seq sequencer handle
1406 * \param info the pointer to be stored
1407 * \return 0 on success otherwise a negative error code
1408 *
1409 * Stores the global system information of ALSA sequencer system.
1410 * The returned data contains
1411 * the maximum available numbers of queues, clients, ports and channels.
1412 */
snd_seq_system_info(snd_seq_t * seq,snd_seq_system_info_t * info)1413 int snd_seq_system_info(snd_seq_t *seq, snd_seq_system_info_t * info)
1414 {
1415 assert(seq && info);
1416 return seq->ops->system_info(seq, info);
1417 }
1418
1419
1420 /*----------------------------------------------------------------*/
1421
1422 /**
1423 * \brief get size of #snd_seq_client_info_t
1424 * \return size in bytes
1425 */
snd_seq_client_info_sizeof()1426 size_t snd_seq_client_info_sizeof()
1427 {
1428 return sizeof(snd_seq_client_info_t);
1429 }
1430
1431 /**
1432 * \brief allocate an empty #snd_seq_client_info_t using standard malloc
1433 * \param ptr returned pointer
1434 * \return 0 on success otherwise negative error code
1435 */
snd_seq_client_info_malloc(snd_seq_client_info_t ** ptr)1436 int snd_seq_client_info_malloc(snd_seq_client_info_t **ptr)
1437 {
1438 assert(ptr);
1439 *ptr = calloc(1, sizeof(snd_seq_client_info_t));
1440 if (!*ptr)
1441 return -ENOMEM;
1442 return 0;
1443 }
1444
1445 /**
1446 * \brief frees a previously allocated #snd_seq_client_info_t
1447 * \param obj pointer to object to free
1448 */
snd_seq_client_info_free(snd_seq_client_info_t * obj)1449 void snd_seq_client_info_free(snd_seq_client_info_t *obj)
1450 {
1451 free(obj);
1452 }
1453
1454 /**
1455 * \brief copy one #snd_seq_client_info_t to another
1456 * \param dst pointer to destination
1457 * \param src pointer to source
1458 */
snd_seq_client_info_copy(snd_seq_client_info_t * dst,const snd_seq_client_info_t * src)1459 void snd_seq_client_info_copy(snd_seq_client_info_t *dst, const snd_seq_client_info_t *src)
1460 {
1461 assert(dst && src);
1462 *dst = *src;
1463 }
1464
1465
1466 /**
1467 * \brief Get client id of a client_info container
1468 * \param info client_info container
1469 * \return client id
1470 *
1471 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_client(), snd_seq_client_id()
1472 */
snd_seq_client_info_get_client(const snd_seq_client_info_t * info)1473 int snd_seq_client_info_get_client(const snd_seq_client_info_t *info)
1474 {
1475 assert(info);
1476 return info->client;
1477 }
1478
1479 /**
1480 * \brief Get client type of a client_info container
1481 * \param info client_info container
1482 * \return client type
1483 *
1484 * The client type is either #SND_SEQ_KERNEL_CLIENT or #SND_SEQ_USER_CLIENT
1485 * for kernel or user client respectively.
1486 *
1487 * \sa snd_seq_get_client_info()
1488 */
snd_seq_client_info_get_type(const snd_seq_client_info_t * info)1489 snd_seq_client_type_t snd_seq_client_info_get_type(const snd_seq_client_info_t *info)
1490 {
1491 assert(info);
1492 return info->type;
1493 }
1494
1495 /**
1496 * \brief Get the name of a client_info container
1497 * \param info client_info container
1498 * \return name string
1499 *
1500 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_name()
1501 */
snd_seq_client_info_get_name(snd_seq_client_info_t * info)1502 const char *snd_seq_client_info_get_name(snd_seq_client_info_t *info)
1503 {
1504 assert(info);
1505 return info->name;
1506 }
1507
1508 /**
1509 * \brief Get the broadcast filter usage of a client_info container
1510 * \param info client_info container
1511 * \return 1 if broadcast is accepted
1512 *
1513 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_broadcast_filter()
1514 */
snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t * info)1515 int snd_seq_client_info_get_broadcast_filter(const snd_seq_client_info_t *info)
1516 {
1517 assert(info);
1518 return (info->filter & SNDRV_SEQ_FILTER_BROADCAST) ? 1 : 0;
1519 }
1520
1521 /**
1522 * \brief Get the error-bounce usage of a client_info container
1523 * \param info client_info container
1524 * \return 1 if error-bounce is enabled
1525 *
1526 * \sa snd_seq_get_client_info(), snd_seq_client_info_set_error_bounce()
1527 */
snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t * info)1528 int snd_seq_client_info_get_error_bounce(const snd_seq_client_info_t *info)
1529 {
1530 assert(info);
1531 return (info->filter & SNDRV_SEQ_FILTER_BOUNCE) ? 1 : 0;
1532 }
1533
1534 /**
1535 * \brief Get the sound card number.
1536 * \param info client_info container
1537 * \return card number or -1 if value is not available.
1538 *
1539 * Only available for #SND_SEQ_KERNEL_CLIENT clients.
1540 *
1541 * The card number can be used to query state about the hardware
1542 * device providing this client, by concatenating <code>"hw:CARD="</code>
1543 * with the card number and using it as the <code>name</code> parameter
1544 * to #snd_ctl_open().
1545 *
1546 * \note
1547 * The return value of -1 is returned for two different conditions: when the
1548 * running kernel does not support this operation, and when the client
1549 * does not have a hardware card attached. See
1550 * #snd_seq_client_info_get_pid() for a way to determine if the
1551 * currently running kernel has support for this operation.
1552 *
1553 * \sa snd_seq_client_info_get_pid(),
1554 * snd_card_get_name(),
1555 * snd_card_get_longname(),
1556 * snd_ctl_open(),
1557 * snd_ctl_card_info()
1558 */
snd_seq_client_info_get_card(const snd_seq_client_info_t * info)1559 int snd_seq_client_info_get_card(const snd_seq_client_info_t *info)
1560 {
1561 assert(info);
1562 return info->card;
1563 }
1564
1565 /**
1566 * \brief Get the owning PID.
1567 * \param info client_info container
1568 * \return pid or -1 if value is not available.
1569 *
1570 * Only available for #SND_SEQ_USER_CLIENT clients.
1571 *
1572 * \note
1573 * The functionality for getting a client's PID and getting a
1574 * client's card was added to the kernel at the same time, so you can
1575 * use this function to determine if the running kernel
1576 * supports reporting these values. If your own client has a valid
1577 * PID as reported by this function, then the running kernel supports
1578 * both #snd_seq_client_info_get_card() and #snd_seq_client_info_get_pid().
1579 *
1580 * \note
1581 * Example code for determining kernel support:
1582 * \code
1583 * int is_get_card_or_pid_supported(snd_seq_t *seq)
1584 * {
1585 * snd_seq_client_info_t *my_client_info;
1586 * snd_seq_client_info_alloca(&my_client_info);
1587 * snd_seq_get_client_info(seq, my_client_info);
1588 * return snd_seq_client_info_get_pid(my_client_info) != -1;
1589 * }
1590 * \endcode
1591 *
1592 * \sa snd_seq_client_info_get_card()
1593 */
snd_seq_client_info_get_pid(const snd_seq_client_info_t * info)1594 int snd_seq_client_info_get_pid(const snd_seq_client_info_t *info)
1595 {
1596 assert(info);
1597 return info->pid;
1598 }
1599
1600 /**
1601 * \brief (DEPRECATED) Get the event filter bitmap of a client_info container
1602 * \param info client_info container
1603 * \return NULL if no event filter, or pointer to event filter bitmap
1604 *
1605 * Use #snd_seq_client_info_event_filter_check() instead.
1606 *
1607 * \sa snd_seq_client_info_event_filter_add(),
1608 * snd_seq_client_info_event_filter_del(),
1609 * snd_seq_client_info_event_filter_check(),
1610 * snd_seq_client_info_event_filter_clear(),
1611 * snd_seq_get_client_info()
1612 */
snd_seq_client_info_get_event_filter(const snd_seq_client_info_t * info)1613 const unsigned char *snd_seq_client_info_get_event_filter(const snd_seq_client_info_t *info)
1614 {
1615 assert(info);
1616 if (info->filter & SNDRV_SEQ_FILTER_USE_EVENT)
1617 return info->event_filter;
1618 else
1619 return NULL;
1620 }
1621
1622 /**
1623 * \brief Disable event filtering of a client_info container
1624 * \param info client_info container
1625 *
1626 * Remove all event types added with #snd_seq_client_info_event_filter_add and clear
1627 * the event filtering flag of this client_info container.
1628 *
1629 * \sa snd_seq_client_info_event_filter_add(),
1630 * snd_seq_client_info_event_filter_del(),
1631 * snd_seq_client_info_event_filter_check(),
1632 * snd_seq_get_client_info(),
1633 * snd_seq_set_client_info()
1634 */
snd_seq_client_info_event_filter_clear(snd_seq_client_info_t * info)1635 void snd_seq_client_info_event_filter_clear(snd_seq_client_info_t *info)
1636 {
1637 assert(info);
1638 info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT;
1639 memset(info->event_filter, 0, sizeof(info->event_filter));
1640 }
1641
1642 /**
1643 * \brief Add an event type to the event filtering of a client_info container
1644 * \param info client_info container
1645 * \param event_type event type to be added
1646 *
1647 * Set the event filtering flag of this client_info and add the specified event type to the
1648 * filter bitmap of this client_info container.
1649 *
1650 * \sa snd_seq_get_client_info(),
1651 * snd_seq_set_client_info(),
1652 * snd_seq_client_info_event_filter_del(),
1653 * snd_seq_client_info_event_filter_check(),
1654 * snd_seq_client_info_event_filter_clear()
1655 */
snd_seq_client_info_event_filter_add(snd_seq_client_info_t * info,int event_type)1656 void snd_seq_client_info_event_filter_add(snd_seq_client_info_t *info, int event_type)
1657 {
1658 assert(info);
1659 info->filter |= SNDRV_SEQ_FILTER_USE_EVENT;
1660 snd_seq_set_bit(event_type, info->event_filter);
1661 }
1662
1663 /**
1664 * \brief Remove an event type from the event filtering of a client_info container
1665 * \param info client_info container
1666 * \param event_type event type to be removed
1667 *
1668 * Removes the specified event from the filter bitmap of this client_info container. It will
1669 * not clear the event filtering flag, use #snd_seq_client_info_event_filter_clear instead.
1670 *
1671 * \sa snd_seq_get_client_info(),
1672 * snd_seq_set_client_info(),
1673 * snd_seq_client_info_event_filter_add(),
1674 * snd_seq_client_info_event_filter_check(),
1675 * snd_seq_client_info_event_filter_clear()
1676 */
snd_seq_client_info_event_filter_del(snd_seq_client_info_t * info,int event_type)1677 void snd_seq_client_info_event_filter_del(snd_seq_client_info_t *info, int event_type)
1678 {
1679 assert(info);
1680 snd_seq_unset_bit(event_type, info->event_filter);
1681 }
1682
1683 /**
1684 * \brief Check if an event type is present in the event filtering of a client_info container
1685 * \param info client_info container
1686 * \param event_type event type to be checked
1687 * \return 1 if the event type is present, 0 otherwise
1688 *
1689 * Test if the event type is in the filter bitmap of this client_info container.
1690 *
1691 * \sa snd_seq_get_client_info(),
1692 * snd_seq_set_client_info(),
1693 * snd_seq_client_info_event_filter_add(),
1694 * snd_seq_client_info_event_filter_del(),
1695 * snd_seq_client_info_event_filter_clear()
1696 */
snd_seq_client_info_event_filter_check(snd_seq_client_info_t * info,int event_type)1697 int snd_seq_client_info_event_filter_check(snd_seq_client_info_t *info, int event_type)
1698 {
1699 assert(info);
1700 return snd_seq_get_bit(event_type, info->event_filter);
1701 }
1702
1703 /**
1704 * \brief Get the number of opened ports of a client_info container
1705 * \param info client_info container
1706 * \return number of opened ports
1707 *
1708 * \sa snd_seq_get_client_info()
1709 */
snd_seq_client_info_get_num_ports(const snd_seq_client_info_t * info)1710 int snd_seq_client_info_get_num_ports(const snd_seq_client_info_t *info)
1711 {
1712 assert(info);
1713 return info->num_ports;
1714 }
1715
1716 /**
1717 * \brief Get the number of lost events of a client_info container
1718 * \param info client_info container
1719 * \return number of lost events
1720 *
1721 * \sa snd_seq_get_client_info()
1722 */
snd_seq_client_info_get_event_lost(const snd_seq_client_info_t * info)1723 int snd_seq_client_info_get_event_lost(const snd_seq_client_info_t *info)
1724 {
1725 assert(info);
1726 return info->event_lost;
1727 }
1728
1729 /**
1730 * \brief Set the client id of a client_info container
1731 * \param info client_info container
1732 * \param client client id
1733 *
1734 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_client()
1735 */
snd_seq_client_info_set_client(snd_seq_client_info_t * info,int client)1736 void snd_seq_client_info_set_client(snd_seq_client_info_t *info, int client)
1737 {
1738 assert(info);
1739 info->client = client;
1740 }
1741
1742 /**
1743 * \brief Set the name of a client_info container
1744 * \param info client_info container
1745 * \param name name string
1746 *
1747 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_name(),
1748 * snd_seq_set_client_name()
1749 */
snd_seq_client_info_set_name(snd_seq_client_info_t * info,const char * name)1750 void snd_seq_client_info_set_name(snd_seq_client_info_t *info, const char *name)
1751 {
1752 assert(info && name);
1753 snd_strlcpy(info->name, name, sizeof(info->name));
1754 }
1755
1756 /**
1757 * \brief Set the broadcast filter usage of a client_info container
1758 * \param info client_info container
1759 * \param val non-zero if broadcast is accepted
1760 *
1761 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_broadcast_filter()
1762 */
snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t * info,int val)1763 void snd_seq_client_info_set_broadcast_filter(snd_seq_client_info_t *info, int val)
1764 {
1765 assert(info);
1766 if (val)
1767 info->filter |= SNDRV_SEQ_FILTER_BROADCAST;
1768 else
1769 info->filter &= ~SNDRV_SEQ_FILTER_BROADCAST;
1770 }
1771
1772 /**
1773 * \brief Set the error-bounce usage of a client_info container
1774 * \param info client_info container
1775 * \param val non-zero if error is bounced
1776 *
1777 * \sa snd_seq_get_client_info(), snd_seq_client_info_get_error_bounce()
1778 */
snd_seq_client_info_set_error_bounce(snd_seq_client_info_t * info,int val)1779 void snd_seq_client_info_set_error_bounce(snd_seq_client_info_t *info, int val)
1780 {
1781 assert(info);
1782 if (val)
1783 info->filter |= SNDRV_SEQ_FILTER_BOUNCE;
1784 else
1785 info->filter &= ~SNDRV_SEQ_FILTER_BOUNCE;
1786 }
1787
1788 /**
1789 * \brief (DEPRECATED) Set the event filter bitmap of a client_info container
1790 * \param info client_info container
1791 * \param filter event filter bitmap, pass NULL for no event filtering
1792 *
1793 * Use #snd_seq_client_info_event_filter_add instead.
1794 *
1795 * \sa snd_seq_client_info_event_filter_add(),
1796 * snd_seq_client_info_event_filter_del(),
1797 * snd_seq_client_info_event_filter_check(),
1798 * snd_seq_client_info_event_filter_clear(),
1799 * snd_seq_set_client_info()
1800 */
snd_seq_client_info_set_event_filter(snd_seq_client_info_t * info,unsigned char * filter)1801 void snd_seq_client_info_set_event_filter(snd_seq_client_info_t *info, unsigned char *filter)
1802 {
1803 assert(info);
1804 if (! filter)
1805 info->filter &= ~SNDRV_SEQ_FILTER_USE_EVENT;
1806 else {
1807 info->filter |= SNDRV_SEQ_FILTER_USE_EVENT;
1808 memcpy(info->event_filter, filter, sizeof(info->event_filter));
1809 }
1810 }
1811
1812
1813 /**
1814 * \brief obtain the information of the given client
1815 * \param seq sequencer handle
1816 * \param client client id
1817 * \param info the pointer to be stored
1818 * \return 0 on success otherwise a negative error code
1819 *
1820 * Obtains the information of the client with a client id specified by
1821 * info argument.
1822 * The obtained information is written on info parameter.
1823 *
1824 * \sa snd_seq_get_client_info()
1825 */
snd_seq_get_any_client_info(snd_seq_t * seq,int client,snd_seq_client_info_t * info)1826 int snd_seq_get_any_client_info(snd_seq_t *seq, int client, snd_seq_client_info_t *info)
1827 {
1828 assert(seq && info && client >= 0);
1829 memset(info, 0, sizeof(snd_seq_client_info_t));
1830 info->client = client;
1831 return seq->ops->get_client_info(seq, info);
1832 }
1833
1834 /**
1835 * \brief obtain the current client information
1836 * \param seq sequencer handle
1837 * \param info the pointer to be stored
1838 * \return 0 on success otherwise a negative error code
1839 *
1840 * Obtains the information of the current client stored on info.
1841 * client and type fields are ignored.
1842 *
1843 * \sa snd_seq_get_any_client_info(), snd_seq_set_client_info(),
1844 * snd_seq_query_next_client()
1845 */
snd_seq_get_client_info(snd_seq_t * seq,snd_seq_client_info_t * info)1846 int snd_seq_get_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
1847 {
1848 return snd_seq_get_any_client_info(seq, seq->client, info);
1849 }
1850
1851 /**
1852 * \brief set the current client information
1853 * \param seq sequencer handle
1854 * \param info the client info data to set
1855 * \return 0 on success otherwise a negative error code
1856 *
1857 * Obtains the information of the current client stored on info.
1858 * client and type fields are ignored.
1859 *
1860 * \sa snd_seq_get_client_info()
1861 */
snd_seq_set_client_info(snd_seq_t * seq,snd_seq_client_info_t * info)1862 int snd_seq_set_client_info(snd_seq_t *seq, snd_seq_client_info_t *info)
1863 {
1864 assert(seq && info);
1865 info->client = seq->client;
1866 info->type = USER_CLIENT;
1867 return seq->ops->set_client_info(seq, info);
1868 }
1869
1870 /**
1871 * \brief query the next client
1872 * \param seq sequencer handle
1873 * \param info query pattern and result
1874 *
1875 * Queries the next client.
1876 * The search begins at the client with an id one greater than
1877 * client field in info.
1878 * If a client is found, its attributes are stored in info,
1879 * and zero is returned.
1880 * Otherwise returns a negative error code.
1881 *
1882 * \sa snd_seq_get_any_client_info()
1883 */
snd_seq_query_next_client(snd_seq_t * seq,snd_seq_client_info_t * info)1884 int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info)
1885 {
1886 assert(seq && info);
1887 return seq->ops->query_next_client(seq, info);
1888 }
1889
1890
1891 /*----------------------------------------------------------------*/
1892
1893
1894 /*
1895 * Port
1896 */
1897
1898 /**
1899 * \brief get size of #snd_seq_port_info_t
1900 * \return size in bytes
1901 */
snd_seq_port_info_sizeof()1902 size_t snd_seq_port_info_sizeof()
1903 {
1904 return sizeof(snd_seq_port_info_t);
1905 }
1906
1907 /**
1908 * \brief allocate an empty #snd_seq_port_info_t using standard malloc
1909 * \param ptr returned pointer
1910 * \return 0 on success otherwise negative error code
1911 */
snd_seq_port_info_malloc(snd_seq_port_info_t ** ptr)1912 int snd_seq_port_info_malloc(snd_seq_port_info_t **ptr)
1913 {
1914 assert(ptr);
1915 *ptr = calloc(1, sizeof(snd_seq_port_info_t));
1916 if (!*ptr)
1917 return -ENOMEM;
1918 return 0;
1919 }
1920
1921 /**
1922 * \brief frees a previously allocated #snd_seq_port_info_t
1923 * \param obj pointer to object to free
1924 */
snd_seq_port_info_free(snd_seq_port_info_t * obj)1925 void snd_seq_port_info_free(snd_seq_port_info_t *obj)
1926 {
1927 free(obj);
1928 }
1929
1930 /**
1931 * \brief copy one #snd_seq_port_info_t to another
1932 * \param dst pointer to destination
1933 * \param src pointer to source
1934 */
snd_seq_port_info_copy(snd_seq_port_info_t * dst,const snd_seq_port_info_t * src)1935 void snd_seq_port_info_copy(snd_seq_port_info_t *dst, const snd_seq_port_info_t *src)
1936 {
1937 assert(dst && src);
1938 *dst = *src;
1939 }
1940
1941
1942 /**
1943 * \brief Get client id of a port_info container
1944 * \param info port_info container
1945 * \return client id
1946 *
1947 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_client()
1948 */
snd_seq_port_info_get_client(const snd_seq_port_info_t * info)1949 int snd_seq_port_info_get_client(const snd_seq_port_info_t *info)
1950 {
1951 assert(info);
1952 return info->addr.client;
1953 }
1954
1955 /**
1956 * \brief Get port id of a port_info container
1957 * \param info port_info container
1958 * \return port id
1959 *
1960 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port()
1961 */
snd_seq_port_info_get_port(const snd_seq_port_info_t * info)1962 int snd_seq_port_info_get_port(const snd_seq_port_info_t *info)
1963 {
1964 assert(info);
1965 return info->addr.port;
1966 }
1967
1968 /**
1969 * \brief Get client/port address of a port_info container
1970 * \param info port_info container
1971 * \return client/port address pointer
1972 *
1973 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_addr()
1974 */
snd_seq_port_info_get_addr(const snd_seq_port_info_t * info)1975 const snd_seq_addr_t *snd_seq_port_info_get_addr(const snd_seq_port_info_t *info)
1976 {
1977 assert(info);
1978 return (const snd_seq_addr_t *) &info->addr;
1979 }
1980
1981 /**
1982 * \brief Get the name of a port_info container
1983 * \param info port_info container
1984 * \return name string
1985 *
1986 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_name()
1987 */
snd_seq_port_info_get_name(const snd_seq_port_info_t * info)1988 const char *snd_seq_port_info_get_name(const snd_seq_port_info_t *info)
1989 {
1990 assert(info);
1991 return info->name;
1992 }
1993
1994 /**
1995 * \brief Get the capability bits of a port_info container
1996 * \param info port_info container
1997 * \return capability bits
1998 *
1999 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_capability()
2000 */
snd_seq_port_info_get_capability(const snd_seq_port_info_t * info)2001 unsigned int snd_seq_port_info_get_capability(const snd_seq_port_info_t *info)
2002 {
2003 assert(info);
2004 return info->capability;
2005 }
2006
2007 /**
2008 * \brief Get the type bits of a port_info container
2009 * \param info port_info container
2010 * \return port type bits
2011 *
2012 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_type()
2013 */
snd_seq_port_info_get_type(const snd_seq_port_info_t * info)2014 unsigned int snd_seq_port_info_get_type(const snd_seq_port_info_t *info)
2015 {
2016 assert(info);
2017 return info->type;
2018 }
2019
2020 /**
2021 * \brief Get the number of read subscriptions of a port_info container
2022 * \param info port_info container
2023 * \return number of read subscriptions
2024 *
2025 * \sa snd_seq_get_port_info()
2026 */
snd_seq_port_info_get_read_use(const snd_seq_port_info_t * info)2027 int snd_seq_port_info_get_read_use(const snd_seq_port_info_t *info)
2028 {
2029 assert(info);
2030 return info->read_use;
2031 }
2032
2033 /**
2034 * \brief Get the number of write subscriptions of a port_info container
2035 * \param info port_info container
2036 * \return number of write subscriptions
2037 *
2038 * \sa snd_seq_get_port_info()
2039 */
snd_seq_port_info_get_write_use(const snd_seq_port_info_t * info)2040 int snd_seq_port_info_get_write_use(const snd_seq_port_info_t *info)
2041 {
2042 assert(info);
2043 return info->write_use;
2044 }
2045
2046 /**
2047 * \brief Get the midi channels of a port_info container
2048 * \param info port_info container
2049 * \return number of midi channels (default 0)
2050 *
2051 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_midi_channels()
2052 */
snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t * info)2053 int snd_seq_port_info_get_midi_channels(const snd_seq_port_info_t *info)
2054 {
2055 assert(info);
2056 return info->midi_channels;
2057 }
2058
2059 /**
2060 * \brief Get the midi voices of a port_info container
2061 * \param info port_info container
2062 * \return number of midi voices (default 0)
2063 *
2064 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_midi_voices()
2065 */
snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t * info)2066 int snd_seq_port_info_get_midi_voices(const snd_seq_port_info_t *info)
2067 {
2068 assert(info);
2069 return info->midi_voices;
2070 }
2071
2072 /**
2073 * \brief Get the synth voices of a port_info container
2074 * \param info port_info container
2075 * \return number of synth voices (default 0)
2076 *
2077 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_synth_voices()
2078 */
snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t * info)2079 int snd_seq_port_info_get_synth_voices(const snd_seq_port_info_t *info)
2080 {
2081 assert(info);
2082 return info->synth_voices;
2083 }
2084
2085 /**
2086 * \brief Get the port-specified mode of a port_info container
2087 * \param info port_info container
2088 * \return 1 if port id is specified at creation
2089 *
2090 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_port_specified()
2091 */
snd_seq_port_info_get_port_specified(const snd_seq_port_info_t * info)2092 int snd_seq_port_info_get_port_specified(const snd_seq_port_info_t *info)
2093 {
2094 assert(info);
2095 return (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? 1 : 0;
2096 }
2097
2098 /**
2099 * \brief Get the time-stamping mode of the given port in a port_info container
2100 * \param info port_info container
2101 * \return 1 if the port updates timestamps of incoming events
2102 *
2103 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamping()
2104 */
snd_seq_port_info_get_timestamping(const snd_seq_port_info_t * info)2105 int snd_seq_port_info_get_timestamping(const snd_seq_port_info_t *info)
2106 {
2107 assert(info);
2108 return (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
2109 }
2110
2111 /**
2112 * \brief Get whether the time-stamping of the given port is real-time mode
2113 * \param info port_info container
2114 * \return 1 if the time-stamping is in the real-time mode
2115 *
2116 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_real()
2117 */
snd_seq_port_info_get_timestamp_real(const snd_seq_port_info_t * info)2118 int snd_seq_port_info_get_timestamp_real(const snd_seq_port_info_t *info)
2119 {
2120 assert(info);
2121 return (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
2122 }
2123
2124 /**
2125 * \brief Get the queue id to update timestamps
2126 * \param info port_info container
2127 * \return the queue id to get the timestamps
2128 *
2129 * \sa snd_seq_get_port_info(), snd_seq_port_info_set_timestamp_queue()
2130 */
snd_seq_port_info_get_timestamp_queue(const snd_seq_port_info_t * info)2131 int snd_seq_port_info_get_timestamp_queue(const snd_seq_port_info_t *info)
2132 {
2133 assert(info);
2134 return info->time_queue;
2135 }
2136
2137 /**
2138 * \brief Set the client id of a port_info container
2139 * \param info port_info container
2140 * \param client client id
2141 *
2142 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_client()
2143 */
snd_seq_port_info_set_client(snd_seq_port_info_t * info,int client)2144 void snd_seq_port_info_set_client(snd_seq_port_info_t *info, int client)
2145 {
2146 assert(info);
2147 info->addr.client = client;
2148 }
2149
2150 /**
2151 * \brief Set the port id of a port_info container
2152 * \param info port_info container
2153 * \param port port id
2154 *
2155 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port()
2156 */
snd_seq_port_info_set_port(snd_seq_port_info_t * info,int port)2157 void snd_seq_port_info_set_port(snd_seq_port_info_t *info, int port)
2158 {
2159 assert(info);
2160 info->addr.port = port;
2161 }
2162
2163 /**
2164 * \brief Set the client/port address of a port_info container
2165 * \param info port_info container
2166 * \param addr client/port address
2167 *
2168 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_addr()
2169 */
snd_seq_port_info_set_addr(snd_seq_port_info_t * info,const snd_seq_addr_t * addr)2170 void snd_seq_port_info_set_addr(snd_seq_port_info_t *info, const snd_seq_addr_t *addr)
2171 {
2172 assert(info);
2173 info->addr = *(const struct sndrv_seq_addr *)addr;
2174 }
2175
2176 /**
2177 * \brief Set the name of a port_info container
2178 * \param info port_info container
2179 * \param name name string
2180 *
2181 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_name()
2182 */
snd_seq_port_info_set_name(snd_seq_port_info_t * info,const char * name)2183 void snd_seq_port_info_set_name(snd_seq_port_info_t *info, const char *name)
2184 {
2185 assert(info && name);
2186 snd_strlcpy(info->name, name, sizeof(info->name));
2187 }
2188
2189 /**
2190 * \brief set the capability bits of a port_info container
2191 * \param info port_info container
2192 * \param capability capability bits
2193 *
2194 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_capability()
2195 */
snd_seq_port_info_set_capability(snd_seq_port_info_t * info,unsigned int capability)2196 void snd_seq_port_info_set_capability(snd_seq_port_info_t *info, unsigned int capability)
2197 {
2198 assert(info);
2199 info->capability = capability;
2200 }
2201
2202 /**
2203 * \brief Get the type bits of a port_info container
2204 * \param info port_info container
2205 * \param type port type bits
2206 *
2207 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_type()
2208 */
snd_seq_port_info_set_type(snd_seq_port_info_t * info,unsigned int type)2209 void snd_seq_port_info_set_type(snd_seq_port_info_t *info, unsigned int type)
2210 {
2211 assert(info);
2212 info->type = type;
2213 }
2214
2215 /**
2216 * \brief set the midi channels of a port_info container
2217 * \param info port_info container
2218 * \param channels midi channels (default 0)
2219 *
2220 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_midi_channels()
2221 */
snd_seq_port_info_set_midi_channels(snd_seq_port_info_t * info,int channels)2222 void snd_seq_port_info_set_midi_channels(snd_seq_port_info_t *info, int channels)
2223 {
2224 assert(info);
2225 info->midi_channels = channels;
2226 }
2227
2228 /**
2229 * \brief set the midi voices of a port_info container
2230 * \param info port_info container
2231 * \param voices midi voices (default 0)
2232 *
2233 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_midi_voices()
2234 */
snd_seq_port_info_set_midi_voices(snd_seq_port_info_t * info,int voices)2235 void snd_seq_port_info_set_midi_voices(snd_seq_port_info_t *info, int voices)
2236 {
2237 assert(info);
2238 info->midi_voices = voices;
2239 }
2240
2241 /**
2242 * \brief set the synth voices of a port_info container
2243 * \param info port_info container
2244 * \param voices synth voices (default 0)
2245 *
2246 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_synth_voice()
2247 */
snd_seq_port_info_set_synth_voices(snd_seq_port_info_t * info,int voices)2248 void snd_seq_port_info_set_synth_voices(snd_seq_port_info_t *info, int voices)
2249 {
2250 assert(info);
2251 info->synth_voices = voices;
2252 }
2253
2254 /**
2255 * \brief Set the port-specified mode of a port_info container
2256 * \param info port_info container
2257 * \param val non-zero if specifying the port id at creation
2258 *
2259 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_port_specified()
2260 */
snd_seq_port_info_set_port_specified(snd_seq_port_info_t * info,int val)2261 void snd_seq_port_info_set_port_specified(snd_seq_port_info_t *info, int val)
2262 {
2263 assert(info);
2264 if (val)
2265 info->flags |= SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
2266 else
2267 info->flags &= ~SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
2268 }
2269
2270 /**
2271 * \brief Set the time-stamping mode of the given port
2272 * \param info port_info container
2273 * \param enable non-zero if updating the timestamps of incoming events
2274 *
2275 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamping()
2276 */
snd_seq_port_info_set_timestamping(snd_seq_port_info_t * info,int enable)2277 void snd_seq_port_info_set_timestamping(snd_seq_port_info_t *info, int enable)
2278 {
2279 assert(info);
2280 if (enable)
2281 info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
2282 else
2283 info->flags &= ~SNDRV_SEQ_PORT_FLG_TIMESTAMP;
2284 }
2285
2286 /**
2287 * \brief Set whether the timestime is updated in the real-time mode
2288 * \param info port_info container
2289 * \param enable non-zero if updating the timestamps in real-time mode
2290 *
2291 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_real()
2292 */
snd_seq_port_info_set_timestamp_real(snd_seq_port_info_t * info,int enable)2293 void snd_seq_port_info_set_timestamp_real(snd_seq_port_info_t *info, int enable)
2294 {
2295 assert(info);
2296 if (enable)
2297 info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
2298 else
2299 info->flags &= ~SNDRV_SEQ_PORT_FLG_TIME_REAL;
2300 }
2301
2302 /**
2303 * \brief Set the queue id for timestamping
2304 * \param info port_info container
2305 * \param queue the queue id to get timestamps
2306 *
2307 * \sa snd_seq_get_port_info(), snd_seq_port_info_get_timestamp_queue()
2308 */
snd_seq_port_info_set_timestamp_queue(snd_seq_port_info_t * info,int queue)2309 void snd_seq_port_info_set_timestamp_queue(snd_seq_port_info_t *info, int queue)
2310 {
2311 assert(info);
2312 info->time_queue = queue;
2313 }
2314
2315
2316 /**
2317 * \brief create a sequencer port on the current client
2318 * \param seq sequencer handle
2319 * \param port port information for the new port
2320 * \return 0 on success otherwise a negative error code
2321 *
2322 * Creates a sequencer port on the current client.
2323 * The attributes of created port is specified in \a info argument.
2324 *
2325 * The client field in \a info argument is overwritten with the current client id.
2326 * The port id to be created can be specified via #snd_seq_port_info_set_port_specified.
2327 * You can get the created port id by reading the port pointer via #snd_seq_port_info_get_port.
2328 *
2329 * Each port has the capability bit-masks to specify the access capability
2330 * of the port from other clients.
2331 * The capability bit flags are defined as follows:
2332 * - #SND_SEQ_PORT_CAP_READ Readable from this port
2333 * - #SND_SEQ_PORT_CAP_WRITE Writable to this port.
2334 * - #SND_SEQ_PORT_CAP_SYNC_READ For synchronization (not implemented)
2335 * - #SND_SEQ_PORT_CAP_SYNC_WRITE For synchronization (not implemented)
2336 * - #SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported
2337 * - #SND_SEQ_PORT_CAP_SUBS_READ Read subscription is allowed
2338 * - #SND_SEQ_PORT_CAP_SUBS_WRITE Write subscription is allowed
2339 * - #SND_SEQ_PORT_CAP_NO_EXPORT Subscription management from 3rd client is disallowed
2340 *
2341 * Each port has also the type bitmasks defined as follows:
2342 * - #SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port
2343 * - #SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device
2344 * - #SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device
2345 * - #SND_SEQ_PORT_TYPE_MIDI_GM2 General MIDI 2 compatible device
2346 * - #SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device
2347 * - #SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device
2348 * - #SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device
2349 * - #SND_SEQ_PORT_TYPE_HARDWARE Implemented in hardware
2350 * - #SND_SEQ_PORT_TYPE_SOFTWARE Implemented in software
2351 * - #SND_SEQ_PORT_TYPE_SYNTHESIZER Generates sound
2352 * - #SND_SEQ_PORT_TYPE_PORT Connects to other device(s)
2353 * - #SND_SEQ_PORT_TYPE_APPLICATION Application (sequencer/editor)
2354 *
2355 * A port may contain specific midi channels, midi voices and synth voices.
2356 * These values could be zero as default.
2357 *
2358 * \sa snd_seq_delete_port(), snd_seq_get_port_info(),
2359 * snd_seq_create_simple_port()
2360 */
snd_seq_create_port(snd_seq_t * seq,snd_seq_port_info_t * port)2361 int snd_seq_create_port(snd_seq_t *seq, snd_seq_port_info_t * port)
2362 {
2363 assert(seq && port);
2364 port->addr.client = seq->client;
2365 return seq->ops->create_port(seq, port);
2366 }
2367
2368 /**
2369 * \brief delete a sequencer port on the current client
2370 * \param seq sequencer handle
2371 * \param port port to be deleted
2372 * \return 0 on success otherwise a negative error code
2373 *
2374 * Deletes the existing sequencer port on the current client.
2375 *
2376 * \sa snd_seq_create_port(), snd_seq_delete_simple_port()
2377 */
snd_seq_delete_port(snd_seq_t * seq,int port)2378 int snd_seq_delete_port(snd_seq_t *seq, int port)
2379 {
2380 snd_seq_port_info_t pinfo;
2381 assert(seq);
2382 memset(&pinfo, 0, sizeof(pinfo));
2383 pinfo.addr.client = seq->client;
2384 pinfo.addr.port = port;
2385 return seq->ops->delete_port(seq, &pinfo);
2386 }
2387
2388 /**
2389 * \brief obtain the information of a port on an arbitrary client
2390 * \param seq sequencer handle
2391 * \param client client id to get
2392 * \param port port id to get
2393 * \param info pointer information returns
2394 * \return 0 on success otherwise a negative error code
2395 *
2396 * \sa snd_seq_get_port_info()
2397 */
snd_seq_get_any_port_info(snd_seq_t * seq,int client,int port,snd_seq_port_info_t * info)2398 int snd_seq_get_any_port_info(snd_seq_t *seq, int client, int port, snd_seq_port_info_t * info)
2399 {
2400 assert(seq && info && client >= 0 && port >= 0);
2401 memset(info, 0, sizeof(snd_seq_port_info_t));
2402 info->addr.client = client;
2403 info->addr.port = port;
2404 return seq->ops->get_port_info(seq, info);
2405 }
2406
2407 /**
2408 * \brief obtain the information of a port on the current client
2409 * \param seq sequencer handle
2410 * \param port port id to get
2411 * \param info pointer information returns
2412 * \return 0 on success otherwise a negative error code
2413 *
2414 * \sa snd_seq_create_port(), snd_seq_get_any_port_info(), snd_seq_set_port_info(),
2415 * snd_seq_query_next_port()
2416 */
snd_seq_get_port_info(snd_seq_t * seq,int port,snd_seq_port_info_t * info)2417 int snd_seq_get_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
2418 {
2419 return snd_seq_get_any_port_info(seq, seq->client, port, info);
2420 }
2421
2422 /**
2423 * \brief set the information of a port on the current client
2424 * \param seq sequencer handle
2425 * \param port port to be set
2426 * \param info port information to be set
2427 * \return 0 on success otherwise a negative error code
2428 *
2429 * \sa snd_seq_set_port_info()
2430 */
snd_seq_set_port_info(snd_seq_t * seq,int port,snd_seq_port_info_t * info)2431 int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info)
2432 {
2433 assert(seq && info && port >= 0);
2434 info->addr.client = seq->client;
2435 info->addr.port = port;
2436 return seq->ops->set_port_info(seq, info);
2437 }
2438
2439 /**
2440 * \brief query the next matching port
2441 * \param seq sequencer handle
2442 * \param info query pattern and result
2443
2444 * Queries the next matching port on the client specified in
2445 * \a info argument.
2446 * The search begins at the next port specified in
2447 * port field of \a info argument.
2448 * For finding the first port at a certain client, give -1.
2449 *
2450 * If a matching port is found, its attributes are stored on
2451 * \a info and function returns zero.
2452 * Otherwise, a negative error code is returned.
2453 *
2454 * \sa snd_seq_get_port_info()
2455 */
snd_seq_query_next_port(snd_seq_t * seq,snd_seq_port_info_t * info)2456 int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info)
2457 {
2458 assert(seq && info);
2459 return seq->ops->query_next_port(seq, info);
2460 }
2461
2462
2463 /*----------------------------------------------------------------*/
2464
2465 /*
2466 * subscription
2467 */
2468
2469
2470 /**
2471 * \brief get size of #snd_seq_port_subscribe_t
2472 * \return size in bytes
2473 */
snd_seq_port_subscribe_sizeof()2474 size_t snd_seq_port_subscribe_sizeof()
2475 {
2476 return sizeof(snd_seq_port_subscribe_t);
2477 }
2478
2479 /**
2480 * \brief allocate an empty #snd_seq_port_subscribe_t using standard malloc
2481 * \param ptr returned pointer
2482 * \return 0 on success otherwise negative error code
2483 */
snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t ** ptr)2484 int snd_seq_port_subscribe_malloc(snd_seq_port_subscribe_t **ptr)
2485 {
2486 assert(ptr);
2487 *ptr = calloc(1, sizeof(snd_seq_port_subscribe_t));
2488 if (!*ptr)
2489 return -ENOMEM;
2490 return 0;
2491 }
2492
2493 /**
2494 * \brief frees a previously allocated #snd_seq_port_subscribe_t
2495 * \param obj pointer to object to free
2496 */
snd_seq_port_subscribe_free(snd_seq_port_subscribe_t * obj)2497 void snd_seq_port_subscribe_free(snd_seq_port_subscribe_t *obj)
2498 {
2499 free(obj);
2500 }
2501
2502 /**
2503 * \brief copy one #snd_seq_port_subscribe_t to another
2504 * \param dst pointer to destination
2505 * \param src pointer to source
2506 */
snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t * dst,const snd_seq_port_subscribe_t * src)2507 void snd_seq_port_subscribe_copy(snd_seq_port_subscribe_t *dst, const snd_seq_port_subscribe_t *src)
2508 {
2509 assert(dst && src);
2510 *dst = *src;
2511 }
2512
2513
2514 /**
2515 * \brief Get sender address of a port_subscribe container
2516 * \param info port_subscribe container
2517 *
2518 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_sender()
2519 */
snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t * info)2520 const snd_seq_addr_t *snd_seq_port_subscribe_get_sender(const snd_seq_port_subscribe_t *info)
2521 {
2522 assert(info);
2523 return (const snd_seq_addr_t *)&info->sender;
2524 }
2525
2526 /**
2527 * \brief Get destination address of a port_subscribe container
2528 * \param info port_subscribe container
2529 *
2530 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_dest()
2531 */
snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t * info)2532 const snd_seq_addr_t *snd_seq_port_subscribe_get_dest(const snd_seq_port_subscribe_t *info)
2533 {
2534 assert(info);
2535 return (const snd_seq_addr_t *)&info->dest;
2536 }
2537
2538 /**
2539 * \brief Get the queue id of a port_subscribe container
2540 * \param info port_subscribe container
2541 * \return queue id
2542 *
2543 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_queue()
2544 */
snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t * info)2545 int snd_seq_port_subscribe_get_queue(const snd_seq_port_subscribe_t *info)
2546 {
2547 assert(info);
2548 return info->queue;
2549 }
2550
2551 /**
2552 * \brief Get the exclusive mode of a port_subscribe container
2553 * \param info port_subscribe container
2554 * \return 1 if exclusive mode
2555 *
2556 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_exclusive()
2557 */
snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t * info)2558 int snd_seq_port_subscribe_get_exclusive(const snd_seq_port_subscribe_t *info)
2559 {
2560 assert(info);
2561 return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
2562 }
2563
2564 /**
2565 * \brief Get the time-update mode of a port_subscribe container
2566 * \param info port_subscribe container
2567 * \return 1 if update timestamp
2568 *
2569 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_time_update()
2570 */
snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t * info)2571 int snd_seq_port_subscribe_get_time_update(const snd_seq_port_subscribe_t *info)
2572 {
2573 assert(info);
2574 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2575 }
2576
2577 /**
2578 * \brief Get the real-time update mode of a port_subscribe container
2579 * \param info port_subscribe container
2580 * \return 1 if real-time update mode
2581 *
2582 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_set_time_real()
2583 */
snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t * info)2584 int snd_seq_port_subscribe_get_time_real(const snd_seq_port_subscribe_t *info)
2585 {
2586 assert(info);
2587 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 1 : 0;
2588 }
2589
2590 /**
2591 * \brief Set sender address of a port_subscribe container
2592 * \param info port_subscribe container
2593 * \param addr sender address
2594 *
2595 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_sender()
2596 */
snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t * info,const snd_seq_addr_t * addr)2597 void snd_seq_port_subscribe_set_sender(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
2598 {
2599 assert(info);
2600 memcpy(&info->sender, addr, sizeof(*addr));
2601 }
2602
2603 /**
2604 * \brief Set destination address of a port_subscribe container
2605 * \param info port_subscribe container
2606 * \param addr destination address
2607 *
2608 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_dest()
2609 */
snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t * info,const snd_seq_addr_t * addr)2610 void snd_seq_port_subscribe_set_dest(snd_seq_port_subscribe_t *info, const snd_seq_addr_t *addr)
2611 {
2612 assert(info);
2613 memcpy(&info->dest, addr, sizeof(*addr));
2614 }
2615
2616 /**
2617 * \brief Set the queue id of a port_subscribe container
2618 * \param info port_subscribe container
2619 * \param q queue id
2620 *
2621 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_queue()
2622 */
snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t * info,int q)2623 void snd_seq_port_subscribe_set_queue(snd_seq_port_subscribe_t *info, int q)
2624 {
2625 assert(info);
2626 info->queue = q;
2627 }
2628
2629 /**
2630 * \brief Set the exclusive mode of a port_subscribe container
2631 * \param info port_subscribe container
2632 * \param val non-zero to enable
2633 *
2634 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_exclusive()
2635 */
snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t * info,int val)2636 void snd_seq_port_subscribe_set_exclusive(snd_seq_port_subscribe_t *info, int val)
2637 {
2638 assert(info);
2639 if (val)
2640 info->flags |= SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
2641 else
2642 info->flags &= ~SNDRV_SEQ_PORT_SUBS_EXCLUSIVE;
2643 }
2644
2645 /**
2646 * \brief Set the time-update mode of a port_subscribe container
2647 * \param info port_subscribe container
2648 * \param val non-zero to enable
2649 *
2650 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_update()
2651 */
snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t * info,int val)2652 void snd_seq_port_subscribe_set_time_update(snd_seq_port_subscribe_t *info, int val)
2653 {
2654 assert(info);
2655 if (val)
2656 info->flags |= SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
2657 else
2658 info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIMESTAMP;
2659 }
2660
2661 /**
2662 * \brief Set the real-time mode of a port_subscribe container
2663 * \param info port_subscribe container
2664 * \param val non-zero to enable
2665 *
2666 * \sa snd_seq_subscribe_port(), snd_seq_port_subscribe_get_time_real()
2667 */
snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t * info,int val)2668 void snd_seq_port_subscribe_set_time_real(snd_seq_port_subscribe_t *info, int val)
2669 {
2670 assert(info);
2671 if (val)
2672 info->flags |= SNDRV_SEQ_PORT_SUBS_TIME_REAL;
2673 else
2674 info->flags &= ~SNDRV_SEQ_PORT_SUBS_TIME_REAL;
2675 }
2676
2677
2678 /**
2679 * \brief obtain subscription information
2680 * \param seq sequencer handle
2681 * \param sub pointer to return the subscription information
2682 * \return 0 on success otherwise a negative error code
2683 *
2684 * \sa snd_seq_subscribe_port(), snd_seq_query_port_subscribers()
2685 */
snd_seq_get_port_subscription(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2686 int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2687 {
2688 assert(seq && sub);
2689 return seq->ops->get_port_subscription(seq, sub);
2690 }
2691
2692 /**
2693 * \brief subscribe a port connection
2694 * \param seq sequencer handle
2695 * \param sub subscription information
2696 * \return 0 on success otherwise a negative error code
2697 *
2698 * Subscribes a connection between two ports.
2699 * The subscription information is stored in sub argument.
2700 *
2701 * \sa snd_seq_get_port_subscription(), snd_seq_unsubscribe_port(),
2702 * snd_seq_connect_from(), snd_seq_connect_to()
2703 */
snd_seq_subscribe_port(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2704 int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2705 {
2706 assert(seq && sub);
2707 return seq->ops->subscribe_port(seq, sub);
2708 }
2709
2710 /**
2711 * \brief unsubscribe a connection between ports
2712 * \param seq sequencer handle
2713 * \param sub subscription information to disconnect
2714 * \return 0 on success otherwise a negative error code
2715 *
2716 * Unsubscribes a connection between two ports,
2717 * described in sender and dest fields in sub argument.
2718 *
2719 * \sa snd_seq_subscribe_port(), snd_seq_disconnect_from(), snd_seq_disconnect_to()
2720 */
snd_seq_unsubscribe_port(snd_seq_t * seq,snd_seq_port_subscribe_t * sub)2721 int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub)
2722 {
2723 assert(seq && sub);
2724 return seq->ops->unsubscribe_port(seq, sub);
2725 }
2726
2727
2728 /**
2729 * \brief get size of #snd_seq_query_subscribe_t
2730 * \return size in bytes
2731 */
snd_seq_query_subscribe_sizeof()2732 size_t snd_seq_query_subscribe_sizeof()
2733 {
2734 return sizeof(snd_seq_query_subscribe_t);
2735 }
2736
2737 /**
2738 * \brief allocate an empty #snd_seq_query_subscribe_t using standard malloc
2739 * \param ptr returned pointer
2740 * \return 0 on success otherwise negative error code
2741 */
snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t ** ptr)2742 int snd_seq_query_subscribe_malloc(snd_seq_query_subscribe_t **ptr)
2743 {
2744 assert(ptr);
2745 *ptr = calloc(1, sizeof(snd_seq_query_subscribe_t));
2746 if (!*ptr)
2747 return -ENOMEM;
2748 return 0;
2749 }
2750
2751 /**
2752 * \brief frees a previously allocated #snd_seq_query_subscribe_t
2753 * \param obj pointer to object to free
2754 */
snd_seq_query_subscribe_free(snd_seq_query_subscribe_t * obj)2755 void snd_seq_query_subscribe_free(snd_seq_query_subscribe_t *obj)
2756 {
2757 free(obj);
2758 }
2759
2760 /**
2761 * \brief copy one #snd_seq_query_subscribe_t to another
2762 * \param dst pointer to destination
2763 * \param src pointer to source
2764 */
snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t * dst,const snd_seq_query_subscribe_t * src)2765 void snd_seq_query_subscribe_copy(snd_seq_query_subscribe_t *dst, const snd_seq_query_subscribe_t *src)
2766 {
2767 assert(dst && src);
2768 *dst = *src;
2769 }
2770
2771
2772 /**
2773 * \brief Get the client id of a query_subscribe container
2774 * \param info query_subscribe container
2775 * \return client id
2776 *
2777 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_client()
2778 */
snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t * info)2779 int snd_seq_query_subscribe_get_client(const snd_seq_query_subscribe_t *info)
2780 {
2781 assert(info);
2782 return info->root.client;
2783 }
2784
2785 /**
2786 * \brief Get the port id of a query_subscribe container
2787 * \param info query_subscribe container
2788 * \return port id
2789 *
2790 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_port()
2791 */
snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t * info)2792 int snd_seq_query_subscribe_get_port(const snd_seq_query_subscribe_t *info)
2793 {
2794 assert(info);
2795 return info->root.port;
2796 }
2797
2798 /**
2799 * \brief Get the client/port address of a query_subscribe container
2800 * \param info query_subscribe container
2801 * \return client/port address pointer
2802 *
2803 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_root()
2804 */
snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t * info)2805 const snd_seq_addr_t *snd_seq_query_subscribe_get_root(const snd_seq_query_subscribe_t *info)
2806 {
2807 assert(info);
2808 return (const snd_seq_addr_t *)&info->root;
2809 }
2810
2811 /**
2812 * \brief Get the query type of a query_subscribe container
2813 * \param info query_subscribe container
2814 * \return query type
2815 *
2816 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_type()
2817 */
snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t * info)2818 snd_seq_query_subs_type_t snd_seq_query_subscribe_get_type(const snd_seq_query_subscribe_t *info)
2819 {
2820 assert(info);
2821 return info->type;
2822 }
2823
2824 /**
2825 * \brief Get the index of subscriber of a query_subscribe container
2826 * \param info query_subscribe container
2827 * \return subscriber's index
2828 *
2829 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_set_index()
2830 */
snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t * info)2831 int snd_seq_query_subscribe_get_index(const snd_seq_query_subscribe_t *info)
2832 {
2833 assert(info);
2834 return info->index;
2835 }
2836
2837 /**
2838 * \brief Get the number of subscriptions of a query_subscribe container
2839 * \param info query_subscribe container
2840 * \return number of subscriptions
2841 *
2842 * \sa snd_seq_query_port_subscribers()
2843 */
snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t * info)2844 int snd_seq_query_subscribe_get_num_subs(const snd_seq_query_subscribe_t *info)
2845 {
2846 assert(info);
2847 return info->num_subs;
2848 }
2849
2850 /**
2851 * \brief Get the address of subscriber of a query_subscribe container
2852 * \param info query_subscribe container
2853 * \return subscriber's address pointer
2854 *
2855 * \sa snd_seq_query_port_subscribers()
2856 */
snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t * info)2857 const snd_seq_addr_t *snd_seq_query_subscribe_get_addr(const snd_seq_query_subscribe_t *info)
2858 {
2859 assert(info);
2860 return (const snd_seq_addr_t *)&info->addr;
2861 }
2862
2863 /**
2864 * \brief Get the queue id of subscriber of a query_subscribe container
2865 * \param info query_subscribe container
2866 * \return subscriber's queue id
2867 *
2868 * \sa snd_seq_query_port_subscribers()
2869 */
snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t * info)2870 int snd_seq_query_subscribe_get_queue(const snd_seq_query_subscribe_t *info)
2871 {
2872 assert(info);
2873 return info->queue;
2874 }
2875
2876 /**
2877 * \brief Get the exclusive mode of a query_subscribe container
2878 * \param info query_subscribe container
2879 * \return 1 if exclusive mode
2880 *
2881 * \sa snd_seq_query_port_subscribers()
2882 */
snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t * info)2883 int snd_seq_query_subscribe_get_exclusive(const snd_seq_query_subscribe_t *info)
2884 {
2885 assert(info);
2886 return (info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE) ? 1 : 0;
2887 }
2888
2889 /**
2890 * \brief Get the time-update mode of a query_subscribe container
2891 * \param info query_subscribe container
2892 * \return 1 if update timestamp
2893 *
2894 * \sa snd_seq_query_port_subscribers()
2895 */
snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t * info)2896 int snd_seq_query_subscribe_get_time_update(const snd_seq_query_subscribe_t *info)
2897 {
2898 assert(info);
2899 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2900 }
2901
2902 /**
2903 * \brief Get the real-time update mode of a query_subscribe container
2904 * \param info query_subscribe container
2905 * \return 1 if real-time update mode
2906 *
2907 * \sa snd_seq_query_port_subscribers()
2908 */
snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t * info)2909 int snd_seq_query_subscribe_get_time_real(const snd_seq_query_subscribe_t *info)
2910 {
2911 assert(info);
2912 return (info->flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) ? 1 : 0;
2913 }
2914
2915 /**
2916 * \brief Set the client id of a query_subscribe container
2917 * \param info query_subscribe container
2918 * \param client client id
2919 *
2920 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_client()
2921 */
snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t * info,int client)2922 void snd_seq_query_subscribe_set_client(snd_seq_query_subscribe_t *info, int client)
2923 {
2924 assert(info);
2925 info->root.client = client;
2926 }
2927
2928 /**
2929 * \brief Set the port id of a query_subscribe container
2930 * \param info query_subscribe container
2931 * \param port port id
2932 *
2933 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_port()
2934 */
snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t * info,int port)2935 void snd_seq_query_subscribe_set_port(snd_seq_query_subscribe_t *info, int port)
2936 {
2937 assert(info);
2938 info->root.port = port;
2939 }
2940
2941 /**
2942 * \brief Set the client/port address of a query_subscribe container
2943 * \param info query_subscribe container
2944 * \param addr client/port address pointer
2945 *
2946 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_root()
2947 */
snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t * info,const snd_seq_addr_t * addr)2948 void snd_seq_query_subscribe_set_root(snd_seq_query_subscribe_t *info, const snd_seq_addr_t *addr)
2949 {
2950 assert(info);
2951 info->root = *(const struct snd_seq_addr *)addr;
2952 }
2953
2954 /**
2955 * \brief Set the query type of a query_subscribe container
2956 * \param info query_subscribe container
2957 * \param type query type
2958 *
2959 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_type()
2960 */
snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t * info,snd_seq_query_subs_type_t type)2961 void snd_seq_query_subscribe_set_type(snd_seq_query_subscribe_t *info, snd_seq_query_subs_type_t type)
2962 {
2963 assert(info);
2964 info->type = type;
2965 }
2966
2967 /**
2968 * \brief Set the subscriber's index to be queried
2969 * \param info query_subscribe container
2970 * \param index index to be queried
2971 *
2972 * \sa snd_seq_query_port_subscribers(), snd_seq_query_subscribe_get_index()
2973 */
snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t * info,int index)2974 void snd_seq_query_subscribe_set_index(snd_seq_query_subscribe_t *info, int index)
2975 {
2976 assert(info);
2977 info->index = index;
2978 }
2979
2980
2981 /**
2982 * \brief query port subscriber list
2983 * \param seq sequencer handle
2984 * \param subs subscription to query
2985 * \return 0 on success otherwise a negative error code
2986 *
2987 * Queries the subscribers accessing to a port.
2988 * The query information is specified in subs argument.
2989 *
2990 * At least, the client id, the port id, the index number and
2991 * the query type must be set to perform a proper query.
2992 * As the query type, #SND_SEQ_QUERY_SUBS_READ or #SND_SEQ_QUERY_SUBS_WRITE
2993 * can be specified to check whether the readers or the writers to the port.
2994 * To query the first subscription, set 0 to the index number. To list up
2995 * all the subscriptions, call this function with the index numbers from 0
2996 * until this returns a negative value.
2997 *
2998 * \sa snd_seq_get_port_subscription()
2999 */
snd_seq_query_port_subscribers(snd_seq_t * seq,snd_seq_query_subscribe_t * subs)3000 int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subscribe_t * subs)
3001 {
3002 assert(seq && subs);
3003 return seq->ops->query_port_subscribers(seq, subs);
3004 }
3005
3006 /*----------------------------------------------------------------*/
3007
3008 /*
3009 * queue handlers
3010 */
3011
3012 /**
3013 * \brief get size of #snd_seq_queue_info_t
3014 * \return size in bytes
3015 */
snd_seq_queue_info_sizeof()3016 size_t snd_seq_queue_info_sizeof()
3017 {
3018 return sizeof(snd_seq_queue_info_t);
3019 }
3020
3021 /**
3022 * \brief allocate an empty #snd_seq_queue_info_t using standard malloc
3023 * \param ptr returned pointer
3024 * \return 0 on success otherwise negative error code
3025 */
snd_seq_queue_info_malloc(snd_seq_queue_info_t ** ptr)3026 int snd_seq_queue_info_malloc(snd_seq_queue_info_t **ptr)
3027 {
3028 assert(ptr);
3029 *ptr = calloc(1, sizeof(snd_seq_queue_info_t));
3030 if (!*ptr)
3031 return -ENOMEM;
3032 return 0;
3033 }
3034
3035 /**
3036 * \brief frees a previously allocated #snd_seq_queue_info_t
3037 * \param obj pointer to object to free
3038 */
snd_seq_queue_info_free(snd_seq_queue_info_t * obj)3039 void snd_seq_queue_info_free(snd_seq_queue_info_t *obj)
3040 {
3041 free(obj);
3042 }
3043
3044 /**
3045 * \brief copy one #snd_seq_queue_info_t to another
3046 * \param dst pointer to destination
3047 * \param src pointer to source
3048 */
snd_seq_queue_info_copy(snd_seq_queue_info_t * dst,const snd_seq_queue_info_t * src)3049 void snd_seq_queue_info_copy(snd_seq_queue_info_t *dst, const snd_seq_queue_info_t *src)
3050 {
3051 assert(dst && src);
3052 *dst = *src;
3053 }
3054
3055
3056 /**
3057 * \brief Get the queue id of a queue_info container
3058 * \param info queue_info container
3059 * \return queue id
3060 *
3061 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_queue()
3062 */
snd_seq_queue_info_get_queue(const snd_seq_queue_info_t * info)3063 int snd_seq_queue_info_get_queue(const snd_seq_queue_info_t *info)
3064 {
3065 assert(info);
3066 return info->queue;
3067 }
3068
3069 /**
3070 * \brief Get the name of a queue_info container
3071 * \param info queue_info container
3072 * \return name string
3073 *
3074 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_name()
3075 */
snd_seq_queue_info_get_name(const snd_seq_queue_info_t * info)3076 const char *snd_seq_queue_info_get_name(const snd_seq_queue_info_t *info)
3077 {
3078 assert(info);
3079 return info->name;
3080 }
3081
3082 /**
3083 * \brief Get the owner client id of a queue_info container
3084 * \param info queue_info container
3085 * \return owner client id
3086 *
3087 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_owner()
3088 */
snd_seq_queue_info_get_owner(const snd_seq_queue_info_t * info)3089 int snd_seq_queue_info_get_owner(const snd_seq_queue_info_t *info)
3090 {
3091 assert(info);
3092 return info->owner;
3093 }
3094
3095 /**
3096 * \brief Get the lock status of a queue_info container
3097 * \param info queue_info container
3098 * \return lock status --- non-zero = locked
3099 *
3100 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_locked()
3101 */
snd_seq_queue_info_get_locked(const snd_seq_queue_info_t * info)3102 int snd_seq_queue_info_get_locked(const snd_seq_queue_info_t *info)
3103 {
3104 assert(info);
3105 return info->locked;
3106 }
3107
3108 /**
3109 * \brief Get the conditional bit flags of a queue_info container
3110 * \param info queue_info container
3111 * \return conditional bit flags
3112 *
3113 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_set_flags()
3114 */
snd_seq_queue_info_get_flags(const snd_seq_queue_info_t * info)3115 unsigned int snd_seq_queue_info_get_flags(const snd_seq_queue_info_t *info)
3116 {
3117 assert(info);
3118 return info->flags;
3119 }
3120
3121 /**
3122 * \brief Set the name of a queue_info container
3123 * \param info queue_info container
3124 * \param name name string
3125 *
3126 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_name()
3127 */
snd_seq_queue_info_set_name(snd_seq_queue_info_t * info,const char * name)3128 void snd_seq_queue_info_set_name(snd_seq_queue_info_t *info, const char *name)
3129 {
3130 assert(info && name);
3131 snd_strlcpy(info->name, name, sizeof(info->name));
3132 }
3133
3134 /**
3135 * \brief Set the owner client id of a queue_info container
3136 * \param info queue_info container
3137 * \param owner client id
3138 *
3139 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_owner()
3140 */
snd_seq_queue_info_set_owner(snd_seq_queue_info_t * info,int owner)3141 void snd_seq_queue_info_set_owner(snd_seq_queue_info_t *info, int owner)
3142 {
3143 assert(info);
3144 info->owner = owner;
3145 }
3146
3147 /**
3148 * \brief Set the lock status of a queue_info container
3149 * \param info queue_info container
3150 * \param locked lock status
3151 *
3152 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_locked()
3153 */
snd_seq_queue_info_set_locked(snd_seq_queue_info_t * info,int locked)3154 void snd_seq_queue_info_set_locked(snd_seq_queue_info_t *info, int locked)
3155 {
3156 assert(info);
3157 info->locked = locked;
3158 }
3159
3160 /**
3161 * \brief Set the conditional bit flags of a queue_info container
3162 * \param info queue_info container
3163 * \param flags conditional bit flags
3164 *
3165 * \sa snd_seq_get_queue_info(), snd_seq_queue_info_get_flags()
3166 */
snd_seq_queue_info_set_flags(snd_seq_queue_info_t * info,unsigned int flags)3167 void snd_seq_queue_info_set_flags(snd_seq_queue_info_t *info, unsigned int flags)
3168 {
3169 assert(info);
3170 info->flags = flags;
3171 }
3172
3173
3174 /**
3175 * \brief create a queue
3176 * \param seq sequencer handle
3177 * \param info queue information to initialize
3178 * \return the queue id (zero or positive) on success otherwise a negative error code
3179 *
3180 * \sa snd_seq_alloc_queue()
3181 */
snd_seq_create_queue(snd_seq_t * seq,snd_seq_queue_info_t * info)3182 int snd_seq_create_queue(snd_seq_t *seq, snd_seq_queue_info_t *info)
3183 {
3184 int err;
3185 assert(seq && info);
3186 info->owner = seq->client;
3187 err = seq->ops->create_queue(seq, info);
3188 if (err < 0)
3189 return err;
3190 return info->queue;
3191 }
3192
3193 /**
3194 * \brief allocate a queue with the specified name
3195 * \param seq sequencer handle
3196 * \param name the name of the new queue
3197 * \return the queue id (zero or positive) on success otherwise a negative error code
3198 *
3199 * \sa snd_seq_alloc_queue()
3200 */
snd_seq_alloc_named_queue(snd_seq_t * seq,const char * name)3201 int snd_seq_alloc_named_queue(snd_seq_t *seq, const char *name)
3202 {
3203 snd_seq_queue_info_t info;
3204 memset(&info, 0, sizeof(info));
3205 info.locked = 1;
3206 if (name)
3207 snd_strlcpy(info.name, name, sizeof(info.name));
3208 return snd_seq_create_queue(seq, &info);
3209 }
3210
3211 /**
3212 * \brief allocate a queue
3213 * \param seq sequencer handle
3214 * \return the queue id (zero or positive) on success otherwise a negative error code
3215 *
3216 * \sa snd_seq_alloc_named_queue(), snd_seq_create_queue(), snd_seq_free_queue(),
3217 * snd_seq_get_queue_info()
3218 */
snd_seq_alloc_queue(snd_seq_t * seq)3219 int snd_seq_alloc_queue(snd_seq_t *seq)
3220 {
3221 return snd_seq_alloc_named_queue(seq, NULL);
3222 }
3223
3224 /**
3225 * \brief delete the specified queue
3226 * \param seq sequencer handle
3227 * \param q queue id to delete
3228 * \return 0 on success otherwise a negative error code
3229 *
3230 * \sa snd_seq_alloc_queue()
3231 */
snd_seq_free_queue(snd_seq_t * seq,int q)3232 int snd_seq_free_queue(snd_seq_t *seq, int q)
3233 {
3234 snd_seq_queue_info_t info;
3235 assert(seq);
3236 memset(&info, 0, sizeof(info));
3237 info.queue = q;
3238 return seq->ops->delete_queue(seq, &info);
3239 }
3240
3241 /**
3242 * \brief obtain queue attributes
3243 * \param seq sequencer handle
3244 * \param q queue id to query
3245 * \param info information returned
3246 * \return 0 on success otherwise a negative error code
3247 *
3248 * \sa snd_seq_alloc_queue(), snd_seq_set_queue_info(), snd_seq_query_named_queue()
3249 */
snd_seq_get_queue_info(snd_seq_t * seq,int q,snd_seq_queue_info_t * info)3250 int snd_seq_get_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
3251 {
3252 assert(seq && info);
3253 info->queue = q;
3254 return seq->ops->get_queue_info(seq, info);
3255 }
3256
3257 /**
3258 * \brief change the queue attributes
3259 * \param seq sequencer handle
3260 * \param q queue id to change
3261 * \param info information changed
3262 * \return 0 on success otherwise a negative error code
3263 *
3264 * \sa snd_seq_get_queue_info()
3265 */
snd_seq_set_queue_info(snd_seq_t * seq,int q,snd_seq_queue_info_t * info)3266 int snd_seq_set_queue_info(snd_seq_t *seq, int q, snd_seq_queue_info_t *info)
3267 {
3268 assert(seq && info);
3269 info->queue = q;
3270 return seq->ops->set_queue_info(seq, info);
3271 }
3272
3273 /**
3274 * \brief query the matching queue with the specified name
3275 * \param seq sequencer handle
3276 * \param name the name string to query
3277 * \return the queue id if found or negative error code
3278 *
3279 * Searches the matching queue with the specified name string.
3280 *
3281 * \sa snd_seq_get_queue_info()
3282 */
snd_seq_query_named_queue(snd_seq_t * seq,const char * name)3283 int snd_seq_query_named_queue(snd_seq_t *seq, const char *name)
3284 {
3285 int err;
3286 snd_seq_queue_info_t info;
3287 assert(seq && name);
3288 snd_strlcpy(info.name, name, sizeof(info.name));
3289 err = seq->ops->get_named_queue(seq, &info);
3290 if (err < 0)
3291 return err;
3292 return info.queue;
3293 }
3294
3295 /**
3296 * \brief Get the queue usage flag to the client
3297 * \param seq sequencer handle
3298 * \param q queue id
3299 * \return 1 = client is allowed to access the queue, 0 = not allowed,
3300 * otherwise a negative error code
3301 *
3302 * \sa snd_seq_get_queue_info(), snd_seq_set_queue_usage()
3303 */
snd_seq_get_queue_usage(snd_seq_t * seq,int q)3304 int snd_seq_get_queue_usage(snd_seq_t *seq, int q)
3305 {
3306 struct snd_seq_queue_client info;
3307 int err;
3308 assert(seq);
3309 memset(&info, 0, sizeof(info));
3310 info.queue = q;
3311 info.client = seq->client;
3312 if ((err = seq->ops->get_queue_client(seq, &info)) < 0)
3313 return err;
3314 return info.used;
3315 }
3316
3317 /**
3318 * \brief Set the queue usage flag to the client
3319 * \param seq sequencer handle
3320 * \param q queue id
3321 * \param used non-zero if the client is allowed
3322 * \return 0 on success otherwise a negative error code
3323 *
3324 * \sa snd_seq_get_queue_info(), snd_seq_set_queue_usage()
3325 */
snd_seq_set_queue_usage(snd_seq_t * seq,int q,int used)3326 int snd_seq_set_queue_usage(snd_seq_t *seq, int q, int used)
3327 {
3328 struct snd_seq_queue_client info;
3329 assert(seq);
3330 memset(&info, 0, sizeof(info));
3331 info.queue = q;
3332 info.client = seq->client;
3333 info.used = used ? 1 : 0;
3334 return seq->ops->set_queue_client(seq, &info);
3335 }
3336
3337
3338 /**
3339 * \brief get size of #snd_seq_queue_status_t
3340 * \return size in bytes
3341 */
snd_seq_queue_status_sizeof()3342 size_t snd_seq_queue_status_sizeof()
3343 {
3344 return sizeof(snd_seq_queue_status_t);
3345 }
3346
3347 /**
3348 * \brief allocate an empty #snd_seq_queue_status_t using standard malloc
3349 * \param ptr returned pointer
3350 * \return 0 on success otherwise negative error code
3351 */
snd_seq_queue_status_malloc(snd_seq_queue_status_t ** ptr)3352 int snd_seq_queue_status_malloc(snd_seq_queue_status_t **ptr)
3353 {
3354 assert(ptr);
3355 *ptr = calloc(1, sizeof(snd_seq_queue_status_t));
3356 if (!*ptr)
3357 return -ENOMEM;
3358 return 0;
3359 }
3360
3361 /**
3362 * \brief frees a previously allocated #snd_seq_queue_status_t
3363 * \param obj pointer to object to free
3364 */
snd_seq_queue_status_free(snd_seq_queue_status_t * obj)3365 void snd_seq_queue_status_free(snd_seq_queue_status_t *obj)
3366 {
3367 free(obj);
3368 }
3369
3370 /**
3371 * \brief copy one #snd_seq_queue_status_t to another
3372 * \param dst pointer to destination
3373 * \param src pointer to source
3374 */
snd_seq_queue_status_copy(snd_seq_queue_status_t * dst,const snd_seq_queue_status_t * src)3375 void snd_seq_queue_status_copy(snd_seq_queue_status_t *dst, const snd_seq_queue_status_t *src)
3376 {
3377 assert(dst && src);
3378 *dst = *src;
3379 }
3380
3381
3382 /**
3383 * \brief Get the queue id of a queue_status container
3384 * \param info queue_status container
3385 * \return queue id
3386 *
3387 * \sa snd_seq_get_queue_status()
3388 */
snd_seq_queue_status_get_queue(const snd_seq_queue_status_t * info)3389 int snd_seq_queue_status_get_queue(const snd_seq_queue_status_t *info)
3390 {
3391 assert(info);
3392 return info->queue;
3393 }
3394
3395 /**
3396 * \brief Get the number of events of a queue_status container
3397 * \param info queue_status container
3398 * \return number of events
3399 *
3400 * \sa snd_seq_get_queue_status()
3401 */
snd_seq_queue_status_get_events(const snd_seq_queue_status_t * info)3402 int snd_seq_queue_status_get_events(const snd_seq_queue_status_t *info)
3403 {
3404 assert(info);
3405 return info->events;
3406 }
3407
3408 /**
3409 * \brief Get the tick time of a queue_status container
3410 * \param info queue_status container
3411 * \return tick time
3412 *
3413 * \sa snd_seq_get_queue_status()
3414 */
snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t * info)3415 snd_seq_tick_time_t snd_seq_queue_status_get_tick_time(const snd_seq_queue_status_t *info)
3416 {
3417 assert(info);
3418 return info->tick;
3419 }
3420
3421 /**
3422 * \brief Get the real time of a queue_status container
3423 * \param info queue_status container
3424 *
3425 * \sa snd_seq_get_queue_status()
3426 */
snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t * info)3427 const snd_seq_real_time_t *snd_seq_queue_status_get_real_time(const snd_seq_queue_status_t *info)
3428 {
3429 assert(info);
3430 return (const snd_seq_real_time_t *)&info->time;
3431 }
3432
3433 /**
3434 * \brief Get the running status bits of a queue_status container
3435 * \param info queue_status container
3436 * \return running status bits
3437 *
3438 * \sa snd_seq_get_queue_status()
3439 */
snd_seq_queue_status_get_status(const snd_seq_queue_status_t * info)3440 unsigned int snd_seq_queue_status_get_status(const snd_seq_queue_status_t *info)
3441 {
3442 assert(info);
3443 return info->running;
3444 }
3445
3446
3447 /**
3448 * \brief obtain the running state of the queue
3449 * \param seq sequencer handle
3450 * \param q queue id to query
3451 * \param status pointer to store the current status
3452 * \return 0 on success otherwise a negative error code
3453 *
3454 * Obtains the running state of the specified queue q.
3455 */
snd_seq_get_queue_status(snd_seq_t * seq,int q,snd_seq_queue_status_t * status)3456 int snd_seq_get_queue_status(snd_seq_t *seq, int q, snd_seq_queue_status_t * status)
3457 {
3458 assert(seq && status);
3459 memset(status, 0, sizeof(snd_seq_queue_status_t));
3460 status->queue = q;
3461 return seq->ops->get_queue_status(seq, status);
3462 }
3463
3464
3465 /**
3466 * \brief get size of #snd_seq_queue_tempo_t
3467 * \return size in bytes
3468 */
snd_seq_queue_tempo_sizeof()3469 size_t snd_seq_queue_tempo_sizeof()
3470 {
3471 return sizeof(snd_seq_queue_tempo_t);
3472 }
3473
3474 /**
3475 * \brief allocate an empty #snd_seq_queue_tempo_t using standard malloc
3476 * \param ptr returned pointer
3477 * \return 0 on success otherwise negative error code
3478 */
snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t ** ptr)3479 int snd_seq_queue_tempo_malloc(snd_seq_queue_tempo_t **ptr)
3480 {
3481 assert(ptr);
3482 *ptr = calloc(1, sizeof(snd_seq_queue_tempo_t));
3483 if (!*ptr)
3484 return -ENOMEM;
3485 return 0;
3486 }
3487
3488 /**
3489 * \brief frees a previously allocated #snd_seq_queue_tempo_t
3490 * \param obj pointer to object to free
3491 */
snd_seq_queue_tempo_free(snd_seq_queue_tempo_t * obj)3492 void snd_seq_queue_tempo_free(snd_seq_queue_tempo_t *obj)
3493 {
3494 free(obj);
3495 }
3496
3497 /**
3498 * \brief copy one #snd_seq_queue_tempo_t to another
3499 * \param dst pointer to destination
3500 * \param src pointer to source
3501 */
snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t * dst,const snd_seq_queue_tempo_t * src)3502 void snd_seq_queue_tempo_copy(snd_seq_queue_tempo_t *dst, const snd_seq_queue_tempo_t *src)
3503 {
3504 assert(dst && src);
3505 *dst = *src;
3506 }
3507
3508
3509 /**
3510 * \brief Get the queue id of a queue_status container
3511 * \param info queue_status container
3512 * \return queue id
3513 *
3514 * \sa snd_seq_get_queue_tempo()
3515 */
snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t * info)3516 int snd_seq_queue_tempo_get_queue(const snd_seq_queue_tempo_t *info)
3517 {
3518 assert(info);
3519 return info->queue;
3520 }
3521
3522 /**
3523 * \brief Get the tempo of a queue_status container
3524 * \param info queue_status container
3525 * \return tempo value
3526 *
3527 * \sa snd_seq_get_queue_tempo()
3528 */
snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t * info)3529 unsigned int snd_seq_queue_tempo_get_tempo(const snd_seq_queue_tempo_t *info)
3530 {
3531 assert(info);
3532 return info->tempo;
3533 }
3534
3535 /**
3536 * \brief Get the ppq of a queue_status container
3537 * \param info queue_status container
3538 * \return ppq value
3539 *
3540 * \sa snd_seq_get_queue_tempo()
3541 */
snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t * info)3542 int snd_seq_queue_tempo_get_ppq(const snd_seq_queue_tempo_t *info)
3543 {
3544 assert(info);
3545 return info->ppq;
3546 }
3547
3548 /**
3549 * \brief Get the timer skew value of a queue_status container
3550 * \param info queue_status container
3551 * \return timer skew value
3552 *
3553 * \sa snd_seq_get_queue_tempo()
3554 */
snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t * info)3555 unsigned int snd_seq_queue_tempo_get_skew(const snd_seq_queue_tempo_t *info)
3556 {
3557 assert(info);
3558 return info->skew_value;
3559 }
3560
3561 /**
3562 * \brief Get the timer skew base value of a queue_status container
3563 * \param info queue_status container
3564 * \return timer skew base value
3565 *
3566 * \sa snd_seq_get_queue_tempo()
3567 */
snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t * info)3568 unsigned int snd_seq_queue_tempo_get_skew_base(const snd_seq_queue_tempo_t *info)
3569 {
3570 assert(info);
3571 return info->skew_base;
3572 }
3573
3574 /**
3575 * \brief Set the tempo of a queue_status container
3576 * \param info queue_status container
3577 * \param tempo tempo value
3578 *
3579 * \sa snd_seq_get_queue_tempo()
3580 */
snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t * info,unsigned int tempo)3581 void snd_seq_queue_tempo_set_tempo(snd_seq_queue_tempo_t *info, unsigned int tempo)
3582 {
3583 assert(info);
3584 info->tempo = tempo;
3585 }
3586
3587 /**
3588 * \brief Set the ppq of a queue_status container
3589 * \param info queue_status container
3590 * \param ppq ppq value
3591 *
3592 * \sa snd_seq_get_queue_tempo()
3593 */
snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t * info,int ppq)3594 void snd_seq_queue_tempo_set_ppq(snd_seq_queue_tempo_t *info, int ppq)
3595 {
3596 assert(info);
3597 info->ppq = ppq;
3598 }
3599
3600 /**
3601 * \brief Set the timer skew value of a queue_status container
3602 * \param info queue_status container
3603 * \param skew timer skew value
3604 *
3605 * The skew of timer is calculated as skew / base.
3606 * For example, to play with double speed, pass base * 2 as the skew value.
3607 *
3608 * \sa snd_seq_get_queue_tempo()
3609 */
snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t * info,unsigned int skew)3610 void snd_seq_queue_tempo_set_skew(snd_seq_queue_tempo_t *info, unsigned int skew)
3611 {
3612 assert(info);
3613 info->skew_value = skew;
3614 }
3615
3616 /**
3617 * \brief Set the timer skew base value of a queue_status container
3618 * \param info queue_status container
3619 * \param base timer skew base value
3620 *
3621 * \sa snd_seq_get_queue_tempo()
3622 */
snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t * info,unsigned int base)3623 void snd_seq_queue_tempo_set_skew_base(snd_seq_queue_tempo_t *info, unsigned int base)
3624 {
3625 assert(info);
3626 info->skew_base = base;
3627 }
3628
3629 /**
3630 * \brief obtain the current tempo of the queue
3631 * \param seq sequencer handle
3632 * \param q queue id to be queried
3633 * \param tempo pointer to store the current tempo
3634 * \return 0 on success otherwise a negative error code
3635 *
3636 * \sa snd_seq_set_queue_tempo()
3637 */
snd_seq_get_queue_tempo(snd_seq_t * seq,int q,snd_seq_queue_tempo_t * tempo)3638 int snd_seq_get_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
3639 {
3640 assert(seq && tempo);
3641 memset(tempo, 0, sizeof(snd_seq_queue_tempo_t));
3642 tempo->queue = q;
3643 return seq->ops->get_queue_tempo(seq, tempo);
3644 }
3645
3646 /**
3647 * \brief set the tempo of the queue
3648 * \param seq sequencer handle
3649 * \param q queue id to change the tempo
3650 * \param tempo tempo information
3651 * \return 0 on success otherwise a negative error code
3652 *
3653 * \sa snd_seq_get_queue_tempo()
3654 */
snd_seq_set_queue_tempo(snd_seq_t * seq,int q,snd_seq_queue_tempo_t * tempo)3655 int snd_seq_set_queue_tempo(snd_seq_t *seq, int q, snd_seq_queue_tempo_t * tempo)
3656 {
3657 assert(seq && tempo);
3658 tempo->queue = q;
3659 return seq->ops->set_queue_tempo(seq, tempo);
3660 }
3661
3662
3663 /*----------------------------------------------------------------*/
3664
3665 /**
3666 * \brief get size of #snd_seq_queue_timer_t
3667 * \return size in bytes
3668 */
snd_seq_queue_timer_sizeof()3669 size_t snd_seq_queue_timer_sizeof()
3670 {
3671 return sizeof(snd_seq_queue_timer_t);
3672 }
3673
3674 /**
3675 * \brief allocate an empty #snd_seq_queue_timer_t using standard malloc
3676 * \param ptr returned pointer
3677 * \return 0 on success otherwise negative error code
3678 */
snd_seq_queue_timer_malloc(snd_seq_queue_timer_t ** ptr)3679 int snd_seq_queue_timer_malloc(snd_seq_queue_timer_t **ptr)
3680 {
3681 assert(ptr);
3682 *ptr = calloc(1, sizeof(snd_seq_queue_timer_t));
3683 if (!*ptr)
3684 return -ENOMEM;
3685 return 0;
3686 }
3687
3688 /**
3689 * \brief frees a previously allocated #snd_seq_queue_timer_t
3690 * \param obj pointer to object to free
3691 */
snd_seq_queue_timer_free(snd_seq_queue_timer_t * obj)3692 void snd_seq_queue_timer_free(snd_seq_queue_timer_t *obj)
3693 {
3694 free(obj);
3695 }
3696
3697 /**
3698 * \brief copy one #snd_seq_queue_timer_t to another
3699 * \param dst pointer to destination
3700 * \param src pointer to source
3701 */
snd_seq_queue_timer_copy(snd_seq_queue_timer_t * dst,const snd_seq_queue_timer_t * src)3702 void snd_seq_queue_timer_copy(snd_seq_queue_timer_t *dst, const snd_seq_queue_timer_t *src)
3703 {
3704 assert(dst && src);
3705 *dst = *src;
3706 }
3707
3708
3709 /**
3710 * \brief Get the queue id of a queue_timer container
3711 * \param info queue_timer container
3712 * \return queue id
3713 *
3714 * \sa snd_seq_get_queue_timer()
3715 */
snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t * info)3716 int snd_seq_queue_timer_get_queue(const snd_seq_queue_timer_t *info)
3717 {
3718 assert(info);
3719 return info->queue;
3720 }
3721
3722 /**
3723 * \brief Get the timer type of a queue_timer container
3724 * \param info queue_timer container
3725 * \return timer type
3726 *
3727 * \sa snd_seq_get_queue_timer()
3728 */
snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t * info)3729 snd_seq_queue_timer_type_t snd_seq_queue_timer_get_type(const snd_seq_queue_timer_t *info)
3730 {
3731 assert(info);
3732 return (snd_seq_queue_timer_type_t)info->type;
3733 }
3734
3735 /**
3736 * \brief Get the timer id of a queue_timer container
3737 * \param info queue_timer container
3738 * \return timer id pointer
3739 *
3740 * \sa snd_seq_get_queue_timer()
3741 */
snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t * info)3742 const snd_timer_id_t *snd_seq_queue_timer_get_id(const snd_seq_queue_timer_t *info)
3743 {
3744 assert(info);
3745 return &info->u.alsa.id;
3746 }
3747
3748 /**
3749 * \brief Get the timer resolution of a queue_timer container
3750 * \param info queue_timer container
3751 * \return timer resolution
3752 *
3753 * \sa snd_seq_get_queue_timer()
3754 */
snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t * info)3755 unsigned int snd_seq_queue_timer_get_resolution(const snd_seq_queue_timer_t *info)
3756 {
3757 assert(info);
3758 return info->u.alsa.resolution;
3759 }
3760
3761 /**
3762 * \brief Set the timer type of a queue_timer container
3763 * \param info queue_timer container
3764 * \param type timer type
3765 *
3766 * \sa snd_seq_get_queue_timer()
3767 */
snd_seq_queue_timer_set_type(snd_seq_queue_timer_t * info,snd_seq_queue_timer_type_t type)3768 void snd_seq_queue_timer_set_type(snd_seq_queue_timer_t *info, snd_seq_queue_timer_type_t type)
3769 {
3770 assert(info);
3771 info->type = (int)type;
3772 }
3773
3774 /**
3775 * \brief Set the timer id of a queue_timer container
3776 * \param info queue_timer container
3777 * \param id timer id pointer
3778 *
3779 * \sa snd_seq_get_queue_timer()
3780 */
snd_seq_queue_timer_set_id(snd_seq_queue_timer_t * info,const snd_timer_id_t * id)3781 void snd_seq_queue_timer_set_id(snd_seq_queue_timer_t *info, const snd_timer_id_t *id)
3782 {
3783 assert(info && id);
3784 info->u.alsa.id = *id;
3785 }
3786
3787 /**
3788 * \brief Set the timer resolution of a queue_timer container
3789 * \param info queue_timer container
3790 * \param resolution timer resolution
3791 *
3792 * \sa snd_seq_get_queue_timer()
3793 */
snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t * info,unsigned int resolution)3794 void snd_seq_queue_timer_set_resolution(snd_seq_queue_timer_t *info, unsigned int resolution)
3795 {
3796 assert(info);
3797 info->u.alsa.resolution = resolution;
3798 }
3799
3800
3801 /**
3802 * \brief obtain the queue timer information
3803 * \param seq sequencer handle
3804 * \param q queue id to query
3805 * \param timer pointer to store the timer information
3806 * \return 0 on success otherwise a negative error code
3807 *
3808 * \sa snd_seq_set_queue_timer()
3809 */
snd_seq_get_queue_timer(snd_seq_t * seq,int q,snd_seq_queue_timer_t * timer)3810 int snd_seq_get_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
3811 {
3812 assert(seq && timer);
3813 memset(timer, 0, sizeof(snd_seq_queue_timer_t));
3814 timer->queue = q;
3815 return seq->ops->get_queue_timer(seq, timer);
3816 }
3817
3818 /**
3819 * \brief set the queue timer information
3820 * \param seq sequencer handle
3821 * \param q queue id to change the timer
3822 * \param timer timer information
3823 * \return 0 on success otherwise a negative error code
3824 *
3825 * \sa snd_seq_get_queue_timer()
3826 */
snd_seq_set_queue_timer(snd_seq_t * seq,int q,snd_seq_queue_timer_t * timer)3827 int snd_seq_set_queue_timer(snd_seq_t *seq, int q, snd_seq_queue_timer_t * timer)
3828 {
3829 assert(seq && timer);
3830 timer->queue = q;
3831 return seq->ops->set_queue_timer(seq, timer);
3832 }
3833
3834 /*----------------------------------------------------------------*/
3835
3836 #ifndef DOC_HIDDEN
3837 /**
3838 * \brief (DEPRECATED) create an event cell
3839 * \return the cell pointer allocated
3840 *
3841 * create an event cell via malloc. the returned pointer must be released
3842 * by the application itself via normal free() call,
3843 * not via snd_seq_free_event().
3844 */
snd_seq_create_event(void)3845 snd_seq_event_t *snd_seq_create_event(void)
3846 {
3847 return (snd_seq_event_t *) calloc(1, sizeof(snd_seq_event_t));
3848 }
3849 #endif
3850
3851 /**
3852 * \brief (DEPRECATED) free an event
3853 *
3854 * In the former version, this function was used to
3855 * release the event pointer which was allocated by snd_seq_event_input().
3856 * In the current version, the event record is not allocated, so
3857 * you don't have to call this function any more.
3858 */
3859 #ifndef DOXYGEN
snd_seq_free_event(snd_seq_event_t * ev ATTRIBUTE_UNUSED)3860 int snd_seq_free_event(snd_seq_event_t *ev ATTRIBUTE_UNUSED)
3861 #else
3862 int snd_seq_free_event(snd_seq_event_t *ev)
3863 #endif
3864 {
3865 return 0;
3866 }
3867
3868 /**
3869 * \brief calculates the (encoded) byte-stream size of the event
3870 * \param ev the event
3871 * \return the size of decoded bytes
3872 */
snd_seq_event_length(snd_seq_event_t * ev)3873 ssize_t snd_seq_event_length(snd_seq_event_t *ev)
3874 {
3875 ssize_t len = sizeof(snd_seq_event_t);
3876 assert(ev);
3877 if (snd_seq_ev_is_variable(ev))
3878 len += ev->data.ext.len;
3879 return len;
3880 }
3881
3882 /*----------------------------------------------------------------*/
3883
3884 /*
3885 * output to sequencer
3886 */
3887
3888 /**
3889 * \brief output an event
3890 * \param seq sequencer handle
3891 * \param ev event to be output
3892 * \return the number of remaining events or a negative error code
3893 *
3894 * An event is once expanded on the output buffer.
3895 * The output buffer will be drained automatically if it becomes full.
3896 *
3897 * If events remain unprocessed on output buffer before drained,
3898 * the size of total byte data on output buffer is returned.
3899 * If the output buffer is empty, this returns zero.
3900 *
3901 * \sa snd_seq_event_output_direct(), snd_seq_event_output_buffer(),
3902 * snd_seq_event_output_pending(), snd_seq_drain_output(),
3903 * snd_seq_drop_output(), snd_seq_extract_output(),
3904 * snd_seq_remove_events()
3905 */
snd_seq_event_output(snd_seq_t * seq,snd_seq_event_t * ev)3906 int snd_seq_event_output(snd_seq_t *seq, snd_seq_event_t *ev)
3907 {
3908 int result;
3909
3910 result = snd_seq_event_output_buffer(seq, ev);
3911 if (result == -EAGAIN) {
3912 result = snd_seq_drain_output(seq);
3913 if (result < 0)
3914 return result;
3915 return snd_seq_event_output_buffer(seq, ev);
3916 }
3917 return result;
3918 }
3919
3920 /**
3921 * \brief output an event onto the lib buffer without draining buffer
3922 * \param seq sequencer handle
3923 * \param ev event to be output
3924 * \return the byte size of remaining events. \c -EAGAIN if the buffer becomes full.
3925 *
3926 * This function doesn't drain buffer unlike snd_seq_event_output().
3927 *
3928 * \sa snd_seq_event_output()
3929 */
snd_seq_event_output_buffer(snd_seq_t * seq,snd_seq_event_t * ev)3930 int snd_seq_event_output_buffer(snd_seq_t *seq, snd_seq_event_t *ev)
3931 {
3932 int len;
3933 assert(seq && ev);
3934 len = snd_seq_event_length(ev);
3935 if (len < 0)
3936 return -EINVAL;
3937 if ((size_t) len >= seq->obufsize)
3938 return -EINVAL;
3939 if ((seq->obufsize - seq->obufused) < (size_t) len)
3940 return -EAGAIN;
3941 memcpy(seq->obuf + seq->obufused, ev, sizeof(snd_seq_event_t));
3942 seq->obufused += sizeof(snd_seq_event_t);
3943 if (snd_seq_ev_is_variable(ev)) {
3944 memcpy(seq->obuf + seq->obufused, ev->data.ext.ptr, ev->data.ext.len);
3945 seq->obufused += ev->data.ext.len;
3946 }
3947 return seq->obufused;
3948 }
3949
3950 /*
3951 * allocate the temporary buffer
3952 */
alloc_tmpbuf(snd_seq_t * seq,size_t len)3953 static int alloc_tmpbuf(snd_seq_t *seq, size_t len)
3954 {
3955 size_t size = ((len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t));
3956 if (seq->tmpbuf == NULL) {
3957 if (size > DEFAULT_TMPBUF_SIZE)
3958 seq->tmpbufsize = size;
3959 else
3960 seq->tmpbufsize = DEFAULT_TMPBUF_SIZE;
3961 seq->tmpbuf = malloc(seq->tmpbufsize * sizeof(snd_seq_event_t));
3962 if (seq->tmpbuf == NULL)
3963 return -ENOMEM;
3964 } else if (len > seq->tmpbufsize) {
3965 seq->tmpbuf = realloc(seq->tmpbuf, size * sizeof(snd_seq_event_t));
3966 if (seq->tmpbuf == NULL)
3967 return -ENOMEM;
3968 seq->tmpbufsize = size;
3969 }
3970 return 0;
3971 }
3972
3973 /**
3974 * \brief output an event directly to the sequencer NOT through output buffer
3975 * \param seq sequencer handle
3976 * \param ev event to be output
3977 * \return the byte size sent to sequencer or a negative error code
3978 *
3979 * This function sends an event to the sequencer directly not through the
3980 * output buffer. When the event is a variable length event, a temporary
3981 * buffer is allocated inside alsa-lib and the data is copied there before
3982 * actually sent.
3983 *
3984 * \sa snd_seq_event_output()
3985 */
snd_seq_event_output_direct(snd_seq_t * seq,snd_seq_event_t * ev)3986 int snd_seq_event_output_direct(snd_seq_t *seq, snd_seq_event_t *ev)
3987 {
3988 ssize_t len;
3989 void *buf;
3990
3991 len = snd_seq_event_length(ev);
3992 if (len < 0)
3993 return len;
3994 else if (len == sizeof(*ev)) {
3995 buf = ev;
3996 } else {
3997 if (alloc_tmpbuf(seq, (size_t)len) < 0)
3998 return -ENOMEM;
3999 *seq->tmpbuf = *ev;
4000 memcpy(seq->tmpbuf + 1, ev->data.ext.ptr, ev->data.ext.len);
4001 buf = seq->tmpbuf;
4002 }
4003 return seq->ops->write(seq, buf, (size_t) len);
4004 }
4005
4006 /**
4007 * \brief return the size of pending events on output buffer
4008 * \param seq sequencer handle
4009 * \return the byte size of total of pending events
4010 *
4011 * \sa snd_seq_event_output()
4012 */
snd_seq_event_output_pending(snd_seq_t * seq)4013 int snd_seq_event_output_pending(snd_seq_t *seq)
4014 {
4015 assert(seq);
4016 return seq->obufused;
4017 }
4018
4019 /**
4020 * \brief drain output buffer to sequencer
4021 * \param seq sequencer handle
4022 * \return 0 when all events are drained and sent to sequencer.
4023 * When events still remain on the buffer, the byte size of remaining
4024 * events are returned. On error a negative error code is returned.
4025 *
4026 * This function drains all pending events on the output buffer.
4027 * The function returns immediately after the events are sent to the queues
4028 * regardless whether the events are processed or not.
4029 * To get synchronization with the all event processes, use
4030 * #snd_seq_sync_output_queue() after calling this function.
4031 *
4032 * \sa snd_seq_event_output(), snd_seq_sync_output_queue()
4033 */
snd_seq_drain_output(snd_seq_t * seq)4034 int snd_seq_drain_output(snd_seq_t *seq)
4035 {
4036 ssize_t result, processed = 0;
4037 assert(seq);
4038 while (seq->obufused > 0) {
4039 result = seq->ops->write(seq, seq->obuf, seq->obufused);
4040 if (result < 0) {
4041 if (result == -EAGAIN && processed)
4042 return seq->obufused;
4043 return result;
4044 }
4045 if ((size_t)result < seq->obufused)
4046 memmove(seq->obuf, seq->obuf + result, seq->obufused - result);
4047 seq->obufused -= result;
4048 }
4049 return 0;
4050 }
4051
4052 /**
4053 * \brief extract the first event in output buffer
4054 * \param seq sequencer handle
4055 * \param ev_res event pointer to be extracted
4056 * \return 0 on success otherwise a negative error code
4057 *
4058 * Extracts the first event in output buffer.
4059 * If ev_res is NULL, just remove the event.
4060 *
4061 * \sa snd_seq_event_output()
4062 */
snd_seq_extract_output(snd_seq_t * seq,snd_seq_event_t ** ev_res)4063 int snd_seq_extract_output(snd_seq_t *seq, snd_seq_event_t **ev_res)
4064 {
4065 size_t len, olen;
4066 snd_seq_event_t ev;
4067 assert(seq);
4068 if (ev_res)
4069 *ev_res = NULL;
4070 if ((olen = seq->obufused) < sizeof(snd_seq_event_t))
4071 return -ENOENT;
4072 memcpy(&ev, seq->obuf, sizeof(snd_seq_event_t));
4073 len = snd_seq_event_length(&ev);
4074 if (ev_res) {
4075 /* extract the event */
4076 if (alloc_tmpbuf(seq, len) < 0)
4077 return -ENOMEM;
4078 memcpy(seq->tmpbuf, seq->obuf, len);
4079 *ev_res = seq->tmpbuf;
4080 }
4081 seq->obufused = olen - len;
4082 memmove(seq->obuf, seq->obuf + len, seq->obufused);
4083 return 0;
4084 }
4085
4086 /*----------------------------------------------------------------*/
4087
4088 /*
4089 * input from sequencer
4090 */
4091
4092 /*
4093 * read from sequencer to input buffer
4094 */
snd_seq_event_read_buffer(snd_seq_t * seq)4095 static ssize_t snd_seq_event_read_buffer(snd_seq_t *seq)
4096 {
4097 ssize_t len;
4098 len = (seq->ops->read)(seq, seq->ibuf, seq->ibufsize * sizeof(snd_seq_event_t));
4099 if (len < 0)
4100 return len;
4101 seq->ibuflen = len / sizeof(snd_seq_event_t);
4102 seq->ibufptr = 0;
4103 return seq->ibuflen;
4104 }
4105
snd_seq_event_retrieve_buffer(snd_seq_t * seq,snd_seq_event_t ** retp)4106 static int snd_seq_event_retrieve_buffer(snd_seq_t *seq, snd_seq_event_t **retp)
4107 {
4108 size_t ncells;
4109 snd_seq_event_t *ev;
4110
4111 *retp = ev = &seq->ibuf[seq->ibufptr];
4112 seq->ibufptr++;
4113 seq->ibuflen--;
4114 if (! snd_seq_ev_is_variable(ev))
4115 return 1;
4116 ncells = (ev->data.ext.len + sizeof(snd_seq_event_t) - 1) / sizeof(snd_seq_event_t);
4117 if (seq->ibuflen < ncells) {
4118 seq->ibuflen = 0; /* clear buffer */
4119 *retp = NULL;
4120 return -EINVAL;
4121 }
4122 ev->data.ext.ptr = ev + 1;
4123 seq->ibuflen -= ncells;
4124 seq->ibufptr += ncells;
4125 return 1;
4126 }
4127
4128 /**
4129 * \brief retrieve an event from sequencer
4130 * \param seq sequencer handle
4131 * \param ev event pointer to be stored
4132 * \return
4133 *
4134 * Obtains an input event from sequencer.
4135 * The event is created via snd_seq_create_event(), and its pointer is stored on
4136 * ev argument.
4137 *
4138 * This function firstly receives the event byte-stream data from sequencer
4139 * as much as possible at once. Then it retrieves the first event record
4140 * and store the pointer on ev.
4141 * By calling this function sequentially, events are extracted from the input buffer.
4142 *
4143 * If there is no input from sequencer, function falls into sleep
4144 * in blocking mode until an event is received,
4145 * or returns \c -EAGAIN error in non-blocking mode.
4146 * Occasionally, this function may return \c -ENOSPC error.
4147 * This means that the input FIFO of sequencer overran, and some events are
4148 * lost.
4149 * Once this error is returned, the input FIFO is cleared automatically.
4150 *
4151 * Function returns the byte size of remaining events on the input buffer
4152 * if an event is successfully received.
4153 * Application can determine from the returned value whether to call
4154 * input once more or not.
4155 *
4156 * \sa snd_seq_event_input_pending(), snd_seq_drop_input()
4157 */
snd_seq_event_input(snd_seq_t * seq,snd_seq_event_t ** ev)4158 int snd_seq_event_input(snd_seq_t *seq, snd_seq_event_t **ev)
4159 {
4160 int err;
4161 assert(seq);
4162 *ev = NULL;
4163 if (seq->ibuflen <= 0) {
4164 if ((err = snd_seq_event_read_buffer(seq)) < 0)
4165 return err;
4166 }
4167
4168 return snd_seq_event_retrieve_buffer(seq, ev);
4169 }
4170
4171 /*
4172 * read input data from sequencer if available
4173 */
snd_seq_event_input_feed(snd_seq_t * seq,int timeout)4174 static int snd_seq_event_input_feed(snd_seq_t *seq, int timeout)
4175 {
4176 struct pollfd pfd;
4177 int err;
4178 pfd.fd = seq->poll_fd;
4179 pfd.events = POLLIN;
4180 err = poll(&pfd, 1, timeout);
4181 if (err < 0) {
4182 SYSERR("poll");
4183 return -errno;
4184 }
4185 if (pfd.revents & POLLIN)
4186 return snd_seq_event_read_buffer(seq);
4187 return seq->ibuflen;
4188 }
4189
4190 /**
4191 * \brief check events in input buffer
4192 * \return the byte size of remaining input events on input buffer.
4193 *
4194 * If events remain on the input buffer of user-space, function returns
4195 * the total byte size of events on it.
4196 * If fetch_sequencer argument is non-zero,
4197 * this function checks the presence of events on sequencer FIFO
4198 * When events exist, they are transferred to the input buffer,
4199 * and the number of received events are returned.
4200 * If fetch_sequencer argument is zero and
4201 * no events remain on the input buffer, function simply returns zero.
4202 *
4203 * \sa snd_seq_event_input()
4204 */
snd_seq_event_input_pending(snd_seq_t * seq,int fetch_sequencer)4205 int snd_seq_event_input_pending(snd_seq_t *seq, int fetch_sequencer)
4206 {
4207 if (seq->ibuflen == 0 && fetch_sequencer) {
4208 return snd_seq_event_input_feed(seq, 0);
4209 }
4210 return seq->ibuflen;
4211 }
4212
4213 /*----------------------------------------------------------------*/
4214
4215 /*
4216 * clear event buffers
4217 */
4218
4219 /**
4220 * \brief remove all events on user-space output buffer
4221 * \param seq sequencer handle
4222 *
4223 * Removes all events on user-space output buffer.
4224 * Unlike snd_seq_drain_output(), this function doesn't remove
4225 * events on output memory pool of sequencer.
4226 *
4227 * \sa snd_seq_drop_output()
4228 */
snd_seq_drop_output_buffer(snd_seq_t * seq)4229 int snd_seq_drop_output_buffer(snd_seq_t *seq)
4230 {
4231 assert(seq);
4232 seq->obufused = 0;
4233 return 0;
4234 }
4235
4236 /**
4237 * \brief remove all events on user-space input FIFO
4238 * \param seq sequencer handle
4239 *
4240 * \sa snd_seq_drop_input()
4241 */
snd_seq_drop_input_buffer(snd_seq_t * seq)4242 int snd_seq_drop_input_buffer(snd_seq_t *seq)
4243 {
4244 assert(seq);
4245 seq->ibufptr = 0;
4246 seq->ibuflen = 0;
4247 return 0;
4248 }
4249
4250 /**
4251 * \brief remove all events on output buffer
4252 * \param seq sequencer handle
4253 *
4254 * Removes all events on both user-space output buffer and
4255 * output memory pool on kernel.
4256 *
4257 * \sa snd_seq_drain_output(), snd_seq_drop_output_buffer(), snd_seq_remove_events()
4258 */
snd_seq_drop_output(snd_seq_t * seq)4259 int snd_seq_drop_output(snd_seq_t *seq)
4260 {
4261 snd_seq_remove_events_t rminfo;
4262 assert(seq);
4263
4264 memset(&rminfo, 0, sizeof(rminfo));
4265 rminfo.remove_mode = SNDRV_SEQ_REMOVE_OUTPUT;
4266
4267 return snd_seq_remove_events(seq, &rminfo);
4268 }
4269
4270 /**
4271 * \brief clear input buffer and and remove events in sequencer queue
4272 * \param seq sequencer handle
4273 *
4274 * \sa snd_seq_drop_input_buffer(), snd_seq_remove_events()
4275 */
snd_seq_drop_input(snd_seq_t * seq)4276 int snd_seq_drop_input(snd_seq_t *seq)
4277 {
4278 snd_seq_remove_events_t rminfo;
4279 assert(seq);
4280
4281 memset(&rminfo, 0, sizeof(rminfo));
4282 rminfo.remove_mode = SNDRV_SEQ_REMOVE_INPUT;
4283
4284 return snd_seq_remove_events(seq, &rminfo);
4285 }
4286
4287
4288 /**
4289 * \brief get size of #snd_seq_remove_events_t
4290 * \return size in bytes
4291 */
snd_seq_remove_events_sizeof()4292 size_t snd_seq_remove_events_sizeof()
4293 {
4294 return sizeof(snd_seq_remove_events_t);
4295 }
4296
4297 /**
4298 * \brief allocate an empty #snd_seq_remove_events_t using standard malloc
4299 * \param ptr returned pointer
4300 * \return 0 on success otherwise negative error code
4301 */
snd_seq_remove_events_malloc(snd_seq_remove_events_t ** ptr)4302 int snd_seq_remove_events_malloc(snd_seq_remove_events_t **ptr)
4303 {
4304 assert(ptr);
4305 *ptr = calloc(1, sizeof(snd_seq_remove_events_t));
4306 if (!*ptr)
4307 return -ENOMEM;
4308 return 0;
4309 }
4310
4311 /**
4312 * \brief frees a previously allocated #snd_seq_remove_events_t
4313 * \param obj pointer to object to free
4314 */
snd_seq_remove_events_free(snd_seq_remove_events_t * obj)4315 void snd_seq_remove_events_free(snd_seq_remove_events_t *obj)
4316 {
4317 free(obj);
4318 }
4319
4320 /**
4321 * \brief copy one #snd_seq_remove_events_t to another
4322 * \param dst pointer to destination
4323 * \param src pointer to source
4324 */
snd_seq_remove_events_copy(snd_seq_remove_events_t * dst,const snd_seq_remove_events_t * src)4325 void snd_seq_remove_events_copy(snd_seq_remove_events_t *dst, const snd_seq_remove_events_t *src)
4326 {
4327 assert(dst && src);
4328 *dst = *src;
4329 }
4330
4331
4332 /**
4333 * \brief Get the removal condition bits
4334 * \param info remove_events container
4335 * \return removal condition bits
4336 *
4337 * \sa snd_seq_remove_events()
4338 */
snd_seq_remove_events_get_condition(const snd_seq_remove_events_t * info)4339 unsigned int snd_seq_remove_events_get_condition(const snd_seq_remove_events_t *info)
4340 {
4341 assert(info);
4342 return info->remove_mode;
4343 }
4344
4345 /**
4346 * \brief Get the queue as removal condition
4347 * \param info remove_events container
4348 * \return queue id
4349 *
4350 * \sa snd_seq_remove_events()
4351 */
snd_seq_remove_events_get_queue(const snd_seq_remove_events_t * info)4352 int snd_seq_remove_events_get_queue(const snd_seq_remove_events_t *info)
4353 {
4354 assert(info);
4355 return info->queue;
4356 }
4357
4358 /**
4359 * \brief Get the event timestamp as removal condition
4360 * \param info remove_events container
4361 * \return time stamp
4362 *
4363 * \sa snd_seq_remove_events()
4364 */
snd_seq_remove_events_get_time(const snd_seq_remove_events_t * info)4365 const snd_seq_timestamp_t *snd_seq_remove_events_get_time(const snd_seq_remove_events_t *info)
4366 {
4367 assert(info);
4368 return (const snd_seq_timestamp_t *)&info->time;
4369 }
4370
4371 /**
4372 * \brief Get the event destination address as removal condition
4373 * \param info remove_events container
4374 * \return destination address
4375 *
4376 * \sa snd_seq_remove_events()
4377 */
snd_seq_remove_events_get_dest(const snd_seq_remove_events_t * info)4378 const snd_seq_addr_t *snd_seq_remove_events_get_dest(const snd_seq_remove_events_t *info)
4379 {
4380 assert(info);
4381 return (const snd_seq_addr_t *)&info->dest;
4382 }
4383
4384 /**
4385 * \brief Get the event channel as removal condition
4386 * \param info remove_events container
4387 * \return channel number
4388 *
4389 * \sa snd_seq_remove_events()
4390 */
snd_seq_remove_events_get_channel(const snd_seq_remove_events_t * info)4391 int snd_seq_remove_events_get_channel(const snd_seq_remove_events_t *info)
4392 {
4393 assert(info);
4394 return info->channel;
4395 }
4396
4397 /**
4398 * \brief Get the event type as removal condition
4399 * \param info remove_events container
4400 * \return event type
4401 *
4402 * \sa snd_seq_remove_events()
4403 */
snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t * info)4404 int snd_seq_remove_events_get_event_type(const snd_seq_remove_events_t *info)
4405 {
4406 assert(info);
4407 return info->type;
4408 }
4409
4410 /**
4411 * \brief Get the event tag id as removal condition
4412 * \param info remove_events container
4413 * \return tag id
4414 *
4415 * \sa snd_seq_remove_events()
4416 */
snd_seq_remove_events_get_tag(const snd_seq_remove_events_t * info)4417 int snd_seq_remove_events_get_tag(const snd_seq_remove_events_t *info)
4418 {
4419 assert(info);
4420 return info->tag;
4421 }
4422
4423 /**
4424 * \brief Set the removal condition bits
4425 * \param info remove_events container
4426 * \param flags removal condition bits
4427 *
4428 * \sa snd_seq_remove_events()
4429 */
snd_seq_remove_events_set_condition(snd_seq_remove_events_t * info,unsigned int flags)4430 void snd_seq_remove_events_set_condition(snd_seq_remove_events_t *info, unsigned int flags)
4431 {
4432 assert(info);
4433 info->remove_mode = flags;
4434 }
4435
4436 /**
4437 * \brief Set the queue as removal condition
4438 * \param info remove_events container
4439 * \param queue queue id
4440 *
4441 * \sa snd_seq_remove_events()
4442 */
snd_seq_remove_events_set_queue(snd_seq_remove_events_t * info,int queue)4443 void snd_seq_remove_events_set_queue(snd_seq_remove_events_t *info, int queue)
4444 {
4445 assert(info);
4446 info->queue = queue;
4447 }
4448
4449 /**
4450 * \brief Set the timestamp as removal condition
4451 * \param info remove_events container
4452 * \param time timestamp pointer
4453 *
4454 * \sa snd_seq_remove_events()
4455 */
snd_seq_remove_events_set_time(snd_seq_remove_events_t * info,const snd_seq_timestamp_t * time)4456 void snd_seq_remove_events_set_time(snd_seq_remove_events_t *info, const snd_seq_timestamp_t *time)
4457 {
4458 assert(info);
4459 info->time = *(const union sndrv_seq_timestamp *)time;
4460 }
4461
4462 /**
4463 * \brief Set the destination address as removal condition
4464 * \param info remove_events container
4465 * \param addr destination address
4466 *
4467 * \sa snd_seq_remove_events()
4468 */
snd_seq_remove_events_set_dest(snd_seq_remove_events_t * info,const snd_seq_addr_t * addr)4469 void snd_seq_remove_events_set_dest(snd_seq_remove_events_t *info, const snd_seq_addr_t *addr)
4470 {
4471 assert(info);
4472 info->dest = *(const struct sndrv_seq_addr *)addr;
4473 }
4474
4475 /**
4476 * \brief Set the channel as removal condition
4477 * \param info remove_events container
4478 * \param channel channel number
4479 *
4480 * \sa snd_seq_remove_events()
4481 */
snd_seq_remove_events_set_channel(snd_seq_remove_events_t * info,int channel)4482 void snd_seq_remove_events_set_channel(snd_seq_remove_events_t *info, int channel)
4483 {
4484 assert(info);
4485 info->channel = channel;
4486 }
4487
4488 /**
4489 * \brief Set the event type as removal condition
4490 * \param info remove_events container
4491 * \param type event type
4492 *
4493 * \sa snd_seq_remove_events()
4494 */
snd_seq_remove_events_set_event_type(snd_seq_remove_events_t * info,int type)4495 void snd_seq_remove_events_set_event_type(snd_seq_remove_events_t *info, int type)
4496 {
4497 assert(info);
4498 info->type = type;
4499 }
4500
4501 /**
4502 * \brief Set the event tag as removal condition
4503 * \param info remove_events container
4504 * \param tag tag id
4505 *
4506 * \sa snd_seq_remove_events()
4507 */
snd_seq_remove_events_set_tag(snd_seq_remove_events_t * info,int tag)4508 void snd_seq_remove_events_set_tag(snd_seq_remove_events_t *info, int tag)
4509 {
4510 assert(info);
4511 info->tag = tag;
4512 }
4513
4514
4515 /* compare timestamp between events */
4516 /* 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)4517 static inline int snd_seq_compare_tick_time(snd_seq_tick_time_t *a, snd_seq_tick_time_t *b)
4518 {
4519 /* compare ticks */
4520 return (*a >= *b);
4521 }
4522
snd_seq_compare_real_time(snd_seq_real_time_t * a,snd_seq_real_time_t * b)4523 static inline int snd_seq_compare_real_time(snd_seq_real_time_t *a, snd_seq_real_time_t *b)
4524 {
4525 /* compare real time */
4526 if (a->tv_sec > b->tv_sec)
4527 return 1;
4528 if ((a->tv_sec == b->tv_sec) && (a->tv_nsec >= b->tv_nsec))
4529 return 1;
4530 return 0;
4531 }
4532
4533 /* Routine to match events to be removed */
remove_match(snd_seq_remove_events_t * info,snd_seq_event_t * ev)4534 static int remove_match(snd_seq_remove_events_t *info, snd_seq_event_t *ev)
4535 {
4536 int res;
4537
4538 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
4539 if (ev->dest.client != info->dest.client ||
4540 ev->dest.port != info->dest.port)
4541 return 0;
4542 }
4543 if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
4544 if (! snd_seq_ev_is_channel_type(ev))
4545 return 0;
4546 /* data.note.channel and data.control.channel are identical */
4547 if (ev->data.note.channel != info->channel)
4548 return 0;
4549 }
4550 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
4551 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
4552 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
4553 else
4554 res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
4555 if (!res)
4556 return 0;
4557 }
4558 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
4559 if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
4560 res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
4561 else
4562 res = snd_seq_compare_real_time(&ev->time.time, (snd_seq_real_time_t *)&info->time.time);
4563 if (res)
4564 return 0;
4565 }
4566 if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
4567 if (ev->type != info->type)
4568 return 0;
4569 }
4570 if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
4571 /* Do not remove off events */
4572 switch (ev->type) {
4573 case SND_SEQ_EVENT_NOTEOFF:
4574 /* case SND_SEQ_EVENT_SAMPLE_STOP: */
4575 return 0;
4576 default:
4577 break;
4578 }
4579 }
4580 if (info->remove_mode & SNDRV_SEQ_REMOVE_TAG_MATCH) {
4581 if (info->tag != ev->tag)
4582 return 0;
4583 }
4584
4585 return 1;
4586 }
4587
4588 /**
4589 * \brief remove events on input/output buffers and pools
4590 * \param seq sequencer handle
4591 * \param rmp remove event container
4592 *
4593 * Removes matching events with the given condition from input/output buffers
4594 * and pools.
4595 * The removal condition is specified in \a rmp argument.
4596 *
4597 * \sa snd_seq_event_output(), snd_seq_drop_output(), snd_seq_reset_pool_output()
4598 */
snd_seq_remove_events(snd_seq_t * seq,snd_seq_remove_events_t * rmp)4599 int snd_seq_remove_events(snd_seq_t *seq, snd_seq_remove_events_t *rmp)
4600 {
4601 if (rmp->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
4602 /*
4603 * First deal with any events that are still buffered
4604 * in the library.
4605 */
4606 snd_seq_drop_input_buffer(seq);
4607 }
4608
4609 if (rmp->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) {
4610 /*
4611 * First deal with any events that are still buffered
4612 * in the library.
4613 */
4614 if (! (rmp->remove_mode & ~(SNDRV_SEQ_REMOVE_INPUT|SNDRV_SEQ_REMOVE_OUTPUT))) {
4615 /* The simple case - remove all */
4616 snd_seq_drop_output_buffer(seq);
4617 } else {
4618 char *ep;
4619 size_t len;
4620 snd_seq_event_t *ev;
4621
4622 ep = seq->obuf;
4623 while (ep - seq->obuf < (ssize_t)seq->obufused) {
4624
4625 ev = (snd_seq_event_t *)ep;
4626 len = snd_seq_event_length(ev);
4627
4628 if (remove_match(rmp, ev)) {
4629 /* Remove event */
4630 seq->obufused -= len;
4631 memmove(ep, ep + len, seq->obufused - (ep - seq->obuf));
4632 } else {
4633 ep += len;
4634 }
4635 }
4636 }
4637 }
4638
4639 return seq->ops->remove_events(seq, rmp);
4640 }
4641
4642 /*----------------------------------------------------------------*/
4643
4644 /*
4645 * client memory pool
4646 */
4647
4648 /**
4649 * \brief get size of #snd_seq_client_pool_t
4650 * \return size in bytes
4651 */
snd_seq_client_pool_sizeof()4652 size_t snd_seq_client_pool_sizeof()
4653 {
4654 return sizeof(snd_seq_client_pool_t);
4655 }
4656
4657 /**
4658 * \brief allocate an empty #snd_seq_client_pool_t using standard malloc
4659 * \param ptr returned pointer
4660 * \return 0 on success otherwise negative error code
4661 */
snd_seq_client_pool_malloc(snd_seq_client_pool_t ** ptr)4662 int snd_seq_client_pool_malloc(snd_seq_client_pool_t **ptr)
4663 {
4664 assert(ptr);
4665 *ptr = calloc(1, sizeof(snd_seq_client_pool_t));
4666 if (!*ptr)
4667 return -ENOMEM;
4668 return 0;
4669 }
4670
4671 /**
4672 * \brief frees a previously allocated #snd_seq_client_pool_t
4673 * \param obj pointer to object to free
4674 */
snd_seq_client_pool_free(snd_seq_client_pool_t * obj)4675 void snd_seq_client_pool_free(snd_seq_client_pool_t *obj)
4676 {
4677 free(obj);
4678 }
4679
4680 /**
4681 * \brief copy one #snd_seq_client_pool_t to another
4682 * \param dst pointer to destination
4683 * \param src pointer to source
4684 */
snd_seq_client_pool_copy(snd_seq_client_pool_t * dst,const snd_seq_client_pool_t * src)4685 void snd_seq_client_pool_copy(snd_seq_client_pool_t *dst, const snd_seq_client_pool_t *src)
4686 {
4687 assert(dst && src);
4688 *dst = *src;
4689 }
4690
4691
4692 /**
4693 * \brief Get the client id of a queue_info container
4694 * \param info client_pool container
4695 * \return client id
4696 */
snd_seq_client_pool_get_client(const snd_seq_client_pool_t * info)4697 int snd_seq_client_pool_get_client(const snd_seq_client_pool_t *info)
4698 {
4699 assert(info);
4700 return info->client;
4701 }
4702
4703 /**
4704 * \brief Get the output pool size of a queue_info container
4705 * \param info client_pool container
4706 * \return output pool size
4707 */
snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t * info)4708 size_t snd_seq_client_pool_get_output_pool(const snd_seq_client_pool_t *info)
4709 {
4710 assert(info);
4711 return info->output_pool;
4712 }
4713
4714 /**
4715 * \brief Get the input pool size of a queue_info container
4716 * \param info client_pool container
4717 * \return input pool size
4718 */
snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t * info)4719 size_t snd_seq_client_pool_get_input_pool(const snd_seq_client_pool_t *info)
4720 {
4721 assert(info);
4722 return info->input_pool;
4723 }
4724
4725 /**
4726 * \brief Get the output room size of a queue_info container
4727 * \param info client_pool container
4728 * \return output room size
4729 */
snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t * info)4730 size_t snd_seq_client_pool_get_output_room(const snd_seq_client_pool_t *info)
4731 {
4732 assert(info);
4733 return info->output_room;
4734 }
4735
4736 /**
4737 * \brief Get the available size on output pool of a queue_info container
4738 * \param info client_pool container
4739 * \return available output size
4740 */
snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t * info)4741 size_t snd_seq_client_pool_get_output_free(const snd_seq_client_pool_t *info)
4742 {
4743 assert(info);
4744 return info->output_free;
4745 }
4746
4747 /**
4748 * \brief Get the available size on input pool of a queue_info container
4749 * \param info client_pool container
4750 * \return available input size
4751 */
snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t * info)4752 size_t snd_seq_client_pool_get_input_free(const snd_seq_client_pool_t *info)
4753 {
4754 assert(info);
4755 return info->input_free;
4756 }
4757
4758 /**
4759 * \brief Set the output pool size of a queue_info container
4760 * \param info client_pool container
4761 * \param size output pool size
4762 */
snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t * info,size_t size)4763 void snd_seq_client_pool_set_output_pool(snd_seq_client_pool_t *info, size_t size)
4764 {
4765 assert(info);
4766 info->output_pool = size;
4767 }
4768
4769 /**
4770 * \brief Set the input pool size of a queue_info container
4771 * \param info client_pool container
4772 * \param size input pool size
4773 */
snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t * info,size_t size)4774 void snd_seq_client_pool_set_input_pool(snd_seq_client_pool_t *info, size_t size)
4775 {
4776 assert(info);
4777 info->input_pool = size;
4778 }
4779
4780 /**
4781 * \brief Set the output room size of a queue_info container
4782 * \param info client_pool container
4783 * \param size output room size
4784 */
snd_seq_client_pool_set_output_room(snd_seq_client_pool_t * info,size_t size)4785 void snd_seq_client_pool_set_output_room(snd_seq_client_pool_t *info, size_t size)
4786 {
4787 assert(info);
4788 info->output_room = size;
4789 }
4790
4791
4792 /**
4793 * \brief obtain the pool information of the current client
4794 * \param seq sequencer handle
4795 * \param info information to be stored
4796 */
snd_seq_get_client_pool(snd_seq_t * seq,snd_seq_client_pool_t * info)4797 int snd_seq_get_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
4798 {
4799 assert(seq && info);
4800 info->client = seq->client;
4801 return seq->ops->get_client_pool(seq, info);
4802 }
4803
4804 /**
4805 * \brief set the pool information
4806 * \param seq sequencer handle
4807 * \param info information to update
4808 *
4809 * Sets the pool information of the current client.
4810 * The client field in \a info is replaced automatically with the current id.
4811 */
snd_seq_set_client_pool(snd_seq_t * seq,snd_seq_client_pool_t * info)4812 int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info)
4813 {
4814 assert(seq && info);
4815 info->client = seq->client;
4816 return seq->ops->set_client_pool(seq, info);
4817 }
4818
4819 /*----------------------------------------------------------------*/
4820
4821 /*
4822 * misc.
4823 */
4824
4825 /**
4826 * \brief set a bit flag
4827 */
snd_seq_set_bit(int nr,void * array)4828 void snd_seq_set_bit(int nr, void *array)
4829 {
4830 ((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31);
4831 }
4832
4833 /**
4834 * \brief unset a bit flag
4835 */
snd_seq_unset_bit(int nr,void * array)4836 void snd_seq_unset_bit(int nr, void *array)
4837 {
4838 ((unsigned int *)array)[nr >> 5] &= ~(1UL << (nr & 31));
4839 }
4840
4841 /**
4842 * \brief change a bit flag
4843 */
snd_seq_change_bit(int nr,void * array)4844 int snd_seq_change_bit(int nr, void *array)
4845 {
4846 int result;
4847
4848 result = ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
4849 ((unsigned int *)array)[nr >> 5] ^= 1UL << (nr & 31);
4850 return result;
4851 }
4852
4853 /**
4854 * \brief get a bit flag state
4855 */
snd_seq_get_bit(int nr,void * array)4856 int snd_seq_get_bit(int nr, void *array)
4857 {
4858 return ((((unsigned int *)array)[nr >> 5]) & (1UL << (nr & 31))) ? 1 : 0;
4859 }
4860