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