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 #ifndef DRUMSTICK_ALSAEVENT_H
20 #define DRUMSTICK_ALSAEVENT_H
21 
22 extern "C" {
23     #include <alsa/asoundlib.h>
24 }
25 
26 #include <QObject>
27 #include <QEvent>
28 #include "macros.h"
29 
30 namespace drumstick { namespace ALSA {
31 
32 /**
33  * @file alsaevent.h
34  * Classes managing ALSA Sequencer events.
35  *
36  * @addtogroup ALSAEvent ALSA Sequencer Events
37  * @{
38  */
39 
40 /**
41  * 8-bit unsigned number to be used as a MIDI message parameter
42  */
43 typedef quint8 MidiByte;
44 
45 /**
46  * Constant SequencerEventType is the QEvent::type() of any SequencerEvent
47  * object to be used to check the argument in QObject::customEvent().
48  */
49 const QEvent::Type SequencerEventType = QEvent::Type(QEvent::User + 4154); // :-)
50 
51 /**
52  * Base class for the event's hierarchy
53  *
54  * All event classes share this base class. It provides several common
55  * properties and methods.
56  */
57 class DRUMSTICK_EXPORT SequencerEvent : public QEvent
58 {
59 public:
60     SequencerEvent();
61     SequencerEvent(const SequencerEvent& other);
62     explicit SequencerEvent(const snd_seq_event_t* event);
63 
64     SequencerEvent& operator=(const SequencerEvent& other);
65     void setSequencerType(const snd_seq_event_type_t eventType);
66     /**
67      * Gets the sequencer event type.
68      * @return The sequencer event type.
69      * @see setSequencerType()
70      */
getSequencerType()71     snd_seq_event_type_t getSequencerType() const { return m_event.type; }
72     void setDestination(const unsigned char client, const unsigned char port);
73     void setSource(const unsigned char port);
74     /**
75      * Gets the source client id.
76      * @return The source client id.
77      * @see setSource()
78      */
getSourceClient()79     unsigned char getSourceClient() const { return m_event.source.client; }
80     /**
81      * Gets the source port id.
82      * @return The source port id.
83      * @see setSource()
84      */
getSourcePort()85     unsigned char getSourcePort() const { return m_event.source.port; }
86     /**
87      * Gets the tick time of the event.
88      * @return The tick time.
89      * @see scheduleTick()
90      */
getTick()91     snd_seq_tick_time_t getTick() const { return m_event.time.tick; }
92     /**
93      * Gets the seconds of the event's real time.
94      * @return The seconds of the time.
95      * @see scheduleReal(), getRealTimeNanos()
96      */
getRealTimeSecs()97     unsigned int getRealTimeSecs() const { return m_event.time.time.tv_sec; }
98     /**
99      * Gets the nanoseconds of the event's real time.
100      * @return The nanoseconds of the time.
101      * @see scheduleReal(), getRealTimeSecs()
102      */
getRealTimeNanos()103     unsigned int getRealTimeNanos() const { return m_event.time.time.tv_nsec; }
104     void setSubscribers();
105     void setBroadcast();
106     void setDirect();
107     void scheduleTick(const int queue, const int tick, const bool relative);
108     void scheduleReal(const int queue, const ulong secs, const ulong nanos, const bool relative);
109     void setPriority(const bool high);
110     /**
111      * Gets the tag of the event
112      * @return The event's tag
113      * @see setTag()
114      */
getTag()115     unsigned char getTag() const { return m_event.tag; }
116     void setTag(const unsigned char aTag);
117     unsigned int getRaw32(const unsigned int n) const;
118     void setRaw32(const unsigned int n, const unsigned int value);
119     unsigned char getRaw8(const unsigned int n) const;
120     void setRaw8(const unsigned int n, const unsigned char value);
121     /**
122      * Gets the handle of the event
123      * @return The event's handle
124      */
getHandle()125     snd_seq_event_t* getHandle() { return &m_event; }
126     int getEncodedLength();
127 
128     static bool isSubscription(const SequencerEvent* event);
129     static bool isPort(const SequencerEvent* event);
130     static bool isClient(const SequencerEvent* event);
131     static bool isConnectionChange(const SequencerEvent* event);
132     static bool isChannel(const SequencerEvent* event);
133     virtual SequencerEvent* clone() const;
134 
135 protected:
136     Q_DECL_DEPRECATED void free();
137 
138     /**
139      * ALSA sequencer event record.
140      * @see https://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event.html
141      */
142     snd_seq_event_t m_event;
143 };
144 
145 /**
146  * Base class for the events having a Channel property
147  */
148 class DRUMSTICK_EXPORT ChannelEvent : public SequencerEvent
149 {
150 public:
151     /** Default constructor */
ChannelEvent()152     ChannelEvent() : SequencerEvent() {}
153     /**
154      * Constructor from an ALSA event record
155      * @param event an ALSA event record
156      */
ChannelEvent(const snd_seq_event_t * event)157     explicit ChannelEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
158     /**
159      * Sets the channel of the event
160      * @param c A channel, between 0 and 15.
161      * @see getChannel()
162      */
setChannel(const MidiByte c)163     void setChannel(const MidiByte c) { m_event.data.note.channel = (c & 0xf); }
164     /**
165      * Gets the event's channel
166      * @return The event's channel
167      * @see setChannel()
168      */
getChannel()169     int getChannel() const { return m_event.data.note.channel; }
170 
171     virtual ChannelEvent* clone() const override;
172 };
173 
174 /**
175  * Base class for the events having Key and Velocity properties.
176  */
177 class DRUMSTICK_EXPORT KeyEvent : public ChannelEvent
178 {
179 public:
180     /** Default constructor */
KeyEvent()181     KeyEvent() : ChannelEvent() {}
182     /**
183      * Constructor from an ALSA event record
184      * @param event an ALSA event record
185      */
KeyEvent(const snd_seq_event_t * event)186     explicit KeyEvent(const snd_seq_event_t* event) : ChannelEvent(event) {}
187     /**
188      * Gets the MIDI note of this event.
189      * @return The event's MIDI note.
190      * @see setKey()
191      */
getKey()192     int getKey() const { return m_event.data.note.note; }
193     /**
194      * Sets the MIDI note of this event.
195      * @param b A MIDI note, between 0 and 127.
196      * @see getKey()
197      */
setKey(const MidiByte b)198     void setKey(const MidiByte b) { m_event.data.note.note = b; }
199     /**
200      * Gets the note velocity of this event.
201      * @return The event's note velocity.
202      * @see setVelocity()
203      */
getVelocity()204     int getVelocity() const { return m_event.data.note.velocity; }
205     /**
206      * Sets the note velocity of this event.
207      * @param b A velocity value, between 0 and 127.
208      * @see getVelocity()
209      */
setVelocity(const MidiByte b)210     void setVelocity(const MidiByte b) { m_event.data.note.velocity = b; }
211 
212     virtual KeyEvent* clone() const override;
213 };
214 
215 /**
216  * Class representing a note event with duration
217  *
218  * Note events are converted into two MIDI events, a note-on and a note-off
219  * over the wire.
220  */
221 class DRUMSTICK_EXPORT NoteEvent : public KeyEvent
222 {
223 public:
224     /** Default constructor */
NoteEvent()225     NoteEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTE; }
226     /**
227      * Constructor from an ALSA event record
228      * @param event an ALSA event record
229      */
NoteEvent(const snd_seq_event_t * event)230     explicit NoteEvent(const snd_seq_event_t* event) : KeyEvent(event) {}
231     /**
232      * Constructor
233      * @param ch MIDI Channel
234      * @param key a MIDI note number
235      * @param vel a MIDI velocity value
236      * @param dur duration of the note in ticks
237      */
238     NoteEvent(const int ch, const int key, const int vel, const int dur);
239     /**
240      * Gets the note's duration
241      * @return The duration of the event
242      * @see setDuration()
243      */
getDuration()244     ulong getDuration() const { return m_event.data.note.duration; }
245     /**
246      * Sets the note's duration
247      * @param d The duration of the event
248      * @see getDuration()
249      */
setDuration(const ulong d)250     void setDuration(const ulong d) { m_event.data.note.duration = d; }
251 
252     virtual NoteEvent* clone() const override;
253 };
254 
255 /**
256  * Event representing a note-on MIDI event
257  */
258 class DRUMSTICK_EXPORT NoteOnEvent : public KeyEvent
259 {
260 public:
261     /** Default constructor */
NoteOnEvent()262     NoteOnEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTEON; }
263     /**
264      * Constructor from an ALSA event record
265      * @param event an ALSA event record
266      */
NoteOnEvent(const snd_seq_event_t * event)267     explicit NoteOnEvent(const snd_seq_event_t* event) : KeyEvent(event) {}
268     /**
269      * Constructor
270      * @param ch MIDI Channel
271      * @param key a MIDI note number
272      * @param vel a MIDI velocity value
273      */
274     NoteOnEvent(const int ch, const int key, const int vel);
275     virtual NoteOnEvent* clone() const override;
276 };
277 
278 /**
279  * Event representing a note-off MIDI event
280  */
281 class DRUMSTICK_EXPORT NoteOffEvent : public KeyEvent
282 {
283 public:
284     /** Default constructor */
NoteOffEvent()285     NoteOffEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTEOFF; }
286     /**
287      * Constructor from an ALSA event record
288      * @param event an ALSA event record
289      */
NoteOffEvent(const snd_seq_event_t * event)290     explicit NoteOffEvent(const snd_seq_event_t* event) : KeyEvent(event) {}
291     /**
292      * Constructor
293      * @param ch MIDI Channel
294      * @param key a MIDI note number
295      * @param vel a MIDI velocity value
296      */
297     NoteOffEvent(const int ch, const int key, const int vel);
298     virtual NoteOffEvent* clone() const override;
299 };
300 
301 /**
302  * Event representing a MIDI key pressure, or polyphonic after-touch event
303  */
304 class DRUMSTICK_EXPORT KeyPressEvent : public KeyEvent
305 {
306 public:
307     /** Default constructor */
KeyPressEvent()308     KeyPressEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_KEYPRESS; }
309     /**
310      * Constructor from an ALSA event record
311      * @param event an ALSA event record
312      */
KeyPressEvent(const snd_seq_event_t * event)313     explicit KeyPressEvent(const snd_seq_event_t* event) : KeyEvent(event) {}
314     /**
315      * Constructor
316      * @param ch MIDI Channel
317      * @param key a MIDI note number
318      * @param vel a MIDI velocity value
319      */
320     KeyPressEvent(const int ch, const int key, const int vel);
321     virtual KeyPressEvent* clone() const override;
322 };
323 
324 /**
325  * Event representing a MIDI control change event
326  */
327 class DRUMSTICK_EXPORT ControllerEvent : public ChannelEvent
328 {
329 public:
330     /** Default constructor */
ControllerEvent()331     ControllerEvent() : ChannelEvent() {}
332     /**
333      * Constructor from an ALSA event record
334      * @param event an ALSA event record
335      */
ControllerEvent(const snd_seq_event_t * event)336     explicit ControllerEvent(const snd_seq_event_t* event) : ChannelEvent(event) {}
337     /**
338      * Constructor
339      * @param ch MIDI Channel
340      * @param cc a MIDI controller
341      * @param val a value
342      */
343     ControllerEvent(const int ch, const int cc, const int val);
344     /**
345      * Gets the controller event's parameter.
346      * @return The controller event's parameter.
347      * @see setParam()
348      */
getParam()349     uint getParam() const { return m_event.data.control.param; }
350     /**
351      * Sets the controller event's parameter.
352      * @param p The controller event's parameter.
353      * @see getParam()
354      */
setParam(const uint p)355     void setParam( const uint p ) { m_event.data.control.param = p; }
356     /**
357      * Gets the controller event's value.
358      * @return The controller event's value.
359      * @see setValue()
360      */
getValue()361     int getValue() const { return m_event.data.control.value; }
362     /**
363      * Sets the controller event's value.
364      * @param v The controller event's value.
365      * @see getValue()
366      */
setValue(const int v)367     void setValue( const int v ) { m_event.data.control.value = v; }
368     virtual ControllerEvent* clone() const override;
369 };
370 
371 /**
372  * Event representing a MIDI program change event
373  */
374 class DRUMSTICK_EXPORT ProgramChangeEvent : public ChannelEvent
375 {
376 public:
377     /** Default constructor */
ProgramChangeEvent()378     ProgramChangeEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_PGMCHANGE; }
379     /**
380      * Constructor from an ALSA event record
381      * @param event an ALSA event record
382      */
ProgramChangeEvent(const snd_seq_event_t * event)383     explicit ProgramChangeEvent(const snd_seq_event_t* event) : ChannelEvent(event) {}
384     /**
385      * Constructor
386      * @param ch MIDI Channel
387      * @param val a value
388      */
389     ProgramChangeEvent(const int ch, const int val);
390     /**
391      * Gets the MIDI program number
392      * @return the MIDI program number
393      */
getValue()394     int getValue() const { return m_event.data.control.value; }
395     /**
396      * Sets the MIDI program number
397      * @param v the MIDI program number
398      */
setValue(const int v)399     void setValue( const int v ) { m_event.data.control.value = v; }
400     virtual ProgramChangeEvent* clone() const override;
401 };
402 
403 /**
404  * Event representing a MIDI bender, or pitch wheel event
405  */
406 class DRUMSTICK_EXPORT PitchBendEvent : public ChannelEvent
407 {
408 public:
409     /** Default constructor */
PitchBendEvent()410     PitchBendEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_PITCHBEND; }
411     /**
412      * Constructor from an ALSA event record
413      * @param event an ALSA event record
414      */
PitchBendEvent(const snd_seq_event_t * event)415     explicit PitchBendEvent(const snd_seq_event_t* event) : ChannelEvent(event) {}
416     /**
417      * Constructor
418      * @param ch MIDI Channel
419      * @param val a value
420      */
421     PitchBendEvent(const int ch, const int val);
422     /**
423      * Gets the MIDI pitch bend value, zero centered from -8192 to 8191
424      * @return the MIDI pitch bend value
425      */
getValue()426     int getValue() const { return m_event.data.control.value; }
427     /**
428      * Sets the MIDI pitch bend value, zero centered from -8192 to 8191
429      * @param v the MIDI pitch bend value
430      */
setValue(const int v)431     void setValue( const int v ) { m_event.data.control.value = v; }
432     virtual PitchBendEvent* clone() const override;
433 };
434 
435 /**
436  * Event representing a MIDI channel pressure or after-touch event
437  */
438 class DRUMSTICK_EXPORT ChanPressEvent : public ChannelEvent
439 {
440 public:
441     /** Default constructor */
ChanPressEvent()442     ChanPressEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_CHANPRESS; }
443     /**
444      * Constructor from an ALSA event record
445      * @param event an ALSA event record
446      */
ChanPressEvent(const snd_seq_event_t * event)447     explicit ChanPressEvent( const snd_seq_event_t* event ) : ChannelEvent(event) {}
448     /**
449      * Constructor
450      * @param ch MIDI Channel
451      * @param val a value
452      */
453     ChanPressEvent( const int ch, const int val );
454     /**
455      * Gets the channel aftertouch value
456      * @return the channel aftertouch value
457      */
getValue()458     int getValue() const { return m_event.data.control.value; }
459     /**
460      * Sets the channel aftertouch value
461      * @param v the channel aftertouch value
462      */
setValue(const int v)463     void setValue( const int v ) { m_event.data.control.value = v; }
464     virtual ChanPressEvent* clone() const override;
465 };
466 
467 /**
468  * Base class for variable length events
469  */
470 class DRUMSTICK_EXPORT VariableEvent : public SequencerEvent
471 {
472 public:
473     VariableEvent();
474     explicit VariableEvent(const snd_seq_event_t* event);
475     explicit VariableEvent(const QByteArray& data);
476     VariableEvent(const VariableEvent& other);
477     VariableEvent(const unsigned int datalen, char* dataptr);
478     VariableEvent& operator=(const VariableEvent& other);
479     /**
480      * Gets the data length
481      * @return the data length
482      */
getLength()483     unsigned int getLength() const { return m_event.data.ext.len; }
484     /**
485      * Gets the data pointer
486      * @return the data pointer
487      */
getData()488     const char* getData() const { return static_cast<const char*>(m_event.data.ext.ptr); }
489     virtual VariableEvent* clone() const override;
490 protected:
491     QByteArray m_data;
492 };
493 
494 /**
495  * Event representing a MIDI system exclusive event
496  */
497 class DRUMSTICK_EXPORT SysExEvent : public VariableEvent
498 {
499 public:
500     SysExEvent();
501     explicit SysExEvent(const snd_seq_event_t* event);
502     explicit SysExEvent(const QByteArray& data);
503     SysExEvent(const SysExEvent& other);
504     SysExEvent(const unsigned int datalen, char* dataptr);
505     virtual SysExEvent* clone() const override;
506 };
507 
508 /**
509  * Event representing a SMF text event
510  *
511  * This event type is not intended to be transmitted over the wire to an
512  * external device, but it is useful for sequencer programs or MIDI applications
513  */
514 class DRUMSTICK_EXPORT TextEvent : public VariableEvent
515 {
516 public:
517     TextEvent();
518     explicit TextEvent(const snd_seq_event_t* event);
519     explicit TextEvent(const QString& text, const int textType = 1);
520     TextEvent(const TextEvent& other);
521     TextEvent(const unsigned int datalen, char* dataptr);
522     QString getText() const;
523     int getTextType() const;
524     virtual TextEvent* clone() const override;
525 protected:
526     int m_textType;
527 };
528 
529 /**
530  * Generic event
531  */
532 class DRUMSTICK_EXPORT SystemEvent : public SequencerEvent
533 {
534 public:
535     /** Default constructor */
SystemEvent()536     SystemEvent() : SequencerEvent() {}
537     /**
538      * Constructor from an ALSA event record
539      * @param event an ALSA event record
540      */
SystemEvent(const snd_seq_event_t * event)541     explicit SystemEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
542     explicit SystemEvent(const snd_seq_event_type_t type);
543     virtual SystemEvent* clone() const override;
544 };
545 
546 /**
547  * ALSA Event representing a queue control command
548  *
549  * This event is used to schedule changes to the ALSA queues
550  */
551 class DRUMSTICK_EXPORT QueueControlEvent : public SequencerEvent
552 {
553 public:
554     /** Default constructor */
QueueControlEvent()555     QueueControlEvent() : SequencerEvent() {}
556     /**
557      * Constructor from an ALSA event record
558      * @param event an ALSA event record
559      */
QueueControlEvent(const snd_seq_event_t * event)560     explicit QueueControlEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
561     QueueControlEvent(const snd_seq_event_type_t type, const int queue, const int value);
562     /**
563      * Gets the queue number
564      * @return the queue number
565      */
getQueue()566     int getQueue() const { return m_event.data.queue.queue; }
567     /**
568      * Sets the queue number
569      * @param q the queue number
570      */
setQueue(const uchar q)571     void setQueue(const uchar q) { m_event.data.queue.queue = q; }
572     /**
573      * Gets the event's value
574      * @return the event's value
575      */
getValue()576     int getValue() const { return m_event.data.queue.param.value; }
577     /**
578      * Sets the event's value
579      * @param val the event's value
580      */
setValue(const int val)581     void setValue(const int val) { m_event.data.queue.param.value = val; }
582     /**
583      * Gets the queue position
584      * @return the queue position
585      */
getPosition()586     uint getPosition() const { return m_event.data.queue.param.position; }
587     /**
588      * Sets the queue position
589      * @param pos the queue position
590      */
setPosition(const uint pos)591     void setPosition(const uint pos) { m_event.data.queue.param.position = pos; }
592     /**
593      * Gets the musical time in ticks
594      * @return the musical time in ticks
595      */
getTickTime()596     snd_seq_tick_time_t getTickTime() const { return m_event.data.queue.param.time.tick; }
597     /**
598      * Sets the musical time in ticks
599      * @param t the musical time in ticks
600      */
setTickTime(const snd_seq_tick_time_t t)601     void setTickTime(const snd_seq_tick_time_t t) { m_event.data.queue.param.time.tick = t; }
602     /**
603      * Gets the skew base
604      * @return the skew base
605      */
getSkewBase()606     uint getSkewBase() const { return m_event.data.queue.param.skew.base;  }
607     /**
608      * Sets the skew base, should be 65536
609      * @param base the skew base, should be 65536
610      */
setSkewBase(const uint base)611     void setSkewBase(const uint base) { m_event.data.queue.param.skew.base = base; }
612     /**
613      * Gets the skew value
614      * @return the skew value
615      */
getSkewValue()616     uint getSkewValue() const { return m_event.data.queue.param.skew.value;  }
617     /**
618      * Sets the skew value
619      * @param val the skew value
620      */
setSkewValue(const uint val)621     void setSkewValue(const uint val) {m_event.data.queue.param.skew.value = val; }
622     virtual QueueControlEvent* clone() const override;
623 };
624 
625 /**
626  * Generic event having a value property
627  */
628 class DRUMSTICK_EXPORT ValueEvent : public SequencerEvent
629 {
630 public:
631     /** Default constructor */
ValueEvent()632     ValueEvent() : SequencerEvent() {}
633     /**
634      * Constructor from an ALSA event record
635      * @param event an ALSA event record
636      */
ValueEvent(const snd_seq_event_t * event)637     explicit ValueEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
638     ValueEvent(const snd_seq_event_type_t type, const int val);
639     /**
640      * Gets the event's value
641      * @return the event's value
642      */
getValue()643     int getValue() const { return m_event.data.control.value; }
644     /**
645      * Sets the event's value
646      * @param v the event's value
647      */
setValue(const int v)648     void setValue( const int v ) { m_event.data.control.value = v; }
649     virtual ValueEvent* clone() const override;
650 };
651 
652 /**
653  * ALSA Event representing a tempo change for an ALSA queue
654  */
655 class DRUMSTICK_EXPORT TempoEvent : public QueueControlEvent
656 {
657 public:
658     /** Default constructor */
TempoEvent()659     TempoEvent() : QueueControlEvent() {}
660     /**
661      * Constructor from an ALSA event record
662      * @param event an ALSA event record
663      */
TempoEvent(const snd_seq_event_t * event)664     explicit TempoEvent(const snd_seq_event_t* event) : QueueControlEvent(event) {}
665     TempoEvent(const int queue, const int tempo);
666     virtual TempoEvent* clone() const override;
667 };
668 
669 /**
670  * ALSA Event representing a subscription between two ALSA clients and ports
671  */
672 class DRUMSTICK_EXPORT SubscriptionEvent : public SequencerEvent
673 {
674 public:
675     /** Default constructor */
SubscriptionEvent()676     SubscriptionEvent() : SequencerEvent() {}
677     /**
678      * Constructor from an ALSA event record
679      * @param event an ALSA event record
680      */
SubscriptionEvent(const snd_seq_event_t * event)681     explicit SubscriptionEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
682     /**
683      * Returns true if the event was a subscribed port
684      * @return whether the event was a subscribed port
685      */
subscribed()686     bool subscribed() const { return (m_event.type == SND_SEQ_EVENT_PORT_SUBSCRIBED); }
687     /**
688      * Returns true if the event was an unsubscribed port
689      * @return whether the event was an unsubscribed port
690      */
unsubscribed()691     bool unsubscribed() const { return (m_event.type == SND_SEQ_EVENT_PORT_UNSUBSCRIBED); }
692     /**
693      * Gets the sender client number
694      * @return the sender client number
695      */
getSenderClient()696     int getSenderClient() const { return m_event.data.connect.sender.client; }
697     /**
698      * Gets the sender port number
699      * @return the sender port number
700      */
getSenderPort()701     int getSenderPort() const { return m_event.data.connect.sender.port; }
702     /**
703      * Gets the destination client number
704      * @return the destination client number
705      */
getDestClient()706     int getDestClient() const { return m_event.data.connect.dest.client; }
707     /**
708      * Gets the destination port number
709      * @return the destination port number
710      */
getDestPort()711     int getDestPort() const { return m_event.data.connect.dest.port; }
712     virtual SubscriptionEvent* clone() const override;
713 };
714 
715 /**
716  * ALSA Event representing a change on some ALSA sequencer client on the system
717  */
718 class DRUMSTICK_EXPORT ClientEvent : public SequencerEvent
719 {
720 public:
721     /** Default constructor */
ClientEvent()722     ClientEvent() : SequencerEvent() {}
723     /**
724      * Constructor from an ALSA event record
725      * @param event an ALSA event record
726      */
ClientEvent(const snd_seq_event_t * event)727     explicit ClientEvent(const snd_seq_event_t* event) : SequencerEvent(event) {}
728     /**
729      * Gets the client number
730      * @return the client number
731      */
getClient()732     int getClient() const { return m_event.data.addr.client; }
733     virtual ClientEvent* clone() const override;
734 };
735 
736 /**
737  * ALSA Event representing a change on some ALSA sequencer port on the system
738  */
739 class DRUMSTICK_EXPORT PortEvent : public ClientEvent
740 {
741 public:
742     /** Default constructor */
PortEvent()743     PortEvent() : ClientEvent() {}
744     /**
745      * Constructor from an ALSA event record
746      * @param event an ALSA event record
747      */
PortEvent(const snd_seq_event_t * event)748     explicit PortEvent(const snd_seq_event_t* event) : ClientEvent(event) {}
749     /**
750      * Gets the port number
751      * @return the port number
752      */
getPort()753     int getPort() const { return m_event.data.addr.port; }
754     virtual PortEvent* clone() const override;
755 };
756 
757 /**
758  * Auxiliary class to remove events from an ALSA queue
759  * @see MidiClient::removeEvents()
760  */
761 class DRUMSTICK_EXPORT RemoveEvents
762 {
763 public:
764     friend class MidiClient;
765 
766 public:
767     RemoveEvents();
768     RemoveEvents(const RemoveEvents& other);
769     explicit RemoveEvents(snd_seq_remove_events_t* other);
770     virtual ~RemoveEvents();
771     RemoveEvents* clone();
772     RemoveEvents& operator=(const RemoveEvents& other);
773     int getSizeOfInfo() const;
774 
775     int getChannel();
776     unsigned int getCondition();
777     const snd_seq_addr_t* getDest();
778     int getEventType();
779     int getQueue();
780     int getTag();
781     const snd_seq_timestamp_t* getTime();
782     void setChannel(int chan);
783     void setCondition(unsigned int cond);
784     void setDest(const snd_seq_addr_t* dest);
785     void setEventType(int type);
786     void setQueue(int queue);
787     void setTag(int tag);
788     void setTime(const snd_seq_timestamp_t* time);
789 
790 private:
791     snd_seq_remove_events_t* m_Info;
792 };
793 
794 /**
795  * Auxiliary class to translate between raw MIDI streams and ALSA events
796  */
797 class DRUMSTICK_EXPORT MidiCodec : public QObject
798 {
799     Q_OBJECT
800 public:
801     explicit MidiCodec(int bufsize, QObject* parent = nullptr);
802     ~MidiCodec();
803 
804     void init();
805     long decode(unsigned char *buf,
806                 long count,
807                 const snd_seq_event_t *ev);
808     long encode(const unsigned char *buf,
809                 long count,
810                 snd_seq_event_t *ev);
811     long encode(int c,
812                 snd_seq_event_t *ev);
813     void enableRunningStatus(bool enable);
814     void resetEncoder();
815     void resetDecoder();
816     void resizeBuffer(int bufsize);
817 private:
818     snd_midi_event_t* m_Info;
819 };
820 
821 /** @} */
822 
823 }} /* namespace drumstick::ALSA */
824 
825 #endif //DRUMSTICK_ALSAEVENT_H
826