1 /*
2 MIDI Sequencer C++ library
3 Copyright (C) 2006-2021, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "errorcheck.h"
20 #include <cmath>
21 #include <drumstick/alsaclient.h>
22 #include <drumstick/alsaevent.h>
23 #include <drumstick/alsaqueue.h>
24 #include <drumstick/alsatimer.h>
25
26 /**
27 * @file alsaqueue.cpp
28 * Implementation of classes managing ALSA Sequencer queues
29 */
30
31 namespace drumstick {
32 namespace ALSA {
33
34 /**
35 * This is the value for the base skew used in ALSA. It is not possible
36 * to assign an arbitrary value (ALSA version <= 1.0.20).
37 */
38 const unsigned int SKEW_BASE = 0x10000;
39
40 /**
41 * @addtogroup ALSAQueue
42 * @{
43 *
44 * ALSA events can be delivered to the output ports at scheduled times using the
45 * queues. There is a small amount of available queues in the system, so this is
46 * a limited resource. Queues are also used to time-stamp incoming events.
47 *
48 * Classes:
49 *
50 * QueueInfo holds several properties about the queue object.
51 *
52 * QueueStatus is used to retrieve the status of the queue object.
53 *
54 * QueueTempo holds properties to get and set the tempo in the queue object.
55 *
56 * QueueTimer holds properties about the Timer used in the queue object.
57 *
58 * MidiQueue represents the queue object.
59 *
60 * @see https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html
61 * @}
62 */
63
64 /**
65 * Default constructor
66 */
QueueInfo()67 QueueInfo::QueueInfo()
68 {
69 snd_seq_queue_info_malloc(&m_Info);
70 }
71
72 /**
73 * Constructor.
74 * @param other ALSA queue info object pointer
75 */
QueueInfo(snd_seq_queue_info_t * other)76 QueueInfo::QueueInfo(snd_seq_queue_info_t* other)
77 {
78 snd_seq_queue_info_malloc(&m_Info);
79 snd_seq_queue_info_copy(m_Info, other);
80 }
81
82 /**
83 * Copy constructor.
84 * @param other An existing QueueInfo object reference.
85 */
QueueInfo(const QueueInfo & other)86 QueueInfo::QueueInfo(const QueueInfo& other)
87 {
88 snd_seq_queue_info_malloc(&m_Info);
89 snd_seq_queue_info_copy(m_Info, other.m_Info);
90 }
91
92 /**
93 * Destructor
94 */
~QueueInfo()95 QueueInfo::~QueueInfo()
96 {
97 snd_seq_queue_info_free(m_Info);
98 }
99
100 /**
101 * Copy the current object and return the copy.
102 * @return The pointer to the new object.
103 */
clone()104 QueueInfo* QueueInfo::clone()
105 {
106 return new QueueInfo(m_Info);
107 }
108
109 /**
110 * Assignment operator.
111 * @param other An existing QueueInfo object reference.
112 * @return This object.
113 */
operator =(const QueueInfo & other)114 QueueInfo& QueueInfo::operator=(const QueueInfo& other)
115 {
116 if (this == &other)
117 return *this;
118 snd_seq_queue_info_copy(m_Info, other.m_Info);
119 return *this;
120 }
121
122 /**
123 * Gets the queue's numeric identifier.
124 * @return The numeric identifier.
125 */
getId()126 int QueueInfo::getId()
127 {
128 return snd_seq_queue_info_get_queue(m_Info);
129 }
130
131 /**
132 * Gets the queue name
133 * @return The queue name.
134 */
getName()135 QString QueueInfo::getName()
136 {
137 return QString(snd_seq_queue_info_get_name(m_Info));
138 }
139
140 /**
141 * Gets the owner's client id of the queue.
142 * @return the owner's client id.
143 */
getOwner()144 int QueueInfo::getOwner()
145 {
146 return snd_seq_queue_info_get_owner(m_Info);
147 }
148
149 /**
150 * Returns the locking status of the queue
151 * @return The locking status.
152 */
isLocked()153 bool QueueInfo::isLocked()
154 {
155 return (snd_seq_queue_info_get_locked(m_Info) != 0);
156 }
157
158 /**
159 * Gets the flags of the queue.
160 * @return The flags of the queue.
161 */
getFlags()162 unsigned int QueueInfo::getFlags()
163 {
164 return snd_seq_queue_info_get_flags(m_Info);
165 }
166
167 /**
168 * Sets the queue name
169 * @param value The queue name
170 */
setName(QString value)171 void QueueInfo::setName(QString value)
172 {
173 snd_seq_queue_info_set_name(m_Info, value.toLocal8Bit().data());
174 }
175
176 /**
177 * Sets the client ID of the owner
178 * @param value The client ID of the owner
179 */
setOwner(int value)180 void QueueInfo::setOwner(int value)
181 {
182 snd_seq_queue_info_set_owner(m_Info, value);
183 }
184
185 /**
186 * Sets the bit flags of the queue
187 * @param value The bit flags
188 */
setFlags(unsigned int value)189 void QueueInfo::setFlags(unsigned int value)
190 {
191 snd_seq_queue_info_set_flags(m_Info, value);
192 }
193
194 /**
195 * Sets the locked status of the queue
196 * @param locked The locked status
197 */
setLocked(bool locked)198 void QueueInfo::setLocked(bool locked)
199 {
200 snd_seq_queue_info_set_locked(m_Info, locked ? 1 : 0);
201 }
202
203 /**
204 * Gets the size of the ALSA queue info object.
205 * @return The size of the ALSA object.
206 */
getInfoSize() const207 int QueueInfo::getInfoSize() const
208 {
209 return snd_seq_queue_info_sizeof();
210 }
211
212
213 /**
214 * Default constructor
215 */
QueueStatus()216 QueueStatus::QueueStatus()
217 {
218 snd_seq_queue_status_malloc(&m_Info);
219 }
220
221 /**
222 * Constructor
223 * @param other ALSA queue status object pointer
224 */
QueueStatus(snd_seq_queue_status_t * other)225 QueueStatus::QueueStatus(snd_seq_queue_status_t* other)
226 {
227 snd_seq_queue_status_malloc(&m_Info);
228 snd_seq_queue_status_copy(m_Info, other);
229 }
230
231 /**
232 * Copy constructor
233 * @param other An existing QueueStatus object reference
234 */
QueueStatus(const QueueStatus & other)235 QueueStatus::QueueStatus(const QueueStatus& other)
236 {
237 snd_seq_queue_status_malloc(&m_Info);
238 snd_seq_queue_status_copy(m_Info, other.m_Info);
239 }
240
241 /**
242 * Destructor
243 */
~QueueStatus()244 QueueStatus::~QueueStatus()
245 {
246 snd_seq_queue_status_free(m_Info);
247 }
248
249 /**
250 * Copy the current object and return the copy
251 * @return The pointer to the new object
252 */
clone()253 QueueStatus* QueueStatus::clone()
254 {
255 return new QueueStatus(m_Info);
256 }
257
258 /**
259 * Assignment operator
260 * @param other An existing QueueStatus object reference
261 * @return This object
262 */
operator =(const QueueStatus & other)263 QueueStatus& QueueStatus::operator=(const QueueStatus& other)
264 {
265 if (this == &other)
266 return *this;
267 snd_seq_queue_status_copy(m_Info, other.m_Info);
268 return *this;
269 }
270
271 /**
272 * Gets the queue's numeric identifier
273 * @return The queue's numeric identifier.
274 */
getId()275 int QueueStatus::getId()
276 {
277 return snd_seq_queue_status_get_queue(m_Info);
278 }
279
280 /**
281 * Gets the number of queued events
282 * @return The number of queued events
283 */
getEvents()284 int QueueStatus::getEvents()
285 {
286 return snd_seq_queue_status_get_events(m_Info);
287 }
288
289 /**
290 * Gets the real time (secods and nanoseconds) of the queue
291 * @return The queue's real time.
292 */
getRealtime()293 const snd_seq_real_time_t* QueueStatus::getRealtime()
294 {
295 return snd_seq_queue_status_get_real_time(m_Info);
296 }
297
298 /**
299 * Gets the running status bits
300 * @return The running status bits
301 */
getStatusBits()302 unsigned int QueueStatus::getStatusBits()
303 {
304 return snd_seq_queue_status_get_status(m_Info);
305 }
306
307 /**
308 * Gets the musical time (ticks) of the queue
309 * @return The musical time
310 */
getTickTime()311 snd_seq_tick_time_t QueueStatus::getTickTime()
312 {
313 return snd_seq_queue_status_get_tick_time(m_Info);
314 }
315
316 /**
317 * Gets the size of the ALSA status object
318 * @return The size of the ALSA object
319 */
getInfoSize() const320 int QueueStatus::getInfoSize() const
321 {
322 return snd_seq_queue_status_sizeof();
323 }
324
325 /**
326 * Gets the queue's running state
327 * @return True if the queue is running
328 */
isRunning()329 bool QueueStatus::isRunning()
330 {
331 return (snd_seq_queue_status_get_status(m_Info) != 0);
332 }
333
334 /**
335 * Gets the clock time in seconds of the queue
336 * @return The queue time in seconds
337 */
getClockTime()338 double QueueStatus::getClockTime()
339 {
340 const snd_seq_real_time_t* time = snd_seq_queue_status_get_real_time(m_Info);
341 return (time->tv_sec * 1.0) + (time->tv_nsec * 1.0e-9);
342 }
343
344 /**
345 * Default constructor
346 */
QueueTempo()347 QueueTempo::QueueTempo()
348 {
349 snd_seq_queue_tempo_malloc(&m_Info);
350 }
351
352 /**
353 * Constructor
354 * @param other An ALSA queue tempo object pointer
355 */
QueueTempo(snd_seq_queue_tempo_t * other)356 QueueTempo::QueueTempo(snd_seq_queue_tempo_t* other)
357 {
358 snd_seq_queue_tempo_malloc(&m_Info);
359 snd_seq_queue_tempo_copy(m_Info, other);
360 }
361
362 /**
363 * Copy constructor
364 * @param other An existing QueueTempo object reference
365 */
QueueTempo(const QueueTempo & other)366 QueueTempo::QueueTempo(const QueueTempo& other)
367 {
368 snd_seq_queue_tempo_malloc(&m_Info);
369 snd_seq_queue_tempo_copy(m_Info, other.m_Info);
370 }
371
372 /**
373 * Destructor
374 */
~QueueTempo()375 QueueTempo::~QueueTempo()
376 {
377 snd_seq_queue_tempo_free(m_Info);
378 }
379
380 /**
381 * Copy the current object returning the copied object
382 * @return The pointer to the new object
383 */
clone()384 QueueTempo* QueueTempo::clone()
385 {
386 return new QueueTempo(m_Info);
387 }
388
389 /**
390 * Assignment operator
391 * @param other An existing QueueTempo object reference
392 * @return This object
393 */
operator =(const QueueTempo & other)394 QueueTempo& QueueTempo::operator=(const QueueTempo& other)
395 {
396 if (this == &other)
397 return *this;
398 snd_seq_queue_tempo_copy(m_Info, other.m_Info);
399 return *this;
400 }
401
402 /**
403 * Gets the queue's numeric identifier
404 * @return The queue's numeric identifier
405 */
getId()406 int QueueTempo::getId()
407 {
408 return snd_seq_queue_tempo_get_queue(m_Info);
409 }
410
411 /**
412 * Gets the PPQ (parts per quarter note) resolution of the queue
413 * @return The PPQ (parts per quarter note) resolution
414 */
getPPQ()415 int QueueTempo::getPPQ()
416 {
417 return snd_seq_queue_tempo_get_ppq(m_Info);
418 }
419
420 /**
421 * Gets the tempo skew numerator. The real skew factor is the quotient of this
422 * value divided by the skew base.
423 * @return The tempo skew numerator.
424 * @see getSkewBase(), setSkewValue(), setTempoFactor()
425 */
getSkewValue()426 unsigned int QueueTempo::getSkewValue()
427 {
428 return snd_seq_queue_tempo_get_skew(m_Info);
429 }
430
431 /**
432 * Gets the tempo skew base. The real skew factor is the quotient of the skew
433 * value divided by the skew base.
434 * @return The tempo skew base.
435 * @see getSkewValue(), setSkewValue(), setTempoFactor()
436 */
getSkewBase()437 unsigned int QueueTempo::getSkewBase()
438 {
439 return snd_seq_queue_tempo_get_skew_base(m_Info);
440 }
441
442 /**
443 * Gets the queue's tempo in microseconds per beat.
444 * @return The queue's tempo in microseconds per beat.
445 */
getTempo()446 unsigned int QueueTempo::getTempo()
447 {
448 return snd_seq_queue_tempo_get_tempo(m_Info);
449 }
450
451 /**
452 * Sets the queue resolution in parts per quarter note.
453 * @param value The queue resolution in PPQ.
454 */
setPPQ(int value)455 void QueueTempo::setPPQ(int value)
456 {
457 snd_seq_queue_tempo_set_ppq(m_Info, value);
458 }
459
460 /**
461 * Sets the tempo skew numerator. The real skew factor is the quotient of this
462 * value divided by the skew base.
463 * @param value The tempo skew numerator.
464 * @see getSkewBase(), getSkewValue(), setTempoFactor()
465 */
setSkewValue(unsigned int value)466 void QueueTempo::setSkewValue(unsigned int value)
467 {
468 snd_seq_queue_tempo_set_skew(m_Info, value);
469 }
470
471 /**
472 * Sets the tempo skew base. The real skew factor is the quotient of the skew
473 * value divided by the skew base.
474 * @bug Protected because ALSA only accepts as argument a constant SKEW_BASE
475 * @param value The tempo skew base.
476 * @see getSkewBase(), getSkewValue(), setTempoFactor()
477 */
setSkewBase(unsigned int value)478 void QueueTempo::setSkewBase(unsigned int value)
479 {
480 snd_seq_queue_tempo_set_skew_base(m_Info, value);
481 }
482
483 /**
484 * Sets the queue tempo in microseconds per beat
485 * @param value The tempo in microseconds per beat
486 */
setTempo(unsigned int value)487 void QueueTempo::setTempo(unsigned int value)
488 {
489 snd_seq_queue_tempo_set_tempo(m_Info, value);
490 }
491
492 /**
493 * Gets the queue's nominal BPM tempo (in beats per minute)
494 * @return The queue's nominal BPM tempo (in beats per minute)
495 */
getNominalBPM()496 float QueueTempo::getNominalBPM()
497 {
498 int itempo = getTempo();
499 if (itempo != 0)
500 return 6.0e7f / itempo;
501 return 0.0f;
502 }
503
504 /**
505 * Gets the queue's real BPM tempo in beats per minute. The result is equal to
506 * the nominal BPM tempo multiplied by the skew factor.
507 * @return
508 */
getRealBPM()509 float QueueTempo::getRealBPM()
510 {
511 float tempo = getNominalBPM();
512 return tempo * getSkewValue() / SKEW_BASE;
513 }
514
515 /**
516 * Sets the queue's tempo skew factor
517 * @param value The tempo skew factor.
518 */
setTempoFactor(float value)519 void QueueTempo::setTempoFactor(float value)
520 {
521 setSkewValue(floor(SKEW_BASE * value));
522 setSkewBase(SKEW_BASE);
523 }
524
525 /**
526 * Sets the queue's nominal tempo in BPM (beats per minute).
527 * @param value The nominal tempo in BPM (beats per minute).
528 */
setNominalBPM(float value)529 void QueueTempo::setNominalBPM(float value)
530 {
531 setTempo(floor(6.0e7f / value));
532 }
533
534 /**
535 * Gets the size of the ALSA queue tempo object
536 * @return The size of the ALSA object
537 */
getInfoSize() const538 int QueueTempo::getInfoSize() const
539 {
540 return snd_seq_queue_tempo_sizeof();
541 }
542
543 /**
544 * Default constructor
545 */
QueueTimer()546 QueueTimer::QueueTimer()
547 {
548 snd_seq_queue_timer_malloc(&m_Info);
549 }
550
551 /**
552 * Constructor
553 * @param other An ALSA queue timer object pointer
554 */
QueueTimer(snd_seq_queue_timer_t * other)555 QueueTimer::QueueTimer(snd_seq_queue_timer_t* other)
556 {
557 snd_seq_queue_timer_malloc(&m_Info);
558 snd_seq_queue_timer_copy(m_Info, other);
559 }
560
561 /**
562 * Copy constructor
563 * @param other An existing QueueTimer object reference
564 */
QueueTimer(const QueueTimer & other)565 QueueTimer::QueueTimer(const QueueTimer& other)
566 {
567 snd_seq_queue_timer_malloc(&m_Info);
568 snd_seq_queue_timer_copy(m_Info, other.m_Info);
569 }
570
571 /**
572 * Destructor
573 */
~QueueTimer()574 QueueTimer::~QueueTimer()
575 {
576 snd_seq_queue_timer_free(m_Info);
577 }
578
579 /**
580 * Copy the current object and return the copy
581 * @return The pointer to the new object
582 */
clone()583 QueueTimer* QueueTimer::clone()
584 {
585 return new QueueTimer(m_Info);
586 }
587
588 /**
589 * Assignment operator
590 * @param other An existing QueueTimer object reference
591 * @return This object
592 */
operator =(const QueueTimer & other)593 QueueTimer& QueueTimer::operator=(const QueueTimer& other)
594 {
595 if (this == &other)
596 return *this;
597 snd_seq_queue_timer_copy(m_Info, other.m_Info);
598 return *this;
599 }
600
601 /**
602 * The queue's numeric identifier
603 * @return The queue's numeric identifier
604 */
getQueueId()605 int QueueTimer::getQueueId()
606 {
607 return snd_seq_queue_timer_get_queue(m_Info);
608 }
609
610 /**
611 * Gets the timer type.
612 *
613 * The timer type can be one of the following constants:
614 * <ul>
615 * <li>SND_SEQ_TIMER_ALSA: ALSA timer</li>
616 * <li>SND_SEQ_TIMER_MIDI_CLOCK: MIDI Clock (CLOCK event)</li>
617 * <li>SND_SEQ_TIMER_MIDI_TICK: MIDI Timer Tick (TICK event)</li>
618 * </ul>
619 * @return the timer type.
620 * @see setType()
621 */
getType()622 snd_seq_queue_timer_type_t QueueTimer::getType()
623 {
624 return snd_seq_queue_timer_get_type(m_Info);
625 }
626
627 /**
628 * Gets the timer identifier record
629 * @return The timer identifier record pointer
630 */
getId()631 const snd_timer_id_t* QueueTimer::getId()
632 {
633 return snd_seq_queue_timer_get_id(m_Info);
634 }
635
636 /**
637 * Gets the timer resolution
638 * @return The timer resolution
639 */
getResolution()640 unsigned int QueueTimer::getResolution()
641 {
642 return snd_seq_queue_timer_get_resolution(m_Info);
643 }
644
645 /**
646 * Sets the timer type.
647 * The timer type can be one of the following constants:
648 * <ul>
649 * <li>SND_SEQ_TIMER_ALSA: ALSA timer</li>
650 * <li>SND_SEQ_TIMER_MIDI_CLOCK: MIDI Clock (CLOCK event)</li>
651 * <li>SND_SEQ_TIMER_MIDI_TICK: MIDI Timer Tick (TICK event)</li>
652 * </ul>
653 * @param value The timer type
654 * @see getType()
655 */
setType(snd_seq_queue_timer_type_t value)656 void QueueTimer::setType(snd_seq_queue_timer_type_t value)
657 {
658 snd_seq_queue_timer_set_type(m_Info, value);
659 }
660
661 /**
662 * Sets the timer identifier record
663 * @param value The timer identifier record pointer
664 */
setId(snd_timer_id_t * value)665 void QueueTimer::setId(snd_timer_id_t* value)
666 {
667 snd_seq_queue_timer_set_id(m_Info, value);
668 }
669
670 /**
671 * Sets the timer identifier
672 * @param id Timer identifier object
673 * @since 0.3.0
674 */
setId(const TimerId & id)675 void QueueTimer::setId(const TimerId& id)
676 {
677 setId(id.m_Info);
678 }
679
680 /**
681 * Sets the timer resolution
682 * @param value The timer resolution
683 */
setResolution(unsigned int value)684 void QueueTimer::setResolution(unsigned int value)
685 {
686 snd_seq_queue_timer_set_resolution(m_Info, value);
687 }
688
689 /**
690 * Gets the size of the ALSA queue timer object
691 * @return The size of the ALSA object
692 */
getInfoSize() const693 int QueueTimer::getInfoSize() const
694 {
695 return snd_seq_queue_timer_sizeof();
696 }
697
698 /**
699 * Constructor
700 * @param seq An existing MidiClient instance
701 * @param parent An optional parent object
702 */
MidiQueue(MidiClient * seq,QObject * parent)703 MidiQueue::MidiQueue(MidiClient* seq, QObject* parent)
704 : QObject(parent)
705 {
706 m_MidiClient = seq;
707 m_Id = DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_alloc_queue(m_MidiClient->getHandle()));
708 m_allocated = !(m_Id < 0);
709 }
710
711 /**
712 * Constructor
713 * @param seq An existing MidiClient instance
714 * @param info A QueueInfo object reference
715 * @param parent An optional parent object
716 */
MidiQueue(MidiClient * seq,const QueueInfo & info,QObject * parent)717 MidiQueue::MidiQueue(MidiClient* seq, const QueueInfo& info, QObject* parent)
718 : QObject(parent)
719 {
720 m_MidiClient = seq;
721 m_Info = info;
722 m_Id = DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_create_queue(m_MidiClient->getHandle(), m_Info.m_Info));
723 m_allocated = !(m_Id < 0);
724 }
725
726 /**
727 * Constructor
728 * @param seq An existing MidiClient instance
729 * @param name The name for the new queue
730 * @param parent An optional parent object
731 */
MidiQueue(MidiClient * seq,const QString name,QObject * parent)732 MidiQueue::MidiQueue(MidiClient* seq, const QString name, QObject* parent)
733 : QObject(parent)
734 {
735 m_MidiClient = seq;
736 m_Id = DRUMSTICK_ALSA_CHECK_ERROR(snd_seq_alloc_named_queue(m_MidiClient->getHandle(), name.toLocal8Bit().data()));
737 m_allocated = !(m_Id < 0);
738 }
739
740 /**
741 * Constructor.
742 *
743 * Note: this constructor doesn't allocate a new queue, it uses an existing one.
744 * @param seq An existing MidiClient instance
745 * @param queue_id An existing queue numeric identifier
746 * @param parent An optional parent object
747 */
MidiQueue(MidiClient * seq,const int queue_id,QObject * parent)748 MidiQueue::MidiQueue(MidiClient* seq, const int queue_id, QObject* parent)
749 : QObject(parent)
750 {
751 m_MidiClient = seq;
752 m_Id = queue_id;
753 m_allocated = false;
754 }
755
756 /**
757 * Destructor
758 */
~MidiQueue()759 MidiQueue::~MidiQueue()
760 {
761 if ( m_allocated && (m_MidiClient->getHandle() != nullptr) )
762 {
763 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_free_queue(m_MidiClient->getHandle(), m_Id));
764 }
765 }
766
767 /**
768 * Gets a QueueInfo object reference
769 * @return A QueueInfo object reference
770 */
getInfo()771 QueueInfo& MidiQueue::getInfo()
772 {
773 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_get_queue_info(m_MidiClient->getHandle(), m_Id, m_Info.m_Info));
774 return m_Info;
775 }
776
777 /**
778 * Gets a QueueStatus object reference
779 * @return A QueueStatus object reference
780 */
getStatus()781 QueueStatus& MidiQueue::getStatus()
782 {
783 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_get_queue_status(m_MidiClient->getHandle(), m_Id, m_Status.m_Info));
784 return m_Status;
785 }
786
787 /**
788 * Gets a QueueTempo object reference
789 * @return A QueueTempo object reference
790 */
getTempo()791 QueueTempo& MidiQueue::getTempo()
792 {
793 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_get_queue_tempo(m_MidiClient->getHandle(), m_Id, m_Tempo.m_Info));
794 return m_Tempo;
795 }
796
797 /**
798 * Gets a QueueTimer object reference
799 * @return A QueueTimer object reference
800 */
getTimer()801 QueueTimer& MidiQueue::getTimer()
802 {
803 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_get_queue_timer(m_MidiClient->getHandle(), m_Id, m_Timer.m_Info));
804 return m_Timer;
805 }
806
807 /**
808 * Applies a QueueInfo object to the queue
809 * @param value A QueueInfo object reference
810 */
setInfo(const QueueInfo & value)811 void MidiQueue::setInfo(const QueueInfo& value)
812 {
813 m_Info = value;
814 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_queue_info(m_MidiClient->getHandle(), m_Id, m_Info.m_Info));
815 }
816
817 /**
818 * Applies a QueueTempo object to the queue
819 * @param value A QueueTempo object reference
820 */
setTempo(const QueueTempo & value)821 void MidiQueue::setTempo(const QueueTempo& value)
822 {
823 m_Tempo = value;
824 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_queue_tempo(m_MidiClient->getHandle(), m_Id, m_Tempo.m_Info));
825 }
826
827 /**
828 * Applies q QueueTimer object to the queue
829 * @param value A QueueTimer object reference
830 */
setTimer(const QueueTimer & value)831 void MidiQueue::setTimer(const QueueTimer& value)
832 {
833 m_Timer = value;
834 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_queue_timer(m_MidiClient->getHandle(), m_Id, m_Timer.m_Info));
835 }
836
837 /**
838 * Gets the queue usage flag.
839 *
840 * @return 1 = client is allowed to access the queue, 0 = not allowed.
841 */
getUsage()842 int MidiQueue::getUsage()
843 {
844 return DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_get_queue_usage(m_MidiClient->getHandle(), m_Id));
845 }
846
847 /**
848 * Sets the queue usage flag.
849 *
850 * @param used 1 = client is allowed to access the queue, 0 = not allowed.
851 */
setUsage(int used)852 void MidiQueue::setUsage(int used)
853 {
854 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_set_queue_usage(m_MidiClient->getHandle(), m_Id, used));
855 }
856
857 /**
858 * Start the queue.
859 *
860 * This method should start running the queue from the initial position.
861 */
start()862 void MidiQueue::start()
863 {
864 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_start_queue(m_MidiClient->getHandle(), m_Id, nullptr));
865 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle()));
866 }
867
868 /**
869 * Stop the queue.
870 *
871 * This method should stop running the queue.
872 */
stop()873 void MidiQueue::stop()
874 {
875 if (m_MidiClient != nullptr && m_MidiClient->getHandle() != nullptr) {
876 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_stop_queue(m_MidiClient->getHandle(), m_Id, nullptr));
877 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle()));
878 }
879 }
880
881 /**
882 * Start the queue without resetting the last position.
883 *
884 * This method should start running the queue from the last position set.
885 */
continueRunning()886 void MidiQueue::continueRunning()
887 {
888 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_continue_queue(m_MidiClient->getHandle(), m_Id, nullptr));
889 DRUMSTICK_ALSA_CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle()));
890 }
891
892 /**
893 * Clear the queue, dropping any scheduled events.
894 */
clear()895 void MidiQueue::clear()
896 {
897 if (m_MidiClient != nullptr && m_MidiClient->getHandle() != nullptr)
898 snd_seq_drop_output(m_MidiClient->getHandle());
899 }
900
901 /**
902 * Sets the queue position in musical time (ticks).
903 * @param pos Musical time in ticks.
904 */
setTickPosition(snd_seq_tick_time_t pos)905 void MidiQueue::setTickPosition(snd_seq_tick_time_t pos)
906 {
907 SystemEvent event(SND_SEQ_EVENT_SETPOS_TICK);
908 snd_seq_ev_set_queue_pos_tick(event.getHandle(), m_Id, pos);
909 event.setDirect();
910 m_MidiClient->outputDirect(&event);
911 }
912
913 /**
914 * Sets the queue position in real time (clock) units: seconds and nanoseconds.
915 * @param pos Real time (clock) position in seconds/nanoseconds.
916 */
setRealTimePosition(snd_seq_real_time_t * pos)917 void MidiQueue::setRealTimePosition(snd_seq_real_time_t* pos)
918 {
919 SystemEvent event(SND_SEQ_EVENT_SETPOS_TIME);
920 snd_seq_ev_set_queue_pos_real(event.getHandle(), m_Id, pos);
921 event.setDirect();
922 m_MidiClient->outputDirect(&event);
923 }
924
925 } // namespace ALSA
926 } // namespace drumstick
927
928