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