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 <drumstick/alsaevent.h>
21 /**
22  * @file alsaevent.cpp
23  * Implementation of classes managing ALSA Sequencer events.
24  */
25 
26 /**
27  * @class QEvent
28  * The QEvent class is the base class of all event classes.
29  * @see https://doc.qt.io/qt-5/qevent.html
30  */
31 
32 namespace drumstick { namespace ALSA {
33 
34 /**
35  * @addtogroup ALSAEvent
36  * @{
37  *
38  * MIDI Events are messages transmitted between MIDI devices or applications.
39  *
40  * Classes:
41  *
42  * SequencerEvent: Base class for the event's hierarchy.
43  *
44  * ChannelEvent: Base class for the events having a Channel property.
45  *
46  * KeyEvent: Base class for the events having Key and Velocity properties.
47  *
48  * NoteEvent: Class representing a note event with duration.
49  *
50  * NoteOnEvent: Event representing a note-on MIDI event.
51  *
52  * NoteOffEvent: Event representing a note-off MIDI event.
53  *
54  * KeyPressEvent: Event representing a MIDI key pressure, or polyphonic after-touch event.
55  *
56  * ControllerEvent: Event representing a MIDI control change event.
57  *
58  * ProgramChangeEvent: Event representing a MIDI program change event.
59  *
60  * PitchBendEvent: Event representing a MIDI bender, or pitch wheel event.
61  *
62  * ChanPressEvent: Event representing a MIDI channel pressure or after-touch event.
63  *
64  * VariableEvent: Base class for variable length events.
65  *
66  * SysExEvent: Event representing a MIDI system exclusive event.
67  *
68  * TextEvent: Event representing a SMF text event.
69  *
70  * SystemEvent: Generic event.
71  *
72  * QueueControlEvent: ALSA Event representing a queue control command.
73  *
74  * ValueEvent: Generic event having a value property.
75  *
76  * TempoEvent: ALSA Event representing a tempo change for an ALSA queue.
77  *
78  * SubscriptionEvent: ALSA Event representing a subscription between two ALSA clients and ports.
79  *
80  * ClientEvent: ALSA Event representing a change on some ALSA sequencer client.
81  *
82  * PortEvent: ALSA Event representing a change on some ALSA sequencer port.
83  *
84  * RemoveEvents: Auxiliary class to remove events from an ALSA queue.
85  *
86  * MidiCodec: Auxiliary class to translate between raw MIDI streams and ALSA events.
87  *
88  * @see https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html
89  * @see https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_events.html
90  * @see https://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_ev_type.html
91  * @see https://www.alsa-project.org/alsa-doc/alsa-lib/group___m_i_d_i___event.html
92  * @}
93  */
94 
95 
96 /**
97  * Default constructor.
98  */
SequencerEvent()99 SequencerEvent::SequencerEvent() : QEvent(SequencerEventType)
100 {
101     snd_seq_ev_clear( &m_event );
102 }
103 
104 /**
105  * Constructor from an ALSA event record
106  * @param event ALSA event record
107  */
SequencerEvent(const snd_seq_event_t * event)108 SequencerEvent::SequencerEvent(const snd_seq_event_t* event) : QEvent(SequencerEventType)
109 {
110     snd_seq_ev_clear( &m_event );
111     m_event = *event;
112 }
113 
114 /**
115  * Copy constructor
116  * @param other A SequencerEvent object reference
117  */
SequencerEvent(const SequencerEvent & other)118 SequencerEvent::SequencerEvent(const SequencerEvent& other) : QEvent(SequencerEventType)
119 {
120     snd_seq_ev_clear( &m_event );
121     m_event = other.m_event;
122 }
123 
124 /**
125  * Assignment operator
126  * @param other A SequencerEvent object reference
127  * @return This object
128  */
129 SequencerEvent&
operator =(const SequencerEvent & other)130 SequencerEvent::operator=(const SequencerEvent& other)
131 {
132     m_event = other.m_event;
133     return *this;
134 }
135 
136 /**
137  * Checks if the event's type is a subscription.
138  * @param event A SequencerEvent object pointer
139  * @return True if the event has a subscribe/unsubscribe type.
140  */
141 bool
isSubscription(const SequencerEvent * event)142 SequencerEvent::isSubscription(const SequencerEvent* event)
143 {
144     snd_seq_event_type_t te = event->getSequencerType();
145     return ( te == SND_SEQ_EVENT_PORT_SUBSCRIBED ||
146              te == SND_SEQ_EVENT_PORT_UNSUBSCRIBED );
147 }
148 
149 /**
150  * Checks if the event's type is of type port.
151  * @param event A SequencerEvent object pointer
152  * @return True if the event has a port start/exit/change type.
153  */
154 bool
isPort(const SequencerEvent * event)155 SequencerEvent::isPort(const SequencerEvent* event)
156 {
157     snd_seq_event_type_t te = event->getSequencerType();
158     return ( te == SND_SEQ_EVENT_PORT_START ||
159              te == SND_SEQ_EVENT_PORT_EXIT ||
160              te == SND_SEQ_EVENT_PORT_CHANGE );
161 }
162 
163 /**
164  * Checks if the event's type is of type client.
165  * @param event A SequencerEvent object pointer
166  * @return True if the event has a client start/exit/change type.
167  */
168 bool
isClient(const SequencerEvent * event)169 SequencerEvent::isClient(const SequencerEvent* event)
170 {
171     snd_seq_event_type_t te = event->getSequencerType();
172     return ( te == SND_SEQ_EVENT_CLIENT_START ||
173              te == SND_SEQ_EVENT_CLIENT_EXIT ||
174              te == SND_SEQ_EVENT_CLIENT_CHANGE );
175 }
176 
177 /**
178  * Checks if the event's type is of type connection change.
179  * @param event A SequencerEvent object pointer
180  * @return True if the event has a client/port/subscription type.
181  */
182 bool
isConnectionChange(const SequencerEvent * event)183 SequencerEvent::isConnectionChange(const SequencerEvent* event)
184 {
185     snd_seq_event_type_t te = event->getSequencerType();
186     return ( te == SND_SEQ_EVENT_PORT_START ||
187              te == SND_SEQ_EVENT_PORT_EXIT ||
188              te == SND_SEQ_EVENT_PORT_CHANGE ||
189              te == SND_SEQ_EVENT_CLIENT_START ||
190              te == SND_SEQ_EVENT_CLIENT_EXIT ||
191              te == SND_SEQ_EVENT_CLIENT_CHANGE ||
192              te == SND_SEQ_EVENT_PORT_SUBSCRIBED ||
193              te == SND_SEQ_EVENT_PORT_UNSUBSCRIBED );
194 }
195 
196 /**
197  * Checks if the event's type is a Channel Voice message.
198  * @param event A SequencerEvent object pointer
199  * @return True if the event is a channel voice message.
200  * @since 0.2.0
201  */
202 bool
isChannel(const SequencerEvent * event)203 SequencerEvent::isChannel(const SequencerEvent* event)
204 {
205     snd_seq_event_type_t te = event->getSequencerType();
206     return ( te == SND_SEQ_EVENT_NOTEOFF ||
207              te == SND_SEQ_EVENT_NOTEON ||
208              te == SND_SEQ_EVENT_NOTE ||
209              te == SND_SEQ_EVENT_KEYPRESS ||
210              te == SND_SEQ_EVENT_CONTROLLER ||
211              te == SND_SEQ_EVENT_CONTROL14 ||
212              te == SND_SEQ_EVENT_PGMCHANGE ||
213              te == SND_SEQ_EVENT_CHANPRESS ||
214              te == SND_SEQ_EVENT_PITCHBEND );
215 }
216 
217 /**
218  * Sets the event's ALSA sequencer type
219  * @param eventType The ALSA sequencer type
220  */
setSequencerType(const snd_seq_event_type_t eventType)221 void SequencerEvent::setSequencerType(const snd_seq_event_type_t eventType)
222 {
223     m_event.type = eventType;
224 }
225 
226 /**
227  * Sets the client:port destination of the event.
228  * @param client The destination's client ID
229  * @param port The destination port ID
230  * @see setSubscribers()
231  */
setDestination(const unsigned char client,const unsigned char port)232 void SequencerEvent::setDestination(const unsigned char client, const unsigned char port)
233 {
234     snd_seq_ev_set_dest(&m_event, client, port);
235 }
236 
237 /**
238  * Sets the event's source port ID
239  * @param port The source port ID
240  * @see getSourceClient(), getSourcePort()
241  */
setSource(const unsigned char port)242 void SequencerEvent::setSource(const unsigned char port)
243 {
244     snd_seq_ev_set_source(&m_event, port);
245 }
246 
247 /**
248  * Sets the event's destination to be all the subscribers of the source port.
249  */
setSubscribers()250 void SequencerEvent::setSubscribers()
251 {
252     snd_seq_ev_set_subs(&m_event);
253 }
254 
255 /**
256  * Sets the event's destination to be all queues/clients/ports/channels.
257  */
setBroadcast()258 void SequencerEvent::setBroadcast()
259 {
260     snd_seq_ev_set_broadcast(&m_event);
261 }
262 
263 /**
264  * Sets the event to be immediately delivered, not queued/scheduled.
265  * @see scheduleTick(), scheduleReal()
266  */
setDirect()267 void SequencerEvent::setDirect()
268 {
269     snd_seq_ev_set_direct(&m_event);
270 }
271 
272 /**
273  * Sets the event to be scheduled in musical time (ticks) units.
274  * @param queue The queue number to be used.
275  * @param tick The time in ticks.
276  * @param relative Use relative (to the current) time instead of absolute time.
277  */
scheduleTick(int queue,int tick,bool relative)278 void SequencerEvent::scheduleTick(int queue, int tick, bool relative)
279 {
280     snd_seq_ev_schedule_tick(&m_event, queue, relative, tick);
281 }
282 
283 /**
284  * Sets the event to be scheduled in real (clock) time units.
285  * @param queue The queue number to be used.
286  * @param secs The time in whole seconds.
287  * @param nanos The nanoseconds to be added.
288  * @param relative Use relative (to the current) time instead of absolute time.
289  */
scheduleReal(int queue,ulong secs,ulong nanos,bool relative)290 void SequencerEvent::scheduleReal(int queue, ulong secs, ulong nanos, bool relative)
291 {
292     snd_seq_real_time_t rtime;
293     rtime.tv_sec = secs;
294     rtime.tv_nsec = nanos;
295     snd_seq_ev_schedule_real(&m_event, queue, relative, &rtime);
296 }
297 
298 /**
299  * Sets the priority of the event. This is used in case of several events share
300  * the same scheduling time.
301  *
302  * @param high Mark the event as a high priority one.
303  */
setPriority(const bool high)304 void SequencerEvent::setPriority(const bool high)
305 {
306     snd_seq_ev_set_priority(&m_event, high);
307 }
308 
309 /**
310  * Sets the event's tag. This attribute is any arbitrary number, not used by
311  * the ALSA library. Range limited to 0 thru 255.
312  * @param aTag A tag number.
313  */
setTag(const unsigned char aTag)314 void SequencerEvent::setTag(const unsigned char aTag)
315 {
316 #if SND_LIB_VERSION > 0x010008
317     snd_seq_ev_set_tag(&m_event, aTag);
318 #else
319     m_event.tag = aTag;
320 #endif
321 }
322 
323 /**
324  * Gets an event's raw 32 bits parameter.
325  * @param n The parameter index, between 0 and 2.
326  * @return The parameter's value.
327  * @see setRaw32()
328  */
getRaw32(const unsigned int n) const329 unsigned int SequencerEvent::getRaw32(const unsigned int n) const
330 {
331     if (n < 3) return m_event.data.raw32.d[n];
332     return 0;
333 }
334 
335 /**
336  * Sets an event's raw 32 bits parameter.
337  * @param n The parameter index, between 0 and 2.
338  * @param value The parameter's value.
339  */
setRaw32(const unsigned int n,const unsigned int value)340 void SequencerEvent::setRaw32(const unsigned int n, const unsigned int value)
341 {
342     if (n < 3) m_event.data.raw32.d[n] = value;
343 }
344 
345 /**
346  * Gets an event's raw 8 bits parameter.
347  * @param n The parameter index, between 0 and 11.
348  * @return The parameter's value.
349  * @see setRaw8()
350  */
getRaw8(const unsigned int n) const351 unsigned char SequencerEvent::getRaw8(const unsigned int n) const
352 {
353     if (n < 12) return m_event.data.raw8.d[n];
354     return 0;
355 }
356 
357 /**
358  * Sets an event's raw 8 bits parameter.
359  * @param n The parameter index, between 0 and 11.
360  * @param value The parameter's value.
361  */
setRaw8(const unsigned int n,const unsigned char value)362 void SequencerEvent::setRaw8(const unsigned int n, const unsigned char value)
363 {
364     if (n < 12) m_event.data.raw8.d[n] = value;
365 }
366 
367 /**
368  * Releases the event record.
369  * @deprecated the event record is not allocated, so you don't have to call this function
370  */
free()371 void SequencerEvent::free()
372 {
373     snd_seq_free_event(&m_event);
374 }
375 
376 /**
377  * Gets the encoded length of the event record.
378  * @return The encoded length.
379  */
getEncodedLength()380 int SequencerEvent::getEncodedLength()
381 {
382     return snd_seq_event_length(&m_event);
383 }
384 
385 /**
386  * Clone this object returning a pointer to the new object
387  * @return pointer to the new object
388  */
clone() const389 SequencerEvent* SequencerEvent::clone() const
390 {
391     return new SequencerEvent(&m_event);
392 }
393 
394 /**
395  * Clone this object returning a pointer to the new object
396  * @return pointer to the new object
397  */
clone() const398 ChannelEvent* ChannelEvent::clone() const
399 {
400     return new ChannelEvent(&m_event);
401 }
402 
403 /**
404  * Clone this object returning a pointer to the new object
405  * @return pointer to the new object
406  */
clone() const407 KeyEvent* KeyEvent::clone() const
408 {
409     return new KeyEvent(&m_event);
410 }
411 
412 /**
413  * Constructor using proper attribute values.
414  * @param ch MIDI Channel.
415  * @param key MIDI note.
416  * @param vel Note velocity.
417  * @param dur Note duration.
418  */
NoteEvent(int ch,int key,int vel,int dur)419 NoteEvent::NoteEvent(int ch, int key, int vel, int dur) : KeyEvent()
420 {
421     snd_seq_ev_set_note(&m_event, ch, key, vel, dur);
422 }
423 
424 /**
425  * Clone this object returning a pointer to the new object
426  * @return pointer to the new object
427  */
clone() const428 NoteEvent* NoteEvent::clone() const
429 {
430     return new NoteEvent(&m_event);
431 }
432 
433 /**
434  * Constructor using proper attribute values.
435  * @param ch MIDI Channel.
436  * @param key MIDI note.
437  * @param vel Note velocity.
438  */
NoteOnEvent(int ch,int key,int vel)439 NoteOnEvent::NoteOnEvent(int ch, int key, int vel) : KeyEvent()
440 {
441     snd_seq_ev_set_noteon(&m_event, ch, key, vel);
442 }
443 
444 /**
445  * Clone this object returning a pointer to the new object
446  * @return pointer to the new object
447  */
clone() const448 NoteOnEvent* NoteOnEvent::clone() const
449 {
450     return new NoteOnEvent(&m_event);
451 }
452 
453 /**
454  * Constructor using proper attribute values.
455  * @param ch MIDI Channel.
456  * @param key MIDI note.
457  * @param vel Note velocity.
458  */
NoteOffEvent(int ch,int key,int vel)459 NoteOffEvent::NoteOffEvent(int ch, int key, int vel) : KeyEvent()
460 {
461     snd_seq_ev_set_noteoff(&m_event, ch, key, vel);
462 }
463 
464 /**
465  * Clone this object returning a pointer to the new object
466  * @return pointer to the new object
467  */
clone() const468 NoteOffEvent* NoteOffEvent::clone() const
469 {
470     return new NoteOffEvent(&m_event);
471 }
472 
473 /**
474  * Constructor using proper attribute values.
475  * @param ch MIDI Channel.
476  * @param key MIDI note.
477  * @param vel Note velocity.
478  */
KeyPressEvent(int ch,int key,int vel)479 KeyPressEvent::KeyPressEvent(int ch, int key, int vel) : KeyEvent()
480 {
481     snd_seq_ev_set_keypress(&m_event, ch, key, vel);
482 }
483 
484 /**
485  * Clone this object returning a pointer to the new object
486  * @return pointer to the new object
487  */
clone() const488 KeyPressEvent* KeyPressEvent::clone() const
489 {
490     return new KeyPressEvent(&m_event);
491 }
492 
493 /**
494  * Constructor using proper attribute values.
495  * @param ch MIDI Channel.
496  * @param cc MIDI Controller number.
497  * @param val Controller value.
498  */
ControllerEvent(int ch,int cc,int val)499 ControllerEvent::ControllerEvent(int ch, int cc, int val) : ChannelEvent()
500 {
501     snd_seq_ev_set_controller(&m_event, ch, cc, val);
502 }
503 
504 /**
505  * Clone this object returning a pointer to the new object
506  * @return pointer to the new object
507  */
clone() const508 ControllerEvent* ControllerEvent::clone() const
509 {
510     return new ControllerEvent(&m_event);
511 }
512 
513 /**
514  * Constructor using proper attribute values.
515  * @param ch MIDI Channel.
516  * @param val MIDI Program number.
517  */
ProgramChangeEvent(int ch,int val)518 ProgramChangeEvent::ProgramChangeEvent(int ch, int val) : ChannelEvent()
519 {
520     snd_seq_ev_set_pgmchange(&m_event, ch, val);
521 }
522 
523 /**
524  * Clone this object returning a pointer to the new object
525  * @return pointer to the new object
526  */
clone() const527 ProgramChangeEvent* ProgramChangeEvent::clone() const
528 {
529     return new ProgramChangeEvent(&m_event);
530 }
531 
532 /**
533  * Constructor using proper attribute values.
534  * @param ch MIDI Channel.
535  * @param val Pitch Bend value. Zero centered from -8192 to 8191.
536  */
PitchBendEvent(int ch,int val)537 PitchBendEvent::PitchBendEvent(int ch, int val) : ChannelEvent()
538 {
539     snd_seq_ev_set_pitchbend(&m_event, ch, val);
540 }
541 
542 /**
543  * Clone this object returning a pointer to the new object
544  * @return pointer to the new object
545  */
clone() const546 PitchBendEvent* PitchBendEvent::clone() const
547 {
548     return new PitchBendEvent(&m_event);
549 }
550 
551 /**
552  * Constructor using proper attribute values.
553  * @param ch MIDI Channel.
554  * @param val Aftertouch value.
555  */
ChanPressEvent(int ch,int val)556 ChanPressEvent::ChanPressEvent(int ch, int val) : ChannelEvent()
557 {
558     snd_seq_ev_set_chanpress(&m_event, ch, val);
559 }
560 
561 /**
562  * Clone this object returning a pointer to the new object
563  * @return pointer to the new object
564  */
clone() const565 ChanPressEvent* ChanPressEvent::clone() const
566 {
567     return new ChanPressEvent(&m_event);
568 }
569 
570 /**
571  * Default constructor.
572  */
VariableEvent()573 VariableEvent::VariableEvent()
574     : SequencerEvent()
575 {
576     m_data.clear();
577     snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() );
578 }
579 
580 /**
581  * Constructor from an ALSA event record.
582  * @param event ALSA event record.
583  */
VariableEvent(const snd_seq_event_t * event)584 VariableEvent::VariableEvent(const snd_seq_event_t* event)
585     : SequencerEvent(event)
586 {
587     m_data = QByteArray((char *) event->data.ext.ptr,
588                         event->data.ext.len);
589     snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() );
590 }
591 
592 /**
593  * Constructor from an arbitrary data array.
594  * @param data A data byte array.
595  */
VariableEvent(const QByteArray & data)596 VariableEvent::VariableEvent(const QByteArray& data)
597     : SequencerEvent()
598 {
599     m_data = data;
600     snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() );
601 }
602 
603 /**
604  * Copy constructor.
605  * @param other Another VariableEvent instance.
606 s */
VariableEvent(const VariableEvent & other)607 VariableEvent::VariableEvent(const VariableEvent& other)
608     : SequencerEvent(other)
609 {
610     m_data = other.m_data;
611     snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() );
612 }
613 
614 /**
615  * Constructor from a data pointer.
616  * @param datalen Length of the data.
617  * @param dataptr Pointer the data.
618  */
VariableEvent(const unsigned int datalen,char * dataptr)619 VariableEvent::VariableEvent(const unsigned int datalen, char* dataptr)
620     : SequencerEvent()
621 {
622     m_data = QByteArray(dataptr, datalen);
623     snd_seq_ev_set_variable( &m_event, m_data.size(), m_data.data() );
624 }
625 
626 /**
627  * Assignment operator.
628  * @param other Another VariableEvent object reference
629  * @return Pointer to this object
630  */
operator =(const VariableEvent & other)631 VariableEvent& VariableEvent::operator=(const VariableEvent& other)
632 {
633     m_event = other.m_event;
634     m_data = other.m_data;
635     snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() );
636     return *this;
637 }
638 
639 /**
640  * Clone this object returning a pointer to the new object
641  * @return pointer to the new object
642  */
clone() const643 VariableEvent* VariableEvent::clone() const
644 {
645     return new VariableEvent(&m_event);
646 }
647 
648 /**
649  * Default constructor.
650  */
SysExEvent()651 SysExEvent::SysExEvent()
652     : VariableEvent()
653 {
654     snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() );
655 }
656 
657 /**
658  * Constructor from an ALSA event record.
659  * @param event ALSA event record.
660  */
SysExEvent(const snd_seq_event_t * event)661 SysExEvent::SysExEvent(const snd_seq_event_t* event)
662     : VariableEvent(event)
663 {
664     snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() );
665 }
666 
667 /**
668  * Constructor from a data array.
669  * @param data A data byte array.
670  */
SysExEvent(const QByteArray & data)671 SysExEvent::SysExEvent(const QByteArray& data)
672     : VariableEvent(data)
673 {
674     snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() );
675 }
676 
677 /**
678  * Copy constructor.
679  * @param other Another SysExEvent object reference.
680  */
SysExEvent(const SysExEvent & other)681 SysExEvent::SysExEvent(const SysExEvent& other)
682     : VariableEvent(other)
683 {
684     snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() );
685 }
686 
687 /**
688  * Constructor taking a data pointer and length
689  * @param datalen Data length
690  * @param dataptr Data pointer
691  */
SysExEvent(const unsigned int datalen,char * dataptr)692 SysExEvent::SysExEvent(const unsigned int datalen, char* dataptr)
693     : VariableEvent( datalen, dataptr )
694 {
695     snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() );
696 }
697 
698 /**
699  * Clone this object returning a pointer to the new object
700  * @return pointer to the new object
701  */
clone() const702 SysExEvent* SysExEvent::clone() const
703 {
704     return new SysExEvent(&m_event);
705 }
706 
707 /**
708  * Default constructor
709  */
TextEvent()710 TextEvent::TextEvent()
711     : VariableEvent(), m_textType(1)
712 {
713     setSequencerType(SND_SEQ_EVENT_USR_VAR0);
714 }
715 
716 /**
717  * Constructor from an ALSA sequencer record.
718  * @param event ALSA sequencer record.
719  */
TextEvent(const snd_seq_event_t * event)720 TextEvent::TextEvent(const snd_seq_event_t* event)
721     : VariableEvent(event), m_textType(1)
722 {
723     setSequencerType(SND_SEQ_EVENT_USR_VAR0);
724 }
725 
726 /**
727  * Constructor from a given string
728  * @param text The event's text
729  * @param textType The SMF text type
730  */
TextEvent(const QString & text,const int textType)731 TextEvent::TextEvent(const QString& text, const int textType)
732     : VariableEvent(text.toUtf8()), m_textType(textType)
733 {
734     setSequencerType(SND_SEQ_EVENT_USR_VAR0);
735 }
736 
737 /**
738  * Copy constructor
739  * @param other An existing TextEvent object reference
740  */
TextEvent(const TextEvent & other)741 TextEvent::TextEvent(const TextEvent& other)
742     : VariableEvent(other)
743 {
744     setSequencerType(SND_SEQ_EVENT_USR_VAR0);
745     m_textType = other.getTextType();
746 }
747 
748 /**
749  * Constructor from a data pointer and length
750  * @param datalen Data length
751  * @param dataptr Data pointer
752  */
TextEvent(const unsigned int datalen,char * dataptr)753 TextEvent::TextEvent(const unsigned int datalen, char* dataptr)
754     : VariableEvent(datalen, dataptr), m_textType(1)
755 {
756     setSequencerType(SND_SEQ_EVENT_USR_VAR0);
757 }
758 
759 /**
760  * Gets the event's text content.
761  * @return The text content.
762  */
getText() const763 QString TextEvent::getText() const
764 {
765     return QString::fromUtf8(m_data.data(), m_data.size());
766 }
767 
768 /**
769  * Gets the event's SMF text type.
770  * @return The SMF text type.
771  */
getTextType() const772 int TextEvent::getTextType() const
773 {
774     return m_textType;
775 }
776 
777 /**
778  * Clone this object returning a pointer to the new object
779  * @return pointer to the new object
780  */
clone() const781 TextEvent* TextEvent::clone() const
782 {
783     return new TextEvent(&m_event);
784 }
785 
786 /**
787  * Constructor
788  * @param type The event's type
789  */
SystemEvent(const snd_seq_event_type_t type)790 SystemEvent::SystemEvent(const snd_seq_event_type_t type) : SequencerEvent()
791 {
792     snd_seq_ev_set_fixed(&m_event);
793     setSequencerType(type);
794 }
795 
796 /**
797  * Clone this object returning a pointer to the new object
798  * @return pointer to the new object
799  */
clone() const800 SystemEvent* SystemEvent::clone() const
801 {
802     return new SystemEvent(&m_event);
803 }
804 
805 /**
806  * Constructor
807  * @param type Event type
808  * @param queue Queue number
809  * @param value Value
810  */
QueueControlEvent(snd_seq_event_type_t type,int queue,int value)811 QueueControlEvent::QueueControlEvent(snd_seq_event_type_t type, int queue, int value)
812     : SequencerEvent()
813 {
814     snd_seq_ev_set_queue_control(&m_event, type, queue, value);
815 }
816 
817 /**
818  * Clone this object returning a pointer to the new object
819  * @return pointer to the new object
820  */
clone() const821 QueueControlEvent* QueueControlEvent::clone() const
822 {
823     return new QueueControlEvent(&m_event);
824 }
825 
826 /**
827  * Constructor
828  * @param type The event's type
829  * @param val Value
830  */
ValueEvent(const snd_seq_event_type_t type,int val)831 ValueEvent::ValueEvent(const snd_seq_event_type_t type, int val) : SequencerEvent()
832 {
833     snd_seq_ev_set_fixed(&m_event);
834     setSequencerType(type);
835     setValue(val);
836 }
837 
838 /**
839  * Clone this object returning a pointer to the new object
840  * @return pointer to the new object
841  */
clone() const842 ValueEvent* ValueEvent::clone() const
843 {
844     return new ValueEvent(&m_event);
845 }
846 
847 /**
848  * Constructor
849  * @param queue Queue number.
850  * @param tempo Tempo value in microseconds per quarter note.
851  */
TempoEvent(int queue,int tempo)852 TempoEvent::TempoEvent(int queue, int tempo) : QueueControlEvent()
853 {
854     snd_seq_ev_set_queue_tempo(&m_event, queue, tempo);
855 }
856 
857 /**
858  * Clone this object returning a pointer to the new object
859  * @return pointer to the new object
860  */
clone() const861 TempoEvent* TempoEvent::clone() const
862 {
863     return new TempoEvent(&m_event);
864 }
865 
866 /**
867  * Clone this object returning a pointer to the new object
868  * @return pointer to the new object
869  */
clone() const870 ClientEvent* ClientEvent::clone() const
871 {
872     return new ClientEvent(&m_event);
873 }
874 
875 /**
876  * Clone this object returning a pointer to the new object
877  * @return pointer to the new object
878  */
clone() const879 PortEvent* PortEvent::clone() const
880 {
881     return new PortEvent(&m_event);
882 }
883 
884 /**
885  * Clone this object returning a pointer to the new object
886  * @return pointer to the new object
887  */
clone() const888 SubscriptionEvent* SubscriptionEvent::clone() const
889 {
890     return new SubscriptionEvent(&m_event);
891 }
892 
893 /**
894  * Default constructor.
895  */
RemoveEvents()896 RemoveEvents::RemoveEvents()
897 {
898     snd_seq_remove_events_malloc(&m_Info);
899 }
900 
901 /**
902  * Copy constructor.
903  * @param other An existing RemoveEvents object reference.
904  */
RemoveEvents(const RemoveEvents & other)905 RemoveEvents::RemoveEvents(const RemoveEvents& other)
906 {
907     snd_seq_remove_events_malloc(&m_Info);
908     snd_seq_remove_events_copy(m_Info, other.m_Info);
909 }
910 
911 /**
912  * Constructor from an ALSA remove events object pointer.
913  * @param other An ALSA remove events object pointer.
914  */
RemoveEvents(snd_seq_remove_events_t * other)915 RemoveEvents::RemoveEvents(snd_seq_remove_events_t* other)
916 {
917     snd_seq_remove_events_malloc(&m_Info);
918     snd_seq_remove_events_copy(m_Info, other);
919 }
920 
921 /**
922  * Destructor.
923  */
~RemoveEvents()924 RemoveEvents::~RemoveEvents()
925 {
926     snd_seq_remove_events_free(m_Info);
927 }
928 
929 /**
930  * Create a new object copied from this object and return a pointer to the copy.
931  * @return A pointer to the new object.
932  */
933 RemoveEvents*
clone()934 RemoveEvents::clone()
935 {
936     return new RemoveEvents(m_Info);
937 }
938 
939 /**
940  * Assignment operator.
941  * @param other An existing RemoveEvents object reference.
942  * @return This object.
943  */
944 RemoveEvents&
operator =(const RemoveEvents & other)945 RemoveEvents::operator=(const RemoveEvents& other)
946 {
947     if (this == &other)
948         return *this;
949     snd_seq_remove_events_copy(m_Info, other.m_Info);
950     return *this;
951 }
952 
953 /**
954  * Gets the allocated size of the ALSA remove events object.
955  * @return The size of the ALSA remove events object.
956  */
957 int
getSizeOfInfo() const958 RemoveEvents::getSizeOfInfo() const
959 {
960     return snd_seq_remove_events_sizeof();
961 }
962 
963 /**
964  * Gets the MIDI channel.
965  * @return The MIDI channel.
966  * @see setChannel()
967  */
968 int
getChannel()969 RemoveEvents::getChannel()
970 {
971     return snd_seq_remove_events_get_channel(m_Info);
972 }
973 
974 /**
975  * Gets the condition.
976  * @return The condition.
977  * @see setCondition()
978  */
979 unsigned int
getCondition()980 RemoveEvents::getCondition()
981 {
982     return snd_seq_remove_events_get_condition(m_Info);
983 }
984 
985 /**
986  * Gets the destination.
987  * @return The destination record pointer.
988  * @see setDest()
989  */
990 const snd_seq_addr_t*
getDest()991 RemoveEvents::getDest()
992 {
993     return snd_seq_remove_events_get_dest(m_Info);
994 }
995 
996 /**
997  * Gets the event type.
998  * @return The event type.
999  * @see setEventType()
1000  */
1001 int
getEventType()1002 RemoveEvents::getEventType()
1003 {
1004     return snd_seq_remove_events_get_event_type(m_Info);
1005 }
1006 
1007 /**
1008  * Gets the queue number.
1009  * @return The queue number.
1010  * @see setQueue()
1011  */
1012 int
getQueue()1013 RemoveEvents::getQueue()
1014 {
1015     return snd_seq_remove_events_get_queue(m_Info);
1016 }
1017 
1018 /**
1019  * Gets the numeric tag.
1020  * @return The numeric tag.
1021  * @see setTag()
1022  */
1023 int
getTag()1024 RemoveEvents::getTag()
1025 {
1026     return snd_seq_remove_events_get_tag(m_Info);
1027 }
1028 
1029 /**
1030  * Gets the timestamp.
1031  * @return The timestamp.
1032  * @see setTime()
1033  */
1034 const snd_seq_timestamp_t*
getTime()1035 RemoveEvents::getTime()
1036 {
1037     return snd_seq_remove_events_get_time(m_Info);
1038 }
1039 
1040 /**
1041  * Gets the MIDI channel.
1042  * @param chan The MIDI channel.
1043  * @see getChannel()
1044  */
1045 void
setChannel(int chan)1046 RemoveEvents::setChannel(int chan)
1047 {
1048     snd_seq_remove_events_set_channel(m_Info, chan);
1049 }
1050 
1051 /**
1052  * Sets the flags of the conditional event's removal. This condition is a
1053  * bitmap of the combination (OR) the following auto-described flags:
1054  * <ul>
1055  * <li>SND_SEQ_REMOVE_INPUT</li>
1056  * <li>SND_SEQ_REMOVE_OUTPUT</li>
1057  * <li>SND_SEQ_REMOVE_DEST</li>
1058  * <li>SND_SEQ_REMOVE_DEST_CHANNEL</li>
1059  * <li>SND_SEQ_REMOVE_TIME_BEFORE</li>
1060  * <li>SND_SEQ_REMOVE_TIME_AFTER</li>
1061  * <li>SND_SEQ_REMOVE_TIME_TICK</li>
1062  * <li>SND_SEQ_REMOVE_EVENT_TYPE</li>
1063  * <li>SND_SEQ_REMOVE_IGNORE_OFF</li>
1064  * <li>SND_SEQ_REMOVE_TAG_MATCH</li>
1065  * </ul>
1066  * @param cond The condition bitmap.
1067  * @see getCondition()
1068  */
1069 void
setCondition(unsigned int cond)1070 RemoveEvents::setCondition(unsigned int cond)
1071 {
1072     snd_seq_remove_events_set_condition(m_Info, cond);
1073 }
1074 
1075 /**
1076  * Set the destination address.
1077  * @param dest A pointer to the destination address record.
1078  * @see getDest()
1079  */
1080 void
setDest(const snd_seq_addr_t * dest)1081 RemoveEvents::setDest(const snd_seq_addr_t* dest)
1082 {
1083     snd_seq_remove_events_set_dest(m_Info, dest);
1084 }
1085 
1086 /**
1087  * Sets the event type.
1088  * @param type The event type.
1089  * @see getEventType()
1090  */
1091 void
setEventType(int type)1092 RemoveEvents::setEventType(int type)
1093 {
1094     snd_seq_remove_events_set_event_type(m_Info, type);
1095 }
1096 
1097 /**
1098  * Sets the queue number.
1099  * @param queue The queue number.
1100  * @see getQueue()
1101  */
1102 void
setQueue(int queue)1103 RemoveEvents::setQueue(int queue)
1104 {
1105     snd_seq_remove_events_set_queue(m_Info, queue);
1106 }
1107 
1108 /**
1109  * Sets the numeric tag.
1110  * @param tag The numeric tag.
1111  * @see getTag()
1112  */
1113 void
setTag(int tag)1114 RemoveEvents::setTag(int tag)
1115 {
1116     snd_seq_remove_events_set_tag(m_Info, tag);
1117 }
1118 
1119 /**
1120  * Sets the timestamp.
1121  * @param time A pointer to the timestamp record.
1122  * @see getTime()
1123  */
1124 void
setTime(const snd_seq_timestamp_t * time)1125 RemoveEvents::setTime(const snd_seq_timestamp_t* time)
1126 {
1127     snd_seq_remove_events_set_time(m_Info, time);
1128 }
1129 
1130 /**
1131  * MidiCodec constructor
1132  * @param bufsize The buffer size of the CODEC
1133  * @param parent The optional parent object
1134  */
MidiCodec(int bufsize,QObject * parent)1135 MidiCodec::MidiCodec( int bufsize, QObject* parent ) : QObject(parent)
1136 {
1137     DRUMSTICK_ALSA_CHECK_ERROR(snd_midi_event_new(bufsize, &m_Info));
1138 }
1139 
1140 /**
1141  * Destructor
1142  */
~MidiCodec()1143 MidiCodec::~MidiCodec()
1144 {
1145     snd_midi_event_free(m_Info);
1146 }
1147 
1148 /**
1149  * CODEC initialization.
1150  */
1151 void
init()1152 MidiCodec::init()
1153 {
1154     snd_midi_event_init(m_Info);
1155 }
1156 
1157 /**
1158  * Decode from event to bytes.
1159  * @param buf A buffer to get the results
1160  * @param count Available bytes in MIDI byte stream
1161  * @param ev The input event
1162  * @return The number of written bytes if success.
1163  */
1164 long
decode(unsigned char * buf,long count,const snd_seq_event_t * ev)1165 MidiCodec::decode(unsigned char *buf,
1166                   long count,
1167                   const snd_seq_event_t *ev)
1168 {
1169     return DRUMSTICK_ALSA_CHECK_WARNING(snd_midi_event_decode(m_Info, buf, count, ev));
1170 }
1171 
1172 /**
1173  * Encode from byte stream.
1174  * @param buf MIDI byte stream
1175  * @param count Bytes of MIDI byte stream to encode
1176  * @param ev Result - sequencer event
1177  * @return Number of written bytes if success.
1178  */
1179 long
encode(const unsigned char * buf,long count,snd_seq_event_t * ev)1180 MidiCodec::encode(const unsigned char *buf,
1181                   long count,
1182                   snd_seq_event_t *ev)
1183 {
1184     return DRUMSTICK_ALSA_CHECK_WARNING(snd_midi_event_encode(m_Info, buf, count, ev));
1185 }
1186 
1187 /**
1188  * Read one byte and encode to sequencer event if finished.
1189  * @param c A byte of MIDI stream
1190  * @param ev Result - sequencer event
1191  * @return 1 - sequencer event is completed, 0 - next byte is required for completion, otherwise a negative error code
1192  */
1193 long
encode(int c,snd_seq_event_t * ev)1194 MidiCodec::encode(int c,
1195                   snd_seq_event_t *ev)
1196 {
1197     return DRUMSTICK_ALSA_CHECK_WARNING(snd_midi_event_encode_byte(m_Info, c, ev));
1198 }
1199 
1200 /**
1201  * Enable MIDI running status (command merge)
1202  * @param enable True to enable, false to disable.
1203  */
1204 void
enableRunningStatus(bool enable)1205 MidiCodec::enableRunningStatus(bool enable)
1206 {
1207     snd_midi_event_no_status(m_Info, enable ? 0 : 1);
1208 }
1209 
1210 /**
1211  * Reset MIDI decode parser.
1212  */
1213 void
resetDecoder()1214 MidiCodec::resetDecoder()
1215 {
1216     snd_midi_event_reset_decode(m_Info);
1217 }
1218 
1219 /**
1220  * Reset MIDI encode parser.
1221  */
1222 void
resetEncoder()1223 MidiCodec::resetEncoder()
1224 {
1225     snd_midi_event_reset_encode(m_Info);
1226 }
1227 
1228 /**
1229  * Resize the CODEC buffer
1230  * @param bufsize New buffer size.
1231  */
1232 void
resizeBuffer(int bufsize)1233 MidiCodec::resizeBuffer(int bufsize)
1234 {
1235     DRUMSTICK_ALSA_CHECK_WARNING(snd_midi_event_resize_buffer(m_Info, bufsize));
1236 }
1237 
1238 } // namespace ALSA
1239 } // namespace drumstick
1240 
1241