1 /*
2  * Copyright (C) 2018-2021 Alexandros Theodotou <alex at zrythm dot org>
3  *
4  * This file is part of Zrythm
5  *
6  * Zrythm is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Zrythm is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with Zrythm.  If not, see <https://www.gnu.org/licenses/>.
18  *
19  * This file incorporates work covered by the following copyright and
20  * permission notice:
21  *
22  * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
23  *
24  * This program is free software: you can redistribute it and/or modify
25  * it under the terms of the GNU General Public License as published by
26  * the Free Software Foundation, either version 2 of the License, or
27  * (at your option) any later version.
28  *
29  * This program is distributed in the hope that it will be useful,
30  * but WITHOUT ANY WARRANTY; without even the implied warranty of
31  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32  * GNU General Public License for more details.
33  *
34  * You should have received a copy of the GNU General Public License
35  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
36  */
37 
38 #include <inttypes.h>
39 #include <math.h>
40 #include <stdlib.h>
41 #include <signal.h>
42 
43 #include "audio/channel.h"
44 #include "audio/chord_descriptor.h"
45 #include "audio/engine.h"
46 #include "audio/midi_event.h"
47 #include "audio/router.h"
48 #include "audio/transport.h"
49 #include "project.h"
50 #include "utils/objects.h"
51 
52 static const char * midi_event_type_strings[] =
53 {
54   "pitchbend",
55   "controller",
56   "note off",
57   "note on",
58   "all notes off",
59 };
60 
61 /**
62  * Prints a message saying unknown event, with
63  * information about the given event.
64  */
65 static void
print_unknown_event_message(uint8_t * buf,const int buf_size)66 print_unknown_event_message (
67   uint8_t * buf,
68   const int buf_size)
69 {
70   if (buf_size == 3)
71     {
72       g_message (
73         "Unknown MIDI event %#x %#x %#x"
74         " received", buf[0], buf[1], buf[2]);
75     }
76   else if (buf_size == 2)
77     {
78       g_message (
79         "Unknown MIDI event %#x %#x"
80         " received", buf[0], buf[1]);
81     }
82   else if (buf_size == 1)
83     {
84       g_message (
85         "Unknown MIDI event %#x"
86         " received", buf[0]);
87     }
88   else
89     {
90       g_message (
91         "Unknown MIDI event of size %d"
92         " received", buf_size);
93     }
94 }
95 
96 /**
97  * Appends the events from src to dest
98  *
99  * @param queued Append queued events instead of
100  *   main events.
101  * @param local_offset The start frame offset from 0
102  *   in this cycle.
103  * @param nframes Number of frames to process.
104  */
105 void
midi_events_append(MidiEvents * src,MidiEvents * dest,const nframes_t local_offset,const nframes_t nframes,bool queued)106 midi_events_append (
107   MidiEvents *    src,
108   MidiEvents *    dest,
109   const nframes_t local_offset,
110   const nframes_t nframes,
111   bool            queued)
112 {
113   midi_events_append_w_filter (
114     src, dest, NULL, local_offset, nframes, queued);
115 }
116 
117 /**
118  * Appends the events from src to dest
119  *
120  * @param queued Append queued events instead of
121  *   main events.
122  * @param channels Allowed channels (array of 16
123  *   booleans).
124  * @param local_offset The start frame offset from 0
125  *   in this cycle.
126  * @param nframes Number of frames to process.
127  */
128 void
midi_events_append_w_filter(MidiEvents * src,MidiEvents * dest,int * channels,const nframes_t local_offset,const nframes_t nframes,bool queued)129 midi_events_append_w_filter (
130   MidiEvents *    src,
131   MidiEvents *    dest,
132   int *           channels,
133   const nframes_t local_offset,
134   const nframes_t nframes,
135   bool            queued)
136 {
137   /* queued not implemented yet */
138   g_return_if_fail (!queued);
139 
140   MidiEvent * src_ev, * dest_ev;
141   for (int i = 0; i < src->num_events; i++)
142     {
143       src_ev = &src->events[i];
144 
145       /* only copy events inside the current time
146        * range */
147       if (ZRYTHM_TESTING
148           &&
149           (src_ev->time < local_offset ||
150            src_ev->time >= local_offset + nframes))
151         {
152           g_debug (
153             "skipping event: time %" PRIu8
154             " (local offset %" PRIu32
155             " nframes %" PRIu32 ")",
156             src_ev->time, local_offset, nframes);
157           continue;
158         }
159 
160       /* if filtering, skip disabled channels */
161       if (channels)
162         {
163           midi_byte_t channel =
164             src_ev->raw_buffer[0] & 0xf;
165           if (!channels[channel])
166             {
167               continue;
168             }
169         }
170 
171       g_return_if_fail (
172         dest->num_events < MAX_MIDI_EVENTS);
173 
174       dest_ev =
175         &dest->events[dest->num_events++];
176       midi_event_copy (dest_ev, src_ev);
177     }
178 
179   /* clear duplicates */
180   midi_events_clear_duplicates (dest, queued);
181 }
182 
183 /**
184  * Sets the given MIDI channel on all applicable
185  * MIDI events.
186  *
187  * @param channel Channel, starting from 1.
188  */
189 void
midi_events_set_channel(MidiEvents * self,const int queued,const midi_byte_t channel)190 midi_events_set_channel (
191   MidiEvents *      self,
192   const int         queued,
193   const midi_byte_t channel)
194 {
195   /* queued not implemented yet */
196   g_return_if_fail (!queued);
197 
198   for (int i = 0; i < self->num_events; i++)
199     {
200       MidiEvent * ev = &self->events[i];
201       ev->channel = channel;
202 
203       /* do this on all MIDI events that have
204        * channels */
205 #define SET_CHANNEL(byte) \
206       if ((ev->raw_buffer[0] & byte) == byte) \
207         { \
208           ev->raw_buffer[0] = \
209             (ev->raw_buffer[0] & byte) | \
210             (channel - 1); \
211           continue; \
212         }
213 
214       /* skip MIDI events starting with the given
215        * byte */
216 #define SKIP_CHANNEL(byte) \
217       if ((ev->raw_buffer[0] & byte) == byte) \
218         continue;
219 
220       SKIP_CHANNEL (0xF0);
221       SET_CHANNEL (0xE0);
222       SET_CHANNEL (0xD0);
223       SET_CHANNEL (0xC0);
224       SET_CHANNEL (0xB0);
225       SET_CHANNEL (0xA0);
226       SET_CHANNEL (0x90);
227       SET_CHANNEL (0x80);
228 
229 #undef SET_CHANNEL
230 #undef SKIP_CHANNEL
231     }
232 }
233 
234 /**
235  * Clears midi events.
236  */
237 REALTIME
238 void
midi_events_clear(MidiEvents * self,int queued)239 midi_events_clear (
240   MidiEvents * self,
241   int          queued)
242 {
243   if (queued)
244     {
245       self->num_queued_events = 0;
246     }
247   else
248     {
249       self->num_events = 0;
250     }
251 }
252 
253 /**
254  * Returns if a note on event for the given note
255  * exists in the given events.
256  */
257 int
midi_events_check_for_note_on(MidiEvents * self,int note,int queued)258 midi_events_check_for_note_on (
259   MidiEvents * self,
260   int          note,
261   int          queued)
262 {
263   /*g_message ("waiting check note on");*/
264   zix_sem_wait (&self->access_sem);
265 
266   MidiEvent * ev;
267   for (int i = 0;
268        i < queued ?
269          self->num_queued_events :
270          self->num_events;
271        i++)
272     {
273       if (queued)
274         ev = &self->queued_events[i];
275       else
276         ev = &self->events[i];
277 
278       if (ev->type == MIDI_EVENT_TYPE_NOTE_ON &&
279           ev->note_pitch == note)
280         return 1;
281     }
282 
283   zix_sem_post (&self->access_sem);
284   /*g_message ("posted check note on");*/
285 
286   return 0;
287 }
288 
289 /**
290  * Deletes the midi event with a note on signal
291  * from the queue, and returns if it deleted or not.
292  */
293 int
midi_events_delete_note_on(MidiEvents * self,int note,int queued)294 midi_events_delete_note_on (
295   MidiEvents * self,
296   int note,
297   int queued)
298 {
299   /*g_message ("waiting delete note on");*/
300   zix_sem_wait (&self->access_sem);
301 
302   MidiEvent * ev, * ev2, * next_ev;
303   int match = 0;
304   for (int i = queued ?
305          self->num_queued_events - 1 :
306          self->num_events - 1;
307        i >= 0; i--)
308     {
309       ev = queued ?
310         &self->queued_events[i] :
311         &self->events[i];
312       if (ev->type == MIDI_EVENT_TYPE_NOTE_ON &&
313           ev->note_pitch == note)
314         {
315           match = 1;
316 
317           if (queued)
318             --self->num_queued_events;
319           else
320             --self->num_events;
321 
322           for (int ii = i;
323                ii < queued ?
324                  self->num_queued_events :
325                  self->num_events;
326                ii++)
327             {
328               if (queued)
329                 {
330                   ev2 = &self->queued_events[ii];
331                   next_ev =
332                     &self->queued_events[ii + 1];
333                 }
334               else
335                 {
336                   ev2 = &self->events[ii];
337                   next_ev =
338                     &self->events[ii + 1];
339                 }
340               midi_event_copy (ev2, next_ev);
341             }
342         }
343     }
344 
345   zix_sem_post (&self->access_sem);
346 
347   return match;
348 }
349 
350 /**
351  * Inits the MidiEvents struct.
352  */
353 void
midi_events_init(MidiEvents * self)354 midi_events_init (
355   MidiEvents * self)
356 {
357   self->num_events = 0;
358   self->num_queued_events = 0;
359 
360   zix_sem_init (&self->access_sem, 1);
361 }
362 
363 /**
364  * Allocates and inits a MidiEvents struct.
365  */
366 MidiEvents *
midi_events_new(void)367 midi_events_new (void)
368 {
369   MidiEvents * self = object_new (MidiEvents);
370 
371   midi_events_init (self);
372 
373   return self;
374 }
375 
376 /**
377  * Returrns if the MidiEvents have any note on
378  * events.
379  *
380  * @param check_main Check the main events.
381  * @param check_queued Check the queued events.
382  */
383 int
midi_events_has_note_on(MidiEvents * self,int check_main,int check_queued)384 midi_events_has_note_on (
385   MidiEvents * self,
386   int          check_main,
387   int          check_queued)
388 {
389   if (check_main)
390     {
391       for (int i = 0; i < self->num_events; i++)
392         {
393           if (self->events[i].type ==
394                 MIDI_EVENT_TYPE_NOTE_ON)
395             return 1;
396         }
397     }
398   if (check_queued)
399     {
400       for (int i = 0;
401            i < self->num_queued_events; i++)
402         {
403           if (self->queued_events[i].type ==
404                 MIDI_EVENT_TYPE_NOTE_ON)
405             return 1;
406         }
407     }
408 
409   return 0;
410 }
411 
412 /**
413  * Copies the queue contents to the original struct
414  */
415 REALTIME
416 NONNULL
417 void
midi_events_dequeue(MidiEvents * self)418 midi_events_dequeue (
419   MidiEvents * self)
420 {
421   /*g_message ("waiting dequeue");*/
422   zix_sem_wait (&self->access_sem);
423 
424   MidiEvent * ev, * q_ev;
425   for (int i = 0;
426        i < self->num_queued_events; i++)
427     {
428       q_ev = &self->queued_events[i];
429       ev = &self->events[i];
430 
431       midi_event_copy (ev, q_ev);
432     }
433 
434   self->num_events = self->num_queued_events;
435   self->num_queued_events = 0;
436 
437   zix_sem_post (&self->access_sem);
438   /*g_message ("posted dequeue");*/
439 }
440 
441 /**
442  * Queues MIDI note off to event queue.
443  */
444 void
midi_events_add_all_notes_off(MidiEvents * self,midi_byte_t channel,midi_time_t time,bool queued)445 midi_events_add_all_notes_off (
446   MidiEvents * self,
447   midi_byte_t  channel,
448   midi_time_t  time,
449   bool         queued)
450 {
451   MidiEvent * ev;
452   if (queued)
453     ev =
454       &self->queued_events[self->num_queued_events];
455   else
456     ev =
457       &self->events[self->num_events];
458 
459   ev->type = MIDI_EVENT_TYPE_ALL_NOTES_OFF;
460   ev->channel = channel;
461   ev->time = time;
462   ev->raw_buffer[0] =
463     (midi_byte_t)
464     (MIDI_CH1_CTRL_CHANGE | (channel - 1));
465   ev->raw_buffer[1] = MIDI_ALL_NOTES_OFF;
466   ev->raw_buffer[2] = 0x00;
467 
468   if (queued)
469     self->num_queued_events++;
470   else
471     self->num_events++;
472 }
473 
474 void
midi_events_panic(MidiEvents * self,bool queued)475 midi_events_panic (
476   MidiEvents * self,
477   bool         queued)
478 {
479   zix_sem_wait (&self->access_sem);
480   /*g_message ("sending PANIC");*/
481   for (midi_byte_t i = 0; i < 16; i++)
482     {
483       midi_events_add_all_notes_off (
484         self, i, 0, queued);
485     }
486   zix_sem_post (&self->access_sem);
487 }
488 
489 static int
sort_events_func(const void * _a,const void * _b)490 sort_events_func (
491   const void * _a, const void * _b)
492 {
493   MidiEvent * a = (MidiEvent *) _a;
494   MidiEvent * b = (MidiEvent *) _b;
495 
496   /* if same time put note ons first */
497   if (a->time == b->time)
498     {
499       return
500         a->type == MIDI_EVENT_TYPE_NOTE_ON ?
501           -1 : 1;
502     }
503 
504   return (int) a->time - (int) b->time;
505 }
506 
507 /**
508  * Sorts the MIDI events by time ascendingly.
509  */
510 void
midi_events_sort_by_time(MidiEvents * self)511 midi_events_sort_by_time (
512   MidiEvents * self)
513 {
514   qsort (
515     self->events, (size_t) self->num_events,
516     sizeof (MidiEvent), sort_events_func);
517 }
518 
519 #ifdef HAVE_JACK
520 /**
521  * Writes the events to the given JACK buffer.
522  */
523 void
midi_events_copy_to_jack(MidiEvents * self,void * buff)524 midi_events_copy_to_jack (
525   MidiEvents * self,
526   void *       buff)
527 {
528   jack_midi_clear_buffer (buff);
529 
530   MidiEvent * ev;
531   jack_midi_data_t midi_data[3];
532   for (int i = 0; i < self->num_events; i++)
533     {
534       ev = &self->events[i];
535 
536       for (size_t j = 0; j < ev->raw_buffer_sz;
537            j++)
538         {
539           midi_data[j] = ev->raw_buffer[j];
540         }
541       jack_midi_event_write (
542         buff, ev->time, midi_data,
543         ev->raw_buffer_sz);
544 #if 0
545       g_message (
546         "wrote MIDI event to JACK MIDI out at %d",
547         ev->time);
548 #endif
549     }
550 }
551 #endif
552 
553 /**
554  * Adds a note off event to the given MidiEvents.
555  * FIXME should be wrapped in access sem?
556  *
557  * @param channel MIDI channel starting from 1.
558  * @param queued Add to queued events instead.
559  */
560 void
midi_events_add_note_off(MidiEvents * self,midi_byte_t channel,midi_byte_t note_pitch,midi_time_t time,int queued)561 midi_events_add_note_off (
562   MidiEvents * self,
563   midi_byte_t  channel,
564   midi_byte_t  note_pitch,
565   midi_time_t  time,
566   int          queued)
567 {
568   MidiEvent * ev;
569   if (queued)
570     ev =
571       &self->queued_events[self->num_queued_events];
572   else
573     ev =
574       &self->events[self->num_events];
575 
576   ev->type = MIDI_EVENT_TYPE_NOTE_OFF;
577   ev->channel = channel;
578   ev->note_pitch = note_pitch;
579   ev->time = time;
580   ev->raw_buffer[0] =
581     (midi_byte_t)
582     (MIDI_CH1_NOTE_OFF | (channel - 1));
583   ev->raw_buffer[1] = note_pitch;
584   ev->raw_buffer[2] = 90;
585   ev->raw_buffer_sz = 3;
586 
587   if (queued)
588     self->num_queued_events++;
589   else
590     self->num_events++;
591 }
592 
593 void
midi_events_add_raw(MidiEvents * self,uint8_t * buf,size_t buf_sz,midi_time_t time,bool queued)594 midi_events_add_raw (
595   MidiEvents * self,
596   uint8_t *    buf,
597   size_t       buf_sz,
598   midi_time_t  time,
599   bool         queued)
600 {
601   if (buf_sz > 3)
602     {
603       print_unknown_event_message (buf, buf_sz);
604       g_return_if_reached ();
605     }
606 
607   MidiEvent * ev;
608   if (queued)
609     ev =
610       &self->queued_events[self->num_queued_events];
611   else
612     ev =
613       &self->events[self->num_events];
614 
615   ev->type = MIDI_EVENT_TYPE_RAW;
616   ev->channel = 0;
617   ev->controller = 0;
618   ev->control = 0;
619   ev->time = time;
620   for (size_t i = 0; i < buf_sz; i++)
621     {
622       ev->raw_buffer[i] = buf[i];
623     }
624 
625   if (queued)
626     self->num_queued_events++;
627   else
628     self->num_events++;
629 }
630 
631 /**
632  * Adds a control event to the given MidiEvents.
633  *
634  * @param channel MIDI channel starting from 1.
635  * @param queued Add to queued events instead.
636  */
637 void
midi_events_add_control_change(MidiEvents * self,uint8_t channel,uint8_t controller,uint8_t control,midi_time_t time,int queued)638 midi_events_add_control_change (
639   MidiEvents * self,
640   uint8_t      channel,
641   uint8_t      controller,
642   uint8_t      control,
643   midi_time_t  time,
644   int          queued)
645 {
646   MidiEvent * ev;
647   if (queued)
648     ev =
649       &self->queued_events[self->num_queued_events];
650   else
651     ev =
652       &self->events[self->num_events];
653 
654   ev->type = MIDI_EVENT_TYPE_CONTROLLER;
655   ev->channel = channel;
656   ev->controller = controller;
657   ev->control = control;
658   ev->time = time;
659   ev->raw_buffer[0] =
660     (midi_byte_t)
661     (MIDI_CH1_CTRL_CHANGE | (channel - 1));
662   ev->raw_buffer[1] = controller;
663   ev->raw_buffer[2] = control;
664   ev->raw_buffer_sz = 3;
665 
666   if (queued)
667     self->num_queued_events++;
668   else
669     self->num_events++;
670 }
671 
672 /**
673  * Adds a control event to the given MidiEvents.
674  *
675  * @param channel MIDI channel starting from 1.
676  * @param pitchbend -8192 to 8191
677  * @param queued Add to queued events instead.
678  */
679 void
midi_events_add_pitchbend(MidiEvents * self,midi_byte_t channel,int pitchbend,midi_time_t time,int queued)680 midi_events_add_pitchbend (
681   MidiEvents * self,
682   midi_byte_t  channel,
683   int          pitchbend,
684   midi_time_t  time,
685   int          queued)
686 {
687   MidiEvent * ev;
688   if (queued)
689     ev =
690       &self->queued_events[self->num_queued_events];
691   else
692     ev =
693       &self->events[self->num_events];
694 
695   ev->type = MIDI_EVENT_TYPE_PITCHBEND;
696   ev->pitchbend = pitchbend;
697   ev->time = time;
698   ev->raw_buffer[0] =
699     (midi_byte_t)
700     (MIDI_CH1_PITCH_WHEEL_RANGE | (channel - 1));
701   midi_get_bytes_from_int (
702     pitchbend + 8192, &ev->raw_buffer[1],
703     &ev->raw_buffer[2]);
704   ev->raw_buffer_sz = 3;
705 
706   if (queued)
707     self->num_queued_events++;
708   else
709     self->num_events++;
710 }
711 
712 HOT
713 static int
midi_event_cmpfunc(const void * _a,const void * _b)714 midi_event_cmpfunc (
715   const void * _a,
716   const void * _b)
717 {
718   const MidiEvent * a =
719     (MidiEvent const *) _a;
720   const MidiEvent * b =
721     (MidiEvent const *) _b;
722   if (a->time == b->time)
723     {
724       return (int) a->type - (int) b->type;
725     }
726   return (int) a->time - (int) b->time;
727 }
728 
729 /**
730  * Sorts the MidiEvents by time.
731  */
732 void
midi_events_sort(MidiEvents * self,const bool queued)733 midi_events_sort (
734   MidiEvents * self,
735   const bool   queued)
736 {
737   MidiEvent * events;
738   size_t num_events;
739   if (queued)
740     {
741       events = self->queued_events;
742       num_events = (size_t) self->num_queued_events;
743     }
744   else
745     {
746       events = self->events;
747       num_events = (size_t) self->num_events;
748     }
749   qsort (
750     events, num_events, sizeof (MidiEvent),
751     midi_event_cmpfunc);
752 }
753 
754 /**
755  * Adds a note on event to the given MidiEvents.
756  *
757  * @param channel MIDI channel starting from 1.
758  * @param queued Add to queued events instead.
759  */
760 void
midi_events_add_note_on(MidiEvents * self,uint8_t channel,uint8_t note_pitch,uint8_t velocity,midi_time_t time,int queued)761 midi_events_add_note_on (
762   MidiEvents * self,
763   uint8_t      channel,
764   uint8_t      note_pitch,
765   uint8_t      velocity,
766   midi_time_t  time,
767   int          queued)
768 {
769 #if 0
770   g_message (
771     "%s: ch %"PRIu8", pitch %"PRIu8", vel %"PRIu8
772     ", time %"PRIu32,
773     __func__, channel, note_pitch, velocity, time);
774 #endif
775 
776   MidiEvent * ev;
777   if (queued)
778     ev =
779       &self->queued_events[self->num_queued_events];
780   else
781     ev =
782       &self->events[self->num_events];
783 
784   ev->type = MIDI_EVENT_TYPE_NOTE_ON;
785   ev->channel = channel;
786   ev->note_pitch = note_pitch;
787   ev->velocity = velocity;
788   ev->time = time;
789   ev->raw_buffer[0] =
790     (midi_byte_t)
791     (MIDI_CH1_NOTE_ON | (channel - 1));
792   ev->raw_buffer[1] = note_pitch;
793   ev->raw_buffer[2] = velocity;
794   ev->raw_buffer_sz = 3;
795 
796   if (queued)
797     self->num_queued_events++;
798   else
799     self->num_events++;
800 }
801 
802 /**
803  * Adds a note on for each note in the chord.
804  */
805 void
midi_events_add_note_ons_from_chord_descr(MidiEvents * self,ChordDescriptor * descr,midi_byte_t channel,midi_byte_t velocity,midi_time_t _time,bool queued)806 midi_events_add_note_ons_from_chord_descr (
807   MidiEvents *      self,
808   ChordDescriptor * descr,
809   midi_byte_t       channel,
810   midi_byte_t       velocity,
811   midi_time_t       _time,
812   bool              queued)
813 {
814 #if 0
815   g_message (
816     "%s: vel %"PRIu8", time %"PRIu32,
817     __func__, velocity, _time);
818 #endif
819 
820   for (int i = 0; i < CHORD_DESCRIPTOR_MAX_NOTES;
821        i++)
822     {
823       if (descr->notes[i])
824         {
825           midi_events_add_note_on (
826             self, channel, i + 36,
827             velocity, _time, queued);
828         }
829     }
830 }
831 
832 /**
833  * Adds a note off for each note in the chord.
834  */
835 void
midi_events_add_note_offs_from_chord_descr(MidiEvents * self,ChordDescriptor * descr,midi_byte_t channel,midi_time_t time,bool queued)836 midi_events_add_note_offs_from_chord_descr (
837   MidiEvents *      self,
838   ChordDescriptor * descr,
839   midi_byte_t       channel,
840   midi_time_t       time,
841   bool              queued)
842 {
843   for (int i = 0; i < CHORD_DESCRIPTOR_MAX_NOTES;
844        i++)
845     {
846       if (descr->notes[i])
847         {
848           midi_events_add_note_off (
849             self, channel, i + 36, time, queued);
850         }
851     }
852 }
853 
854 /**
855  * Parses a MidiEvent from a raw MIDI buffer.
856  *
857  * This must be a full 3-byte message. If in
858  * 'running status' mode, the caller is responsible
859  * for prepending the status byte.
860  */
861 REALTIME
862 void
midi_events_add_event_from_buf(MidiEvents * self,midi_time_t time,midi_byte_t * buf,int buf_size,int queued)863 midi_events_add_event_from_buf (
864   MidiEvents *  self,
865   midi_time_t   time,
866   midi_byte_t * buf,
867   int           buf_size,
868   int           queued)
869 {
870 #if 0
871   if (buf_size != 3)
872     {
873       g_debug (
874         "buf size of %d received (%"PRIu8" %"
875         PRIu8" %"PRIu8"), expected 3, skipping...",
876         buf_size > 0 ? buf[0] : 0,
877         buf_size > 1 ? buf[1] : 0,
878         buf_size > 2 ? buf[2] : 0, buf_size);
879     }
880 #endif
881 
882   midi_byte_t type = buf[0] & 0xf0;
883   midi_byte_t channel =
884     (midi_byte_t) ((buf[0] & 0xf) + 1);
885   switch (type)
886     {
887     case MIDI_CH1_NOTE_ON:
888       /* velocity == 0 means note off */
889       if (buf[2] == 0)
890         goto note_off;
891 
892       midi_events_add_note_on (
893         self, channel, buf[1], buf[2], time,
894         queued);
895       break;
896     case MIDI_CH1_NOTE_OFF:
897 note_off:
898       midi_events_add_note_off (
899         self, channel, buf[1], time, queued);
900       break;
901     case MIDI_CH1_PITCH_WHEEL_RANGE:
902       midi_events_add_pitchbend (
903         self, channel,
904         midi_combine_bytes_to_int (buf[1], buf[2]),
905         time, queued);
906       break;
907     case MIDI_SYSTEM_MESSAGE:
908       /* ignore active sensing */
909       if (buf[0] != 0xFE)
910         {
911 #if 0
912           print_unknown_event_message (
913             buf, buf_size);
914 #endif
915         }
916       break;
917     case MIDI_CH1_CTRL_CHANGE:
918       midi_events_add_control_change (
919         self, 1, buf[1], buf[2], time, queued);
920       break;
921     default:
922       midi_events_add_raw (
923         self, buf, (size_t) buf_size, time, queued);
924       break;
925     }
926 }
927 
928 void
midi_events_delete_event(MidiEvents * self,const MidiEvent * ev,const bool queued)929 midi_events_delete_event (
930   MidiEvents *      self,
931   const MidiEvent * ev,
932   const bool        queued)
933 {
934   MidiEvent * arr =
935     queued ?
936       self->queued_events :
937       self->events;
938 #define NUM_EVENTS \
939   (queued ? self->num_queued_events : \
940    self->num_events)
941 
942   for (int i = 0; i < NUM_EVENTS; i++)
943     {
944       MidiEvent * cur_ev = &arr[i];
945       if (cur_ev == ev)
946         {
947           for (int k = i; k < NUM_EVENTS - 1; k++)
948             {
949               midi_event_copy (
950                 &arr[k + 1], &arr[k]);
951             }
952           if (queued)
953             self->num_queued_events--;
954           else
955             self->num_events--;
956           i--;
957         }
958     }
959 }
960 
961 void
midi_event_set_velocity(MidiEvent * ev,midi_byte_t vel)962 midi_event_set_velocity (
963   MidiEvent * ev,
964   midi_byte_t vel)
965 {
966   ev->velocity = vel;
967   ev->raw_buffer[2] = vel;
968 }
969 
970 void
midi_event_print(const MidiEvent * ev)971 midi_event_print (
972   const MidiEvent * ev)
973 {
974   char raw[300];
975   sprintf (raw, "Raw (%zu):", ev->raw_buffer_sz);
976   for (size_t i = 0; i < ev->raw_buffer_sz;
977        i++)
978     {
979       char part[20];
980       sprintf (
981         part, " %hhx", ev->raw_buffer[i]);
982       strcat (raw, part);
983     }
984 
985   char msg[600];
986   sprintf (
987     msg,
988     "~MIDI EVENT~\n"
989     "Type: %s\n"
990     "Channel: %u\n"
991     "Pitch: %u\n"
992     "Velocity: %u\n"
993     "Time: %u\n"
994     "%s",
995     midi_event_type_strings[ev->type], ev->channel,
996     ev->note_pitch,
997     ev->velocity, ev->time, raw);
998 
999   g_message ("%s", msg);
1000 }
1001 
1002 int
midi_events_are_equal(const MidiEvent * src,const MidiEvent * dest)1003 midi_events_are_equal (
1004   const MidiEvent * src,
1005   const MidiEvent * dest)
1006 {
1007   int ret =
1008     dest->type == src->type &&
1009     dest->pitchbend == src->pitchbend &&
1010     dest->controller == src->controller &&
1011     dest->control == src->control &&
1012     dest->channel == src->channel &&
1013     dest->note_pitch == src->note_pitch &&
1014     (src->type != MIDI_EVENT_TYPE_NOTE_ON ||
1015       (src->type == MIDI_EVENT_TYPE_NOTE_ON &&
1016        dest->velocity == src->velocity)) &&
1017     dest->time == src->time &&
1018     dest->raw_buffer[0] == src->raw_buffer[0] &&
1019     dest->raw_buffer[1] == src->raw_buffer[1] &&
1020     dest->raw_buffer[2] == src->raw_buffer[2];
1021   return ret;
1022 }
1023 
1024 void
midi_events_print(MidiEvents * self,const int queued)1025 midi_events_print (
1026   MidiEvents * self,
1027   const int    queued)
1028 {
1029   MidiEvent * arr =
1030     queued ?
1031       self->queued_events :
1032       self->events;
1033   MidiEvent * ev1;
1034 #define NUM_EVENTS \
1035   (queued ? self->num_queued_events : \
1036    self->num_events)
1037 
1038   int i;
1039   for (i = 0; i < NUM_EVENTS; i++)
1040     {
1041       ev1 = &arr[i];
1042       midi_event_print (ev1);
1043     }
1044 }
1045 
1046 /**
1047  * Clears duplicates.
1048  *
1049  * @param queued Clear duplicates from queued events
1050  * instead.
1051  */
1052 void
midi_events_clear_duplicates(MidiEvents * self,const int queued)1053 midi_events_clear_duplicates (
1054   MidiEvents * self,
1055   const int    queued)
1056 {
1057   MidiEvent * arr =
1058     queued ?
1059       self->queued_events :
1060       self->events;
1061   MidiEvent * ev1, * ev2;
1062 #define NUM_EVENTS \
1063   (queued ? self->num_queued_events : \
1064    self->num_events)
1065 
1066   int i, j, k;
1067   for (i = 0; i < NUM_EVENTS; i++)
1068     {
1069       ev1 = &arr[i];
1070 
1071       for (j = i + 1; j < NUM_EVENTS; j++)
1072         {
1073           ev2 = &arr[j];
1074 
1075           if (midi_events_are_equal (ev1, ev2))
1076             {
1077 #if 0
1078               g_message (
1079                 "removing duplicate MIDI event");
1080 #endif
1081               for (k = j; k < NUM_EVENTS; k++)
1082                 {
1083                   midi_event_copy (
1084                     &arr[k], &arr[k + 1]);
1085                 }
1086               if (queued)
1087                 self->num_queued_events--;
1088               else
1089                 self->num_events--;
1090               j--;
1091             }
1092         }
1093     }
1094 }
1095 
1096 /**
1097  * Frees the MIDI events.
1098  */
1099 void
midi_events_free(MidiEvents * self)1100 midi_events_free (
1101   MidiEvents * self)
1102 {
1103   zix_sem_destroy (&self->access_sem);
1104 
1105   object_zero_and_free (self);
1106 }
1107