1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU 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  * GSequencer 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 General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <ags/audio/midi/ags_midi_buffer_util.h>
21 
22 #include <alsa/seq_midi_event.h>
23 #include <alsa/seq_event.h>
24 
25 #include <math.h>
26 #include <string.h>
27 #include <stdlib.h>
28 
29 gpointer ags_midi_buffer_util_copy(gpointer ptr);
30 void ags_midi_buffer_util_free(gpointer ptr);
31 
32 /**
33  * SECTION:ags_midi_buffer_util
34  * @short_description: MIDI buffer util
35  * @title: AgsMidiBufferUtil
36  * @section_id:
37  * @include: ags/audio/midi/ags_midi_buffer_util.h
38  *
39  * Utility functions for MIDI buffers.
40  */
41 
42 GType
ags_midi_buffer_util_get_type(void)43 ags_midi_buffer_util_get_type(void)
44 {
45   static volatile gsize g_define_type_id__volatile = 0;
46 
47   if(g_once_init_enter (&g_define_type_id__volatile)){
48     GType ags_type_midi_buffer_util = 0;
49 
50     ags_type_midi_buffer_util =
51       g_boxed_type_register_static("AgsMidiBufferUtil",
52 				   (GBoxedCopyFunc) ags_midi_buffer_util_copy,
53 				   (GBoxedFreeFunc) ags_midi_buffer_util_free);
54 
55     g_once_init_leave(&g_define_type_id__volatile, ags_type_midi_buffer_util);
56   }
57 
58   return g_define_type_id__volatile;
59 }
60 
61 gpointer
ags_midi_buffer_util_copy(gpointer ptr)62 ags_midi_buffer_util_copy(gpointer ptr)
63 {
64   gpointer retval;
65 
66   retval = g_memdup(ptr, sizeof(AgsMidiBufferUtil));
67 
68   return(retval);
69 }
70 
71 void
ags_midi_buffer_util_free(gpointer ptr)72 ags_midi_buffer_util_free(gpointer ptr)
73 {
74   g_free(ptr);
75 }
76 
77 /**
78  * ags_midi_buffer_util_get_varlength_size:
79  * @varlength: the variable length
80  *
81  * Retrieve the size needed to store the variable length.
82  *
83  * Returns: the size needed to be allocated
84  *
85  * Since: 3.0.0
86  */
87 guint
ags_midi_buffer_util_get_varlength_size(glong varlength)88 ags_midi_buffer_util_get_varlength_size(glong varlength)
89 {
90   guint current;
91   guchar c;
92   guint i;
93   glong mask;
94 
95   /* retrieve new size */
96   mask = 0x7f;
97 
98   current = 8 * 4 - 4;
99   i = current;
100 
101   for(; current >= 8; ){
102     if(((mask << (i - 7)) & varlength) != 0){
103       break;
104     }
105 
106     i -= 7;
107     current -= 8;
108   }
109 
110   return(floor(current / 8.0) + 1);
111 }
112 
113 /**
114  * ags_midi_buffer_util_put_varlength:
115  * @buffer: the character buffer
116  * @varlength: the value to put
117  *
118  * Put the variable lenght value to @buffer.
119  *
120  * Since: 3.0.0
121  */
122 void
ags_midi_buffer_util_put_varlength(guchar * buffer,glong varlength)123 ags_midi_buffer_util_put_varlength(guchar *buffer,
124 				   glong varlength)
125 {
126   guint varlength_size;
127   guint i, j;
128   glong mask;
129 
130   if(buffer == NULL){
131     return;
132   }
133 
134   varlength_size = ags_midi_buffer_util_get_varlength_size(varlength);
135 
136   /* write to internal buffer */
137   mask = 0x7f;
138   j = 0;
139   i = 7 * varlength_size;
140 
141   for(; j < varlength_size; ){
142     buffer[j] = ((mask << (i - 7)) & varlength) >> (i - 7);
143 
144     if(j + 1 < varlength_size){
145       buffer[j] |= 0x80;
146     }
147 
148     i -= 7;
149     j++;
150   }
151 }
152 
153 /**
154  * ags_midi_buffer_util_get_varlength:
155  * @buffer: the character buffer
156  * @varlength: the return location
157  *
158  * Get the variable lenght value from @buffer.
159  *
160  * Returns: the number of bytes read.
161  *
162  * Since: 3.0.0
163  */
164 guint
ags_midi_buffer_util_get_varlength(guchar * buffer,glong * varlength)165 ags_midi_buffer_util_get_varlength(guchar *buffer,
166 				   glong *varlength)
167 {
168   glong value;
169   guint i;
170   char c;
171 
172   if(buffer == NULL){
173     if(varlength != NULL){
174       *varlength = 0;
175     }
176 
177     return(0);
178   }
179 
180   c = buffer[0];
181   value = c;
182   i = 1;
183 
184   if(c & 0x80){
185     value &= 0x7F;
186 
187     do{
188       value = (value << 7) + ((c = buffer[i]) & 0x7F);
189       i++;
190     }while(c & 0x80);
191   }
192 
193   if(varlength != NULL){
194     *varlength = value;
195   }
196 
197   return(i);
198 }
199 
200 /**
201  * ags_midi_buffer_util_put_int16:
202  * @buffer: the character buffer
203  * @val: the integer
204  *
205  * Put signed 16 bit integer.
206  *
207  * Since: 3.0.0
208  */
209 void
ags_midi_buffer_util_put_int16(guchar * buffer,glong val)210 ags_midi_buffer_util_put_int16(guchar *buffer,
211 			       glong val)
212 {
213   if(buffer == NULL){
214     return;
215   }
216 
217   buffer[0] = (val & (0xff << 8)) >> 8;
218   buffer[1] = val & 0xff;
219 }
220 
221 /**
222  * ags_midi_buffer_util_get_int16:
223  * @buffer: the character buffer
224  * @val: return location of the integer
225  *
226  * Get signed 32 bit integer.
227  *
228  * Since: 3.0.0
229  */
230 void
ags_midi_buffer_util_get_int16(guchar * buffer,glong * val)231 ags_midi_buffer_util_get_int16(guchar *buffer,
232 			       glong *val)
233 {
234   glong tmp;
235 
236   if(buffer == NULL){
237     if(val != NULL){
238       *val = 0;
239     }
240 
241     return;
242   }
243 
244   tmp = (buffer[0] & 0xff);
245   tmp = (tmp << 8) + (buffer[1] & 0xff);
246 
247   if(val != NULL){
248     *val = tmp;
249   }
250 }
251 
252 /**
253  * ags_midi_buffer_util_put_int24:
254  * @buffer: the character buffer
255  * @val: the integer
256  *
257  * Put signed 24 bit integer.
258  *
259  * Since: 3.0.0
260  */
261 void
ags_midi_buffer_util_put_int24(guchar * buffer,glong val)262 ags_midi_buffer_util_put_int24(guchar *buffer,
263 			       glong val)
264 {
265   if(buffer == NULL){
266     return;
267   }
268 
269   buffer[0] = (val & (0xff << 16)) >> 16;
270   buffer[1] = (val & (0xff << 8)) >> 8;
271   buffer[2] = val & 0xff;
272 }
273 
274 /**
275  * ags_midi_buffer_util_get_int24:
276  * @buffer: the character buffer
277  * @val: return location of the integer
278  *
279  * Get signed 24 bit integer.
280  *
281  * Since: 3.0.0
282  */
283 void
ags_midi_buffer_util_get_int24(guchar * buffer,glong * val)284 ags_midi_buffer_util_get_int24(guchar *buffer,
285 			       glong *val)
286 {
287   glong tmp;
288 
289   if(buffer == NULL){
290     if(val != NULL){
291       *val = 0;
292     }
293 
294     return;
295   }
296 
297   tmp = (buffer[0] & 0xff);
298   tmp = (tmp << 8) + (buffer[1] & 0xff);
299   tmp = (tmp << 8) + (buffer[2] & 0xff);
300 
301   if(val != NULL){
302     *val = tmp;
303   }
304 }
305 
306 /**
307  * ags_midi_buffer_util_put_int32:
308  * @buffer: the character buffer
309  * @val: the integer
310  *
311  * Put signed 32 bit integer.
312  *
313  * Since: 3.0.0
314  */
315 void
ags_midi_buffer_util_put_int32(guchar * buffer,glong val)316 ags_midi_buffer_util_put_int32(guchar *buffer,
317 			       glong val)
318 {
319   if(buffer == NULL){
320     return;
321   }
322 
323   buffer[0] = (val & (0xff << 24)) >> 24;
324   buffer[1] = (val & (0xff << 16)) >> 16;
325   buffer[2] = (val & (0xff << 8)) >> 8;
326   buffer[3] = val & 0xff;
327 }
328 
329 /**
330  * ags_midi_buffer_util_get_int32:
331  * @buffer: the character buffer
332  * @val: return location of the integer
333  *
334  * Get signed 32 bit integer.
335  *
336  * Since: 3.0.0
337  */
338 void
ags_midi_buffer_util_get_int32(guchar * buffer,glong * val)339 ags_midi_buffer_util_get_int32(guchar *buffer,
340 			       glong *val)
341 {
342   glong tmp;
343 
344   if(buffer == NULL){
345     if(val != NULL){
346       *val = 0;
347     }
348 
349     return;
350   }
351 
352   tmp = (buffer[0] & 0xff);
353   tmp = (tmp << 8) + (buffer[1] & 0xff);
354   tmp = (tmp << 8) + (buffer[2] & 0xff);
355   tmp = (tmp << 8) + (buffer[3] & 0xff);
356 
357   if(val != NULL){
358     *val = tmp;
359   }
360 }
361 
362 /**
363  * ags_midi_buffer_util_put_header:
364  * @buffer: the character buffer
365  * @offset: start delta-time
366  * @format: either 0, 1 or 2.
367  * @track_count: the number of tracks
368  * @division: timing division
369  *
370  * Puts the midi header.
371  *
372  * Since: 3.0.0
373  */
374 void
ags_midi_buffer_util_put_header(guchar * buffer,glong offset,glong format,glong track_count,glong division)375 ags_midi_buffer_util_put_header(guchar *buffer,
376 				glong offset, glong format,
377 				glong track_count, glong division)
378 {
379   static gchar header[] = "MThd";
380 
381   if(buffer == NULL){
382     return;
383   }
384 
385   /* put MThd */
386   memcpy(buffer, header, 4 * sizeof(guchar));
387 
388   /* chunk length */
389   ags_midi_buffer_util_put_int32(buffer + 4,
390 				 offset);
391 
392   /* format */
393   ags_midi_buffer_util_put_int16(buffer + 8,
394 				 format);
395 
396   /* track count */
397   ags_midi_buffer_util_put_int16(buffer + 10,
398 				 track_count);
399 
400   /* division */
401   ags_midi_buffer_util_put_int16(buffer + 12,
402 				 division);
403 }
404 
405 /**
406  * ags_midi_buffer_util_get_header:
407  * @buffer: the character buffer
408  * @offset: start delta-time
409  * @format: either 0, 1 or 2.
410  * @track_count: the number of tracks
411  * @division: timing division
412  *
413  * Gets the midi header
414  *
415  * Returns: the number of bytes read.
416  *
417  * Since: 3.0.0
418  */
419 guint
ags_midi_buffer_util_get_header(guchar * buffer,glong * offset,glong * format,glong * track_count,glong * division)420 ags_midi_buffer_util_get_header(guchar *buffer,
421 				glong *offset, glong *format,
422 				glong *track_count, glong *division)
423 {
424   static gchar header[] = "MThd";
425 
426   if(buffer == NULL ||
427      (!g_ascii_strncasecmp(buffer,
428 			   header,
429 			   4)) == FALSE){
430     if(offset != NULL){
431       *offset = 0;
432     }
433 
434     if(format != NULL){
435       *format = 0;
436     }
437 
438     if(track_count != NULL){
439       *track_count = 0;
440     }
441 
442     if(division != NULL){
443       *division = 0;
444     }
445 
446     return(0);
447   }
448 
449   /* offset */
450   ags_midi_buffer_util_get_int32(buffer + 4,
451 				 offset);
452 
453   /* format */
454   ags_midi_buffer_util_get_int16(buffer + 8,
455 				 format);
456 
457   /* track count */
458   ags_midi_buffer_util_get_int16(buffer + 10,
459 				 track_count);
460 
461   /* division */
462   ags_midi_buffer_util_get_int16(buffer + 12,
463 				 division);
464 
465   return(14);
466 }
467 
468 /**
469  * ags_midi_buffer_util_put_track:
470  * @buffer: the midi buffer
471  * @offset: start delta-time
472  *
473  * Put track.
474  *
475  * Since: 3.0.0
476  */
477 void
ags_midi_buffer_util_put_track(guchar * buffer,glong offset)478 ags_midi_buffer_util_put_track(guchar *buffer,
479 			       glong offset)
480 {
481   static gchar track[] = "MTrk";
482 
483   if(buffer == NULL){
484     return;
485   }
486 
487   /* put MTrk */
488   memcpy(buffer, track, 4 * sizeof(guchar));
489 
490   /* offset */
491   ags_midi_buffer_util_put_int32(buffer + 4,
492 				 offset);
493 }
494 
495 /**
496  * ags_midi_buffer_util_get_track:
497  * @buffer: the midi buffer
498  * @offset: start delta-time
499  *
500  * Get track
501  *
502  * Returns: the number of bytes read.
503  *
504  * Since: 3.0.0
505  */
506 guint
ags_midi_buffer_util_get_track(guchar * buffer,glong * offset)507 ags_midi_buffer_util_get_track(guchar *buffer,
508 			       glong *offset)
509 {
510   static gchar track[] = "MTrk";
511 
512   if(buffer == NULL ||
513      (!g_ascii_strncasecmp(buffer,
514 			   track,
515 			   4)) == FALSE){
516     if(offset != NULL){
517       *offset = 0;
518     }
519 
520     return(0);
521   }
522 
523   /* offset */
524   ags_midi_buffer_util_get_int32(buffer + 4,
525 				 offset);
526 
527   return(8);
528 }
529 
530 /**
531  * ags_midi_buffer_util_put_key_on:
532  * @buffer: the character buffer
533  * @delta_time: timing information
534  * @channel: valid channels from 0-15
535  * @key: valid keys to play 0-128
536  * @velocity: the key dynamics
537  *
538  * Puts the given values to @buffer with appropriate channel message.
539  *
540  * Since: 3.0.0
541  */
542 void
ags_midi_buffer_util_put_key_on(guchar * buffer,glong delta_time,glong channel,glong key,glong velocity)543 ags_midi_buffer_util_put_key_on(guchar *buffer,
544 				glong delta_time,
545 				glong channel,
546 				glong key,
547 				glong velocity)
548 {
549   guint delta_time_size;
550 
551   if(buffer == NULL){
552     return;
553   }
554 
555   /* delta time */
556   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
557   ags_midi_buffer_util_put_varlength(buffer,
558 				     delta_time);
559 
560   /* key-on channel message */
561   buffer[delta_time_size] = 0x90 | (channel & 0xf);
562 
563   /* key */
564   buffer[delta_time_size + 1] = key & 0x7f;
565 
566   /* velocity */
567   buffer[delta_time_size + 2] = velocity & 0x7f;
568 }
569 
570 /**
571  * ags_midi_buffer_util_get_key_on:
572  * @buffer: the character buffer
573  * @delta_time: the return location of timing information
574  * @channel: the return location of channel
575  * @key: the return location of key
576  * @velocity: the return location of velocity
577  *
578  * Get the key-on message from @buffer.
579  *
580  * Returns: the number of bytes read.
581  *
582  * Since: 3.0.0
583  */
584 guint
ags_midi_buffer_util_get_key_on(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * velocity)585 ags_midi_buffer_util_get_key_on(guchar *buffer,
586 				glong *delta_time,
587 				glong *channel,
588 				glong *key,
589 				glong *velocity)
590 {
591   glong val;
592   guint delta_time_size;
593 
594   if(buffer == NULL){
595     if(delta_time != NULL){
596       *delta_time = 0;
597     }
598 
599     if(channel != NULL){
600       *channel = 0;
601     }
602 
603     if(key != NULL){
604       *key = 0;
605     }
606 
607     if(velocity != NULL){
608       *velocity = 0;
609     }
610 
611     return(0);
612   }
613 
614   /* delta time */
615   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
616 						       &val);
617 
618   if(delta_time != NULL){
619     *delta_time = val;
620   }
621 
622   /* channel */
623   if(channel != NULL){
624     *channel = (0xf & buffer[delta_time_size]);
625   }
626 
627   /* key */
628   if(key != NULL){
629     *key = (0x7f & buffer[delta_time_size + 1]);
630   }
631 
632   /* velocity */
633   if(velocity != NULL){
634     *velocity = (0x7f & buffer[delta_time_size + 2]);
635   }
636 
637   return(delta_time_size + 3);
638 }
639 
640 /**
641  * ags_midi_buffer_util_put_key_off:
642  * @buffer: the character buffer
643  * @delta_time: timing information
644  * @channel: valid channels from 0-15
645  * @key: valid keys to play 0-128
646  * @velocity: the key dynamics
647  *
648  * Puts the given values to @buffer with appropriate channel message.
649  *
650  * Since: 3.0.0
651  */
652 void
ags_midi_buffer_util_put_key_off(guchar * buffer,glong delta_time,glong channel,glong key,glong velocity)653 ags_midi_buffer_util_put_key_off(guchar *buffer,
654 				 glong delta_time,
655 				 glong channel,
656 				 glong key,
657 				 glong velocity)
658 {
659   guint delta_time_size;
660 
661   if(buffer == NULL){
662     return;
663   }
664 
665   /* delta time */
666   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
667   ags_midi_buffer_util_put_varlength(buffer,
668 				     delta_time);
669 
670   /* key-off channel message */
671   buffer[delta_time_size] = 0x80;
672   buffer[delta_time_size] |= (channel & 0xf);
673 
674   /* key */
675   buffer[delta_time_size + 1] = key & 0x7f;
676 
677   /* velocity */
678   buffer[delta_time_size + 2] = velocity & 0x7f;
679 }
680 
681 /**
682  * ags_midi_buffer_util_get_key_off:
683  * @buffer: the character buffer
684  * @delta_time: the return location of timing information
685  * @channel: the return location of channel
686  * @key: the return location of key
687  * @velocity: the return location of velocity
688  *
689  * Get the key-off message from @buffer.
690  *
691  * Returns: the number of bytes read.
692  *
693  * Since: 3.0.0
694  */
695 guint
ags_midi_buffer_util_get_key_off(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * velocity)696 ags_midi_buffer_util_get_key_off(guchar *buffer,
697 				 glong *delta_time,
698 				 glong *channel,
699 				 glong *key,
700 				 glong *velocity)
701 {
702   glong val;
703   guint delta_time_size;
704 
705   if(buffer == NULL){
706     if(delta_time != NULL){
707       *delta_time = 0;
708     }
709 
710     if(channel != NULL){
711       *channel = 0;
712     }
713 
714     if(key != NULL){
715       *key = 0;
716     }
717 
718     if(velocity != NULL){
719       *velocity = 0;
720     }
721 
722     return(0);
723   }
724 
725   /* delta time */
726   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
727 						       &val);
728 
729   if(delta_time != NULL){
730     *delta_time = val;
731   }
732 
733   /* channel */
734   if(channel != NULL){
735     *channel = (0xf & buffer[delta_time_size]);
736   }
737 
738   /* key */
739   if(key != NULL){
740     *key = (0x7f & buffer[delta_time_size + 1]);
741   }
742 
743   /* velocity */
744   if(velocity != NULL){
745     *velocity = (0x7f & buffer[delta_time_size + 2]);
746   }
747 
748   return(delta_time_size + 3);
749 }
750 
751 /**
752  * ags_midi_buffer_util_put_key_pressure:
753  * @buffer: the character buffer
754  * @delta_time: timing information
755  * @channel: valid channels from 0-15
756  * @key: valid keys to play 0-128
757  * @pressure: the key dynamics
758  *
759  * Puts the given values to @buffer with appropriate channel message.
760  *
761  * Since: 3.0.0
762  */
763 void
ags_midi_buffer_util_put_key_pressure(guchar * buffer,glong delta_time,glong channel,glong key,glong pressure)764 ags_midi_buffer_util_put_key_pressure(guchar *buffer,
765 				      glong delta_time,
766 				      glong channel,
767 				      glong key,
768 				      glong pressure)
769 {
770   guint delta_time_size;
771 
772   if(buffer == NULL){
773     return;
774   }
775 
776   /* delta time */
777   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
778   ags_midi_buffer_util_put_varlength(buffer,
779 				     delta_time);
780 
781   /* key-pressure channel message */
782   buffer[delta_time_size] = 0xa0;
783   buffer[delta_time_size] |= (channel & 0xf);
784 
785   /* key */
786   buffer[delta_time_size + 1] = key & 0x7f;
787 
788   /* pressure */
789   buffer[delta_time_size + 2] = pressure & 0x7f;
790 }
791 
792 /**
793  * ags_midi_buffer_util_get_key_pressure:
794  * @buffer: the character buffer
795  * @delta_time: the return location of timing information
796  * @channel: the return location of channel
797  * @key: the return location of key
798  * @pressure: the return location of pressure
799  *
800  * Get the key-pressure message from @buffer.
801  *
802  * Returns: the number of bytes read.
803  *
804  * Since: 3.0.0
805  */
806 guint
ags_midi_buffer_util_get_key_pressure(guchar * buffer,glong * delta_time,glong * channel,glong * key,glong * pressure)807 ags_midi_buffer_util_get_key_pressure(guchar *buffer,
808 				      glong *delta_time,
809 				      glong *channel,
810 				      glong *key,
811 				      glong *pressure)
812 {
813   glong val;
814   guint delta_time_size;
815 
816   if(buffer == NULL){
817     if(delta_time != NULL){
818       *delta_time = 0;
819     }
820 
821     if(channel != NULL){
822       *channel = 0;
823     }
824 
825     if(key != NULL){
826       *key = 0;
827     }
828 
829     if(pressure != NULL){
830       *pressure = 0;
831     }
832 
833     return(0);
834   }
835 
836   /* delta time */
837   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
838 						       &val);
839 
840   if(delta_time != NULL){
841     *delta_time = val;
842   }
843 
844   /* channel */
845   if(channel != NULL){
846     *channel = (0xf & buffer[delta_time_size]);
847   }
848 
849   /* key */
850   if(key != NULL){
851     *key = (0x7f & buffer[delta_time_size + 1]);
852   }
853 
854   /* pressure */
855   if(pressure != NULL){
856     *pressure = (0x7f & buffer[delta_time_size + 2]);
857   }
858 
859   return(delta_time_size + 3);
860 }
861 
862 /**
863  * ags_midi_buffer_util_put_change_parameter:
864  * @buffer: the character buffer
865  * @delta_time: timing information
866  * @channel: channel
867  * @control: the control
868  * @value: the value
869  *
870  * Put change parameter.
871  *
872  * Since: 3.0.0
873  */
874 void
ags_midi_buffer_util_put_change_parameter(guchar * buffer,glong delta_time,glong channel,glong control,glong value)875 ags_midi_buffer_util_put_change_parameter(guchar *buffer,
876 					  glong delta_time,
877 					  glong channel,
878 					  glong control,
879 					  glong value)
880 {
881   guint delta_time_size;
882 
883   if(buffer == NULL){
884     return;
885   }
886 
887   /* delta time */
888   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
889   ags_midi_buffer_util_put_varlength(buffer,
890 				     delta_time);
891 
892   /* change-parameter channel message */
893   buffer[delta_time_size] = 0xb0;
894   buffer[delta_time_size] |= (channel & 0xf);
895 
896   /* control */
897   buffer[delta_time_size + 1] = 0x7f & control;
898 
899   /* value */
900   buffer[delta_time_size + 2] = 0x7f & value;
901 }
902 
903 /**
904  * ags_midi_buffer_util_get_change_parameter:
905  * @buffer: the character buffer
906  * @delta_time: the return location of timing information
907  * @channel: the return location of channel
908  * @control: the return location of the control
909  * @value: the return location the value
910  *
911  * Get change parameter.
912  *
913  * Returns: the number of bytes read.
914  *
915  * Since: 3.0.0
916  */
917 guint
ags_midi_buffer_util_get_change_parameter(guchar * buffer,glong * delta_time,glong * channel,glong * control,glong * value)918 ags_midi_buffer_util_get_change_parameter(guchar *buffer,
919 					  glong *delta_time,
920 					  glong *channel,
921 					  glong *control,
922 					  glong *value)
923 {
924   glong val;
925   guint delta_time_size;
926 
927   if(buffer == NULL){
928     if(delta_time != NULL){
929       *delta_time = 0;
930     }
931 
932     if(channel != NULL){
933       *channel = 0;
934     }
935 
936     if(control != NULL){
937       *control = 0;
938     }
939 
940     if(value != NULL){
941       *value = 0;
942     }
943 
944     return(0);
945   }
946 
947   /* delta time */
948   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
949 						       &val);
950 
951   if(delta_time != NULL){
952     *delta_time = val;
953   }
954 
955   /* channel */
956   if(channel != NULL){
957     *channel = (0xf & buffer[delta_time_size]);
958   }
959 
960   /* control */
961   if(control != NULL){
962     *control = 0x7f & buffer[delta_time_size + 1];
963   }
964 
965   /* value */
966   if(value != NULL){
967     *value = 0x7f & buffer[delta_time_size + 2];
968   }
969 
970   return(delta_time_size + 3);
971 }
972 
973 /**
974  * ags_midi_buffer_util_put_pitch_bend:
975  * @buffer: the character buffer
976  * @delta_time: timing information
977  * @channel: channel
978  * @pitch: the pitch
979  * @transmitter: the transmitter
980  *
981  * Put pitch bend.
982  *
983  * Since: 3.0.0
984  */
985 void
ags_midi_buffer_util_put_pitch_bend(guchar * buffer,glong delta_time,glong channel,glong pitch,glong transmitter)986 ags_midi_buffer_util_put_pitch_bend(guchar *buffer,
987 				    glong delta_time,
988 				    glong channel,
989 				    glong pitch,
990 				    glong transmitter)
991 {
992   guint delta_time_size;
993 
994   if(buffer == NULL){
995     return;
996   }
997 
998   /* delta time */
999   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1000   ags_midi_buffer_util_put_varlength(buffer,
1001 				     delta_time);
1002 
1003   /* pitch-bend channel message */
1004   buffer[delta_time_size] = 0xe0;
1005   buffer[delta_time_size] |= (channel & 0xf);
1006 
1007   /* pitch */
1008   buffer[delta_time_size + 1] = 0x7f & pitch;
1009 
1010   /* transmitter */
1011   buffer[delta_time_size + 2] = 0x7f & transmitter;
1012 }
1013 
1014 /**
1015  * ags_midi_buffer_util_get_pitch_bend:
1016  * @buffer: the character buffer
1017  * @delta_time: the return location of timing information
1018  * @channel: the return location of channel
1019  * @pitch: the return location of the pitch
1020  * @transmitter: the return location the transmitter
1021  *
1022  * Get pitch bend.
1023  *
1024  * Returns: the number of bytes read.
1025  *
1026  * Since: 3.0.0
1027  */
1028 guint
ags_midi_buffer_util_get_pitch_bend(guchar * buffer,glong * delta_time,glong * channel,glong * pitch,glong * transmitter)1029 ags_midi_buffer_util_get_pitch_bend(guchar *buffer,
1030 				    glong *delta_time,
1031 				    glong *channel,
1032 				    glong *pitch,
1033 				    glong *transmitter)
1034 {
1035   glong val;
1036   guint delta_time_size;
1037 
1038   if(buffer == NULL){
1039     if(delta_time != NULL){
1040       *delta_time = 0;
1041     }
1042 
1043     if(channel != NULL){
1044       *channel = 0;
1045     }
1046 
1047     if(pitch != NULL){
1048       *pitch = 0;
1049     }
1050 
1051     if(transmitter != NULL){
1052       *transmitter = 0;
1053     }
1054 
1055     return(0);
1056   }
1057 
1058   /* delta time */
1059   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1060 						       &val);
1061 
1062   if(delta_time != NULL){
1063     *delta_time = val;
1064   }
1065 
1066   /* channel */
1067   if(channel != NULL){
1068     *channel = (0xf & buffer[delta_time_size]);
1069   }
1070 
1071   /* pitch */
1072   if(pitch != NULL){
1073     *pitch = 0x7f & buffer[delta_time_size + 1];
1074   }
1075 
1076   /* transmitter */
1077   if(transmitter != NULL){
1078     *transmitter = 0x7f & buffer[delta_time_size + 2];
1079   }
1080 
1081   return(delta_time_size + 3);
1082 }
1083 
1084 /**
1085  * ags_midi_buffer_util_put_change_program:
1086  * @buffer: the character buffer
1087  * @delta_time: timing information
1088  * @channel: channel
1089  * @program: the program
1090  *
1091  * Put change program.
1092  *
1093  * Since: 3.0.0
1094  */
1095 void
ags_midi_buffer_util_put_change_program(guchar * buffer,glong delta_time,glong channel,glong program)1096 ags_midi_buffer_util_put_change_program(guchar *buffer,
1097 					glong delta_time,
1098 					glong channel,
1099 					glong program)
1100 {
1101   guint delta_time_size;
1102 
1103   if(buffer == NULL){
1104     return;
1105   }
1106 
1107   /* delta time */
1108   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1109   ags_midi_buffer_util_put_varlength(buffer,
1110 				     delta_time);
1111 
1112   /* change-parameter channel message */
1113   buffer[delta_time_size] = 0xc0;
1114   buffer[delta_time_size] |= (channel & 0xf);
1115 
1116   /* program */
1117   buffer[delta_time_size + 1] = 0x7f & program;
1118 }
1119 
1120 /**
1121  * ags_midi_buffer_util_get_change_program:
1122  * @buffer: the character buffer
1123  * @delta_time: the return location of timing information
1124  * @channel: the return location of channel
1125  * @program: the return location of the program
1126  *
1127  * Get change program.
1128  *
1129  * Returns: the number of bytes read.
1130  *
1131  * Since: 3.0.0
1132  */
1133 guint
ags_midi_buffer_util_get_change_program(guchar * buffer,glong * delta_time,glong * channel,glong * program)1134 ags_midi_buffer_util_get_change_program(guchar *buffer,
1135 					glong *delta_time,
1136 					glong *channel,
1137 					glong *program)
1138 {
1139   glong val;
1140   guint delta_time_size;
1141 
1142   if(buffer == NULL){
1143     if(delta_time != NULL){
1144       *delta_time = 0;
1145     }
1146 
1147     if(channel != NULL){
1148       *channel = 0;
1149     }
1150 
1151     if(program != NULL){
1152       *program = 0;
1153     }
1154 
1155     return(0);
1156   }
1157 
1158   /* delta time */
1159   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1160 						       &val);
1161 
1162   if(delta_time != NULL){
1163     *delta_time = val;
1164   }
1165 
1166   /* channel */
1167   if(channel != NULL){
1168     *channel = (0xf & buffer[delta_time_size]);
1169   }
1170 
1171   /* program */
1172   if(program != NULL){
1173     *program = 0x7f & buffer[delta_time_size + 1];
1174   }
1175 
1176   return(delta_time_size + 2);
1177 }
1178 
1179 /**
1180  * ags_midi_buffer_util_put_change_pressure:
1181  * @buffer: the character buffer
1182  * @delta_time: timing information
1183  * @channel: channel
1184  * @pressure: the pressure
1185  *
1186  * Put change pressure.
1187  *
1188  * Since: 3.0.0
1189  */
1190 void
ags_midi_buffer_util_put_change_pressure(guchar * buffer,glong delta_time,glong channel,glong pressure)1191 ags_midi_buffer_util_put_change_pressure(guchar *buffer,
1192 					 glong delta_time,
1193 					 glong channel,
1194 					 glong pressure)
1195 {
1196   guint delta_time_size;
1197 
1198   if(buffer == NULL){
1199     return;
1200   }
1201 
1202   /* delta time */
1203   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1204   ags_midi_buffer_util_put_varlength(buffer,
1205 				     delta_time);
1206 
1207   /* change-parameter channel message */
1208   buffer[delta_time_size] = 0xd0;
1209   buffer[delta_time_size] |= (channel & 0xf);
1210 
1211   /* pressure */
1212   buffer[delta_time_size + 1] = 0x7f & pressure;
1213 }
1214 
1215 /**
1216  * ags_midi_buffer_util_get_change_pressure:
1217  * @buffer: the character buffer
1218  * @delta_time: the return location of timing information
1219  * @channel: the return location of channel
1220  * @pressure: the return location of the pressure
1221  *
1222  * Get change pressure.
1223  *
1224  * Returns: the number of bytes read.
1225  *
1226  * Since: 3.0.0
1227  */
1228 guint
ags_midi_buffer_util_get_change_pressure(guchar * buffer,glong * delta_time,glong * channel,glong * pressure)1229 ags_midi_buffer_util_get_change_pressure(guchar *buffer,
1230 					 glong *delta_time,
1231 					 glong *channel,
1232 					 glong *pressure)
1233 {
1234   glong val;
1235   guint delta_time_size;
1236 
1237   if(buffer == NULL){
1238     if(delta_time != NULL){
1239       *delta_time = 0;
1240     }
1241 
1242     if(channel != NULL){
1243       *channel = 0;
1244     }
1245 
1246     if(pressure != NULL){
1247       *pressure = 0;
1248     }
1249 
1250     return(0);
1251   }
1252 
1253   /* delta time */
1254   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1255 						       &val);
1256 
1257   if(delta_time != NULL){
1258     *delta_time = val;
1259   }
1260 
1261   /* channel */
1262   if(channel != NULL){
1263     *channel = (0xf & buffer[delta_time_size]);
1264   }
1265 
1266   /* pressure */
1267   if(pressure != NULL){
1268     *pressure = 0x7f & buffer[delta_time_size + 1];
1269   }
1270 
1271   return(delta_time_size + 2);
1272 }
1273 
1274 /**
1275  * ags_midi_buffer_util_put_sysex:
1276  * @buffer: the character buffer
1277  * @delta_time: timing information
1278  * @data: the data
1279  * @length: the data's length
1280  *
1281  * Put sysex.
1282  *
1283  * Since: 3.0.0
1284  */
1285 void
ags_midi_buffer_util_put_sysex(guchar * buffer,glong delta_time,guchar * data,glong length)1286 ags_midi_buffer_util_put_sysex(guchar *buffer,
1287 			       glong delta_time,
1288 			       guchar *data, glong length)
1289 {
1290   guint delta_time_size;
1291 
1292   if(buffer == NULL){
1293     return;
1294   }
1295 
1296   /* delta time */
1297   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1298   ags_midi_buffer_util_put_varlength(buffer,
1299 				     delta_time);
1300 
1301   /* status byte */
1302   buffer[delta_time_size] = 0xf0;
1303 
1304   /* put data */
1305   memcpy(buffer + delta_time_size + 1, data, length * sizeof(guchar));
1306 
1307   /* EOX end of sysex */
1308   buffer[delta_time_size + length + 1] = 0xf7;
1309 }
1310 
1311 /**
1312  * ags_midi_buffer_util_get_sysex:
1313  * @buffer: the character buffer
1314  * @delta_time: the return location of timing information
1315  * @data: the return location of data
1316  * @length: the return location of length
1317  *
1318  * Get sysex.
1319  *
1320  * Returns: the number of bytes read.
1321  *
1322  * Since: 3.0.0
1323  */
1324 guint
ags_midi_buffer_util_get_sysex(guchar * buffer,glong * delta_time,guchar ** data,glong * length)1325 ags_midi_buffer_util_get_sysex(guchar *buffer,
1326 			       glong *delta_time,
1327 			       guchar **data, glong *length)
1328 {
1329   guchar *tmp_data;
1330 
1331   glong val;
1332   guint delta_time_size;
1333   guint i;
1334 
1335   if(buffer == NULL){
1336     if(delta_time != NULL){
1337       *delta_time = 0;
1338     }
1339 
1340     if(data != NULL){
1341       *data = NULL;
1342     }
1343 
1344     if(length != NULL){
1345       *length = 0;
1346     }
1347 
1348     return(0);
1349   }
1350 
1351   /* delta time */
1352   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1353 						       &val);
1354 
1355   if(delta_time != NULL){
1356     *delta_time = val;
1357   }
1358 
1359   for(i = 0; buffer[delta_time_size + i + 1] != 0xf7; i++);
1360 
1361   if(data != NULL){
1362     if(i > 0){
1363       tmp_data = (guchar *) malloc(i * sizeof(guchar));
1364     }else{
1365       tmp_data = NULL;
1366     }
1367 
1368     memcpy(tmp_data, buffer + delta_time_size + 1, i * sizeof(guchar));
1369 
1370     *data = tmp_data;
1371   }
1372 
1373   if(length != NULL){
1374     *length = i;
1375   }
1376 
1377   return(delta_time_size + i + 2);
1378 }
1379 
1380 /**
1381  * ags_midi_buffer_util_put_quarter_frame:
1382  * @buffer: the character buffer
1383  * @delta_time: timing information
1384  * @message_type: the message type
1385  * @values: the values
1386  *
1387  * Put quarter frame.
1388  *
1389  * Since: 3.0.0
1390  */
1391 void
ags_midi_buffer_util_put_quarter_frame(guchar * buffer,glong delta_time,glong message_type,glong values)1392 ags_midi_buffer_util_put_quarter_frame(guchar *buffer,
1393 				       glong delta_time,
1394 				       glong message_type,
1395 				       glong values)
1396 {
1397   guint delta_time_size;
1398 
1399   if(buffer == NULL){
1400     return;
1401   }
1402 
1403   /* delta time */
1404   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1405   ags_midi_buffer_util_put_varlength(buffer,
1406 				     delta_time);
1407 
1408   /* status byte */
1409   buffer[delta_time_size] = 0xf1;
1410 
1411   /* message type */
1412   buffer[delta_time_size + 1] = 0x70 & message_type;
1413 
1414   /* values */
1415   buffer[delta_time_size + 1] |= 0x0f & values;
1416 }
1417 
1418 /**
1419  * ags_midi_buffer_util_get_quarter_frame:
1420  * @buffer: the character buffer
1421  * @delta_time: the return location of timing information
1422  * @message_type: the return location of the message type
1423  * @values: the return location of the values
1424  *
1425  * Get quarter frame.
1426  *
1427  * Returns: the number of bytes read.
1428  *
1429  * Since: 3.0.0
1430  */
1431 guint
ags_midi_buffer_util_get_quarter_frame(guchar * buffer,glong * delta_time,glong * message_type,glong * values)1432 ags_midi_buffer_util_get_quarter_frame(guchar *buffer,
1433 				       glong *delta_time,
1434 				       glong *message_type, glong *values)
1435 {
1436   glong val;
1437   guint delta_time_size;
1438 
1439   if(buffer == NULL){
1440     if(delta_time != NULL){
1441       *delta_time = 0;
1442     }
1443 
1444     if(message_type != NULL){
1445       *message_type = 0;
1446     }
1447 
1448     if(values != NULL){
1449       *values = 0;
1450     }
1451 
1452     return(0);
1453   }
1454 
1455   /* delta time */
1456   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1457 						       &val);
1458 
1459   if(delta_time != NULL){
1460     *delta_time = val;
1461   }
1462 
1463   if(message_type != NULL){
1464     *message_type = 0x70 & buffer[delta_time_size + 1];
1465   }
1466 
1467   if(values != NULL){
1468     *values = 0x0f & buffer[delta_time_size + 1];
1469   }
1470 
1471   return(delta_time_size + 2);
1472 }
1473 
1474 /**
1475  * ags_midi_buffer_util_put_song_position:
1476  * @buffer: the character buffer
1477  * @delta_time: timing information
1478  * @song_position: the song position
1479  *
1480  * Put song position.
1481  *
1482  * Since: 3.0.0
1483  */
1484 void
ags_midi_buffer_util_put_song_position(guchar * buffer,glong delta_time,glong song_position)1485 ags_midi_buffer_util_put_song_position(guchar *buffer,
1486 				       glong delta_time,
1487 				       glong song_position)
1488 {
1489   guint delta_time_size;
1490 
1491   if(buffer == NULL){
1492     return;
1493   }
1494 
1495   /* delta time */
1496   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1497   ags_midi_buffer_util_put_varlength(buffer,
1498 				     delta_time);
1499 
1500   /* status byte */
1501   buffer[delta_time_size] = 0xf2;
1502 
1503   /* song position */
1504   buffer[delta_time_size + 1] = 0x7f & song_position;
1505   buffer[delta_time_size + 2] = 0x7f & (song_position >> 7);
1506 }
1507 
1508 /**
1509  * ags_midi_buffer_util_get_song_position:
1510  * @buffer: the character buffer
1511  * @delta_time: the return location of timing information
1512  * @song_position: the return location of the song position
1513  *
1514  * Get song position.
1515  *
1516  * Returns: the number of bytes read.
1517  *
1518  * Since: 3.0.0
1519  */
1520 guint
ags_midi_buffer_util_get_song_position(guchar * buffer,glong * delta_time,glong * song_position)1521 ags_midi_buffer_util_get_song_position(guchar *buffer,
1522 				       glong *delta_time,
1523 				       glong *song_position)
1524 {
1525   glong val;
1526   guint delta_time_size;
1527 
1528   if(buffer == NULL){
1529     if(delta_time != NULL){
1530       *delta_time = 0;
1531     }
1532 
1533     if(song_position != NULL){
1534       *song_position = 0;
1535     }
1536 
1537     return(0);
1538   }
1539 
1540   /* delta time */
1541   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1542 						       &val);
1543 
1544   if(delta_time != NULL){
1545     *delta_time = val;
1546   }
1547 
1548   /* song position */
1549   if(song_position != NULL){
1550     *song_position = 0x7f & buffer[delta_time_size + 1];
1551     *song_position |= ((0x7f & buffer[delta_time_size + 2]) << 7);
1552   }
1553 
1554   return(delta_time_size + 3);
1555 }
1556 
1557 /**
1558  * ags_midi_buffer_util_put_song_select:
1559  * @buffer: the character buffer
1560  * @delta_time: timing information
1561  * @song_select: the song select
1562  *
1563  * Put song select.
1564  *
1565  * Since: 3.0.0
1566  */
1567 void
ags_midi_buffer_util_put_song_select(guchar * buffer,glong delta_time,glong song_select)1568 ags_midi_buffer_util_put_song_select(guchar *buffer,
1569 				     glong delta_time,
1570 				     glong song_select)
1571 {
1572   guint delta_time_size;
1573 
1574   if(buffer == NULL){
1575     return;
1576   }
1577 
1578   /* delta time */
1579   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1580   ags_midi_buffer_util_put_varlength(buffer,
1581 				     delta_time);
1582 
1583   /* status byte */
1584   buffer[delta_time_size] = 0xf3;
1585 
1586   /* song select */
1587   buffer[delta_time_size + 1] = 0x7f & song_select;
1588 }
1589 
1590 /**
1591  * ags_midi_buffer_util_get_song_select:
1592  * @buffer: the character buffer
1593  * @delta_time: the return location of timing information
1594  * @song_select: the return location of the song select
1595  *
1596  * Get song select.
1597  *
1598  * Returns: the number of bytes read.
1599  *
1600  * Since: 3.0.0
1601  */
1602 guint
ags_midi_buffer_util_get_song_select(guchar * buffer,glong * delta_time,glong * song_select)1603 ags_midi_buffer_util_get_song_select(guchar *buffer,
1604 				     glong *delta_time,
1605 				     glong *song_select)
1606 {
1607   glong val;
1608   guint delta_time_size;
1609 
1610   if(buffer == NULL){
1611     if(delta_time != NULL){
1612       *delta_time = 0;
1613     }
1614 
1615     if(song_select != NULL){
1616       *song_select = 0;
1617     }
1618 
1619     return(0);
1620   }
1621 
1622   /* delta time */
1623   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1624 						       &val);
1625 
1626   if(delta_time != NULL){
1627     *delta_time = val;
1628   }
1629 
1630   if(song_select != NULL){
1631     *song_select = 0x7f & buffer[delta_time_size + 1];
1632   }
1633 
1634   return(delta_time_size + 2);
1635 }
1636 
1637 /**
1638  * ags_midi_buffer_util_put_tune_request:
1639  * @buffer: the character buffer
1640  * @delta_time: timing information
1641  *
1642  * Put tune request
1643  *
1644  * Since: 3.0.0
1645  */
1646 void
ags_midi_buffer_util_put_tune_request(guchar * buffer,glong delta_time)1647 ags_midi_buffer_util_put_tune_request(guchar *buffer,
1648 				      glong delta_time)
1649 {
1650   guint delta_time_size;
1651 
1652   if(buffer == NULL){
1653     return;
1654   }
1655 
1656   /* delta time */
1657   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1658   ags_midi_buffer_util_put_varlength(buffer,
1659 				     delta_time);
1660 
1661   /* status byte */
1662   buffer[delta_time_size] = 0xf6;
1663 }
1664 
1665 /**
1666  * ags_midi_buffer_util_get_tune_request:
1667  * @buffer: the character buffer
1668  * @delta_time: the return location of timing information
1669  *
1670  * Get tune request.
1671  *
1672  * Returns: the number of bytes read.
1673  *
1674  * Since: 3.0.0
1675  */
1676 guint
ags_midi_buffer_util_get_tune_request(guchar * buffer,glong * delta_time)1677 ags_midi_buffer_util_get_tune_request(guchar *buffer,
1678 				      glong *delta_time)
1679 {
1680   glong val;
1681   guint delta_time_size;
1682 
1683   if(buffer == NULL){
1684     if(delta_time != NULL){
1685       *delta_time = 0;
1686     }
1687 
1688     return(0);
1689   }
1690 
1691   /* delta time */
1692   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1693 						       &val);
1694 
1695   if(delta_time != NULL){
1696     *delta_time = val;
1697   }
1698 
1699   return(delta_time_size + 1);
1700 }
1701 
1702 /**
1703  * ags_midi_buffer_util_put_sequence_number:
1704  * @buffer: the character buffer
1705  * @delta_time: timing information
1706  * @sequence: the sequence
1707  *
1708  * Put sequence number.
1709  *
1710  * Since: 3.0.0
1711  */
1712 void
ags_midi_buffer_util_put_sequence_number(guchar * buffer,glong delta_time,glong sequence)1713 ags_midi_buffer_util_put_sequence_number(guchar *buffer,
1714 					 glong delta_time,
1715 					 glong sequence)
1716 {
1717   guint delta_time_size;
1718 
1719   if(buffer == NULL){
1720     return;
1721   }
1722 
1723   /* delta time */
1724   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1725   ags_midi_buffer_util_put_varlength(buffer,
1726 				     delta_time);
1727 
1728   /* status byte */
1729   buffer[delta_time_size] = 0xff;
1730 
1731   /* type */
1732   buffer[delta_time_size + 1] = 0x00;
1733 
1734   /* length */
1735   buffer[delta_time_size + 2] = 2;
1736 
1737   /* data */
1738   buffer[delta_time_size + 3] = ((0xff00 & sequence) >> 8);
1739   buffer[delta_time_size + 4] = 0xff & sequence;
1740 }
1741 
1742 /**
1743  * ags_midi_buffer_util_get_sequence_number:
1744  * @buffer: the character buffer
1745  * @delta_time: the return location of timing information
1746  * @sequence: the return location of the sequence
1747  *
1748  * Get sequence number.
1749  *
1750  * Returns: the number of bytes read.
1751  *
1752  * Since: 3.0.0
1753  */
1754 guint
ags_midi_buffer_util_get_sequence_number(guchar * buffer,glong * delta_time,glong * sequence)1755 ags_midi_buffer_util_get_sequence_number(guchar *buffer,
1756 					 glong *delta_time,
1757 					 glong *sequence)
1758 {
1759   glong val;
1760   guint delta_time_size;
1761 
1762   if(buffer == NULL){
1763     if(delta_time != NULL){
1764       *delta_time = 0;
1765     }
1766 
1767     if(sequence != NULL){
1768       *sequence = 0;
1769     }
1770 
1771     return(0);
1772   }
1773 
1774   /* delta time */
1775   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1776 						       &val);
1777 
1778   if(delta_time != NULL){
1779     *delta_time = val;
1780   }
1781 
1782   /* sequence */
1783   if(sequence != NULL){
1784     *sequence = buffer[delta_time_size + 3] << 8;
1785     *sequence |= buffer[delta_time_size + 4];
1786   }
1787 
1788   return(delta_time_size + 5);
1789 }
1790 
1791 /**
1792  * ags_midi_buffer_util_put_smtpe:
1793  * @buffer: the character buffer
1794  * @delta_time: timing information
1795  * @rr: frame rate
1796  * @hr: hour
1797  * @mn: minute
1798  * @se: second
1799  * @fr: frame number
1800  *
1801  * Put smtpe timestamp.
1802  *
1803  * Since: 3.0.0
1804  */
1805 void
ags_midi_buffer_util_put_smtpe(guchar * buffer,glong delta_time,glong rr,glong hr,glong mn,glong se,glong fr)1806 ags_midi_buffer_util_put_smtpe(guchar *buffer,
1807 			       glong delta_time,
1808 			       glong rr, glong hr, glong mn, glong se, glong fr)
1809 {
1810   guint delta_time_size;
1811 
1812   if(buffer == NULL){
1813     return;
1814   }
1815 
1816   /* delta time */
1817   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1818   ags_midi_buffer_util_put_varlength(buffer,
1819 				     delta_time);
1820 
1821   /* status byte */
1822   buffer[delta_time_size] = 0xff;
1823 
1824   /* type */
1825   buffer[delta_time_size + 1] = 0x54;
1826 
1827   /* length */
1828   buffer[delta_time_size + 2] = 5;
1829 
1830   /* rr */
1831   buffer[delta_time_size + 3] = rr;
1832 
1833   /* hr */
1834   buffer[delta_time_size + 3] |= hr;
1835 
1836   /* mn */
1837   buffer[delta_time_size + 4] = mn;
1838 
1839   /* se */
1840   buffer[delta_time_size + 5] = se;
1841 
1842   /* fr */
1843   buffer[delta_time_size + 6] = fr;
1844 }
1845 
1846 /**
1847  * ags_midi_buffer_util_get_smtpe:
1848  * @buffer: the character buffer
1849  * @delta_time: the return location of timing information
1850  * @rr: the return location of frame rate
1851  * @hr: the return location of hour
1852  * @mn: the return location of minute
1853  * @se: the return location of second
1854  * @fr: the return location of frame number
1855  *
1856  * Get smtpe timestamp.
1857  *
1858  * Returns: the number of bytes read.
1859  *
1860  * Since: 3.0.0
1861  */
1862 guint
ags_midi_buffer_util_get_smtpe(guchar * buffer,glong * delta_time,glong * rr,glong * hr,glong * mn,glong * se,glong * fr)1863 ags_midi_buffer_util_get_smtpe(guchar *buffer,
1864 			       glong *delta_time,
1865 			       glong *rr, glong *hr, glong *mn, glong *se, glong *fr)
1866 {
1867   glong val;
1868   guint delta_time_size;
1869 
1870   if(buffer == NULL){
1871     if(delta_time != NULL){
1872       *delta_time = 0;
1873     }
1874 
1875     if(rr != NULL){
1876       *rr = 0;
1877     }
1878 
1879     if(hr != NULL){
1880       *hr = 0;
1881     }
1882 
1883     if(mn != NULL){
1884       *mn = 0;
1885     }
1886 
1887     if(se != NULL){
1888       *se = 0;
1889     }
1890 
1891     if(fr != NULL){
1892       *fr = 0;
1893     }
1894 
1895     return(0);
1896   }
1897 
1898   /* delta time */
1899   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
1900 						       &val);
1901 
1902   if(delta_time != NULL){
1903     *delta_time = val;
1904   }
1905 
1906   /* rr */
1907   if(rr != NULL){
1908     *rr = 0xc0 & buffer[delta_time_size + 3];
1909   }
1910 
1911   /* hr */
1912   if(hr != NULL){
1913     *hr = 0x3f & buffer[delta_time_size + 3];
1914   }
1915 
1916   /* mn */
1917   if(mn != NULL){
1918     *mn = buffer[delta_time_size + 4];
1919   }
1920 
1921   /* se */
1922   if(se != NULL){
1923     *se = buffer[delta_time_size + 5];
1924   }
1925 
1926   /* fr */
1927   if(fr != NULL){
1928     *fr = buffer[delta_time_size + 6];
1929   }
1930 
1931   return(delta_time_size + 7);
1932 }
1933 
1934 /**
1935  * ags_midi_buffer_util_put_tempo:
1936  * @buffer: the character buffer
1937  * @delta_time: timing information
1938  * @tempo: the tempo
1939  *
1940  * Put tempo.
1941  *
1942  * Since: 3.0.0
1943  */
1944 void
ags_midi_buffer_util_put_tempo(guchar * buffer,glong delta_time,glong tempo)1945 ags_midi_buffer_util_put_tempo(guchar *buffer,
1946 			       glong delta_time,
1947 			       glong tempo)
1948 {
1949   guint delta_time_size;
1950 
1951   if(buffer == NULL){
1952     return;
1953   }
1954 
1955   /* delta time */
1956   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
1957   ags_midi_buffer_util_put_varlength(buffer,
1958 				     delta_time);
1959 
1960   /* status byte */
1961   buffer[delta_time_size] = 0xff;
1962 
1963   /* type */
1964   buffer[delta_time_size + 1] = 0x51;
1965 
1966   /* length */
1967   buffer[delta_time_size + 2] = 0x03;
1968 
1969   /* tempo */
1970   ags_midi_buffer_util_put_int24(buffer + delta_time_size + 3,
1971 				 tempo);
1972 }
1973 
1974 /**
1975  * ags_midi_buffer_util_get_tempo:
1976  * @buffer: the character buffer
1977  * @delta_time: the return location of timing information
1978  * @tempo: the tempo
1979  *
1980  * Get tempo.
1981  *
1982  * Returns: the number of bytes read.
1983  *
1984  * Since: 3.0.0
1985  */
1986 guint
ags_midi_buffer_util_get_tempo(guchar * buffer,glong * delta_time,glong * tempo)1987 ags_midi_buffer_util_get_tempo(guchar *buffer,
1988 			       glong *delta_time,
1989 			       glong *tempo)
1990 {
1991   glong val;
1992   guint delta_time_size;
1993 
1994   if(buffer == NULL){
1995     if(delta_time != NULL){
1996       *delta_time = 0;
1997     }
1998 
1999     if(tempo != NULL){
2000       *tempo = 0;
2001     }
2002 
2003     return(0);
2004   }
2005 
2006   /* delta time */
2007   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2008 						       &val);
2009 
2010   if(delta_time != NULL){
2011     *delta_time = val;
2012   }
2013 
2014   /* tempo */
2015   ags_midi_buffer_util_get_int24(buffer + delta_time_size + 3,
2016 				 tempo);
2017 
2018   return(delta_time_size + 6);
2019 }
2020 
2021 /**
2022  * ags_midi_buffer_util_put_time_signature:
2023  * @buffer: the character buffer
2024  * @delta_time: timing information
2025  * @nn: numerator
2026  * @dd: denominator
2027  * @cc: clocks
2028  * @bb: beats
2029  *
2030  * Put time signature
2031  *
2032  * Since: 3.0.0
2033  */
2034 void
ags_midi_buffer_util_put_time_signature(guchar * buffer,glong delta_time,glong nn,glong dd,glong cc,glong bb)2035 ags_midi_buffer_util_put_time_signature(guchar *buffer,
2036 					glong delta_time,
2037 					glong nn, glong dd, glong cc, glong bb)
2038 {
2039   guint delta_time_size;
2040 
2041   if(buffer == NULL){
2042     return;
2043   }
2044 
2045   /* delta time */
2046   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2047   ags_midi_buffer_util_put_varlength(buffer,
2048 				     delta_time);
2049 
2050   /* status byte */
2051   buffer[delta_time_size] = 0xff;
2052 
2053   /* type */
2054   buffer[delta_time_size + 1] = 0x58;
2055 
2056   /* length */
2057   buffer[delta_time_size + 2] = 0x4;
2058 
2059   /* nn */
2060   buffer[delta_time_size + 3] = nn;
2061 
2062   /* dd */
2063   buffer[delta_time_size + 4] = dd;
2064 
2065   /* cc */
2066   buffer[delta_time_size + 5] = cc;
2067 
2068   /* bb */
2069   buffer[delta_time_size + 6] = bb;
2070 }
2071 
2072 /**
2073  * ags_midi_buffer_util_get_time_signature:
2074  * @buffer: the character buffer
2075  * @delta_time: the return location of timing information
2076  * @nn: the return location of numerator
2077  * @dd: the return location of denominator
2078  * @cc: the return location of clocks
2079  * @bb: the return location of beats
2080  *
2081  * Get time signature.
2082  *
2083  * Returns: the number of bytes read.
2084  *
2085  * Since: 3.0.0
2086  */
2087 guint
ags_midi_buffer_util_get_time_signature(guchar * buffer,glong * delta_time,glong * nn,glong * dd,glong * cc,glong * bb)2088 ags_midi_buffer_util_get_time_signature(guchar *buffer,
2089 					glong *delta_time,
2090 					glong *nn, glong *dd, glong *cc, glong *bb)
2091 {
2092   glong val;
2093   guint delta_time_size;
2094 
2095   if(buffer == NULL){
2096     if(delta_time != NULL){
2097       *delta_time = 0;
2098     }
2099 
2100     if(nn != NULL){
2101       *nn = 0;
2102     }
2103 
2104     if(dd != NULL){
2105       *dd = 0;
2106     }
2107 
2108     if(cc != NULL){
2109       *cc = 0;
2110     }
2111 
2112     if(bb != NULL){
2113       *bb = 0;
2114     }
2115 
2116     return(0);
2117   }
2118 
2119   /* delta time */
2120   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2121 						       &val);
2122 
2123   if(delta_time != NULL){
2124     *delta_time = val;
2125   }
2126 
2127   /* nn */
2128   if(nn != NULL){
2129     *nn = buffer[delta_time_size + 3];
2130   }
2131 
2132   /* dd */
2133   if(dd != NULL){
2134     *dd = buffer[delta_time_size + 4];
2135   }
2136 
2137   /* cc */
2138   if(cc != NULL){
2139     *cc = buffer[delta_time_size + 5];
2140   }
2141 
2142   /* bb */
2143   if(bb != NULL){
2144     *bb = buffer[delta_time_size + 6];
2145   }
2146 
2147   return(delta_time_size + 7);
2148 }
2149 
2150 /**
2151  * ags_midi_buffer_util_put_key_signature:
2152  * @buffer: the character buffer
2153  * @delta_time: timing information
2154  * @sf: flats or sharps
2155  * @mi: 1 equals minor or 0 means major
2156  *
2157  * Put key signature.
2158  *
2159  * Since: 3.0.0
2160  */
2161 void
ags_midi_buffer_util_put_key_signature(guchar * buffer,glong delta_time,glong sf,glong mi)2162 ags_midi_buffer_util_put_key_signature(guchar *buffer,
2163 				       glong delta_time,
2164 				       glong sf, glong mi)
2165 {
2166   guint delta_time_size;
2167 
2168   if(buffer == NULL){
2169     return;
2170   }
2171 
2172   /* delta time */
2173   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2174   ags_midi_buffer_util_put_varlength(buffer,
2175 				     delta_time);
2176 
2177   /* status byte */
2178   buffer[delta_time_size] = 0xff;
2179 
2180   /* type */
2181   buffer[delta_time_size + 1] = 0x59;
2182 
2183   /* length */
2184   buffer[delta_time_size + 2] = 2;
2185 
2186   /* sf */
2187   buffer[delta_time_size + 3] = sf;
2188 
2189   /* mi */
2190   buffer[delta_time_size + 4] = mi;
2191 }
2192 
2193 /**
2194  * ags_midi_buffer_util_get_key_signature:
2195  * @buffer: the character buffer
2196  * @delta_time: the return location of timing information
2197  * @sf: the return location of flats or sharps
2198  * @mi: the return location of minor or major
2199  *
2200  * Get key signature.
2201  *
2202  * Returns: the number of bytes read.
2203  *
2204  * Since: 3.0.0
2205  */
2206 guint
ags_midi_buffer_util_get_key_signature(guchar * buffer,glong * delta_time,glong * sf,glong * mi)2207 ags_midi_buffer_util_get_key_signature(guchar *buffer,
2208 				       glong *delta_time,
2209 				       glong *sf, glong *mi)
2210 {
2211   glong val;
2212   guint delta_time_size;
2213 
2214   if(buffer == NULL){
2215     if(delta_time != NULL){
2216       *delta_time = 0;
2217     }
2218 
2219     if(sf != NULL){
2220       *sf = 0;
2221     }
2222 
2223     if(mi != NULL){
2224       *mi = 0;
2225     }
2226 
2227     return(0);
2228   }
2229 
2230   /* delta time */
2231   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2232 						       &val);
2233 
2234   if(delta_time != NULL){
2235     *delta_time = val;
2236   }
2237 
2238   /* sf */
2239   if(sf != NULL){
2240     *sf = buffer[delta_time_size + 3];
2241   }
2242 
2243   /* mi */
2244   if(mi != NULL){
2245     *mi = buffer[delta_time_size + 4];
2246   }
2247 
2248   return(delta_time_size + 5);
2249 }
2250 
2251 /**
2252  * ags_midi_buffer_util_put_sequencer_meta_event:
2253  * @buffer: the character buffer
2254  * @delta_time: timing information
2255  * @len: the length of data
2256  * @id: the manufacturer id
2257  * @data: the data
2258  *
2259  * Put sequencer meta event.
2260  *
2261  * Since: 3.0.0
2262  */
2263 void
ags_midi_buffer_util_put_sequencer_meta_event(guchar * buffer,glong delta_time,glong len,glong id,glong data)2264 ags_midi_buffer_util_put_sequencer_meta_event(guchar *buffer,
2265 					      glong delta_time,
2266 					      glong len, glong id, glong data)
2267 {
2268   guint delta_time_size;
2269 
2270   if(buffer == NULL){
2271     return;
2272   }
2273 
2274   /* delta time */
2275   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2276   ags_midi_buffer_util_put_varlength(buffer,
2277 				     delta_time);
2278 
2279   /* status byte */
2280   buffer[delta_time_size] = 0xff;
2281 
2282   /* type */
2283   buffer[delta_time_size + 1] = 0x7f;
2284 
2285   /* length */
2286   buffer[delta_time_size + 2] = 0xff & len;
2287 
2288   /* id */
2289   buffer[delta_time_size + 3] = 0xff & id;
2290 
2291   /* data */
2292   switch(len){
2293   case 3:
2294     {
2295       buffer[delta_time_size + 6] = ((0xff << 16) & data) >> 16;
2296     }
2297   case 2:
2298     {
2299       buffer[delta_time_size + 4] = 0xff & data;
2300       buffer[delta_time_size + 5] = ((0xff << 8) & data) >> 8;
2301     }
2302   }
2303 }
2304 
2305 /**
2306  * ags_midi_buffer_util_get_sequencer_meta_event:
2307  * @buffer: the character buffer
2308  * @delta_time: the return location of timing information
2309  * @len: the return location of the length of data
2310  * @id: the return location of the manufacturer id
2311  * @data: the return location of the data
2312  *
2313  * Get sequencer meta event.
2314  *
2315  * Returns: the number of bytes read.
2316  *
2317  * Since: 3.0.0
2318  */
2319 guint
ags_midi_buffer_util_get_sequencer_meta_event(guchar * buffer,glong * delta_time,glong * len,glong * id,glong * data)2320 ags_midi_buffer_util_get_sequencer_meta_event(guchar *buffer,
2321 					      glong *delta_time,
2322 					      glong *len, glong *id, glong *data)
2323 {
2324   glong val;
2325   guint delta_time_size;
2326 
2327   if(buffer == NULL){
2328     if(delta_time != NULL){
2329       *delta_time = 0;
2330     }
2331 
2332     if(len != NULL){
2333       *len = 0;
2334     }
2335 
2336     if(id != NULL){
2337       *id = 0;
2338     }
2339 
2340     if(data != NULL){
2341       *data = 0;
2342     }
2343 
2344     return(0);
2345   }
2346 
2347   /* delta time */
2348   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2349 						       &val);
2350 
2351   if(delta_time != NULL){
2352     *delta_time = val;
2353   }
2354 
2355   if(len != NULL){
2356     len[0] = buffer[delta_time_size + 2];
2357   }
2358 
2359   if(id != NULL){
2360     *id = buffer[delta_time_size + 3];
2361   }
2362 
2363   if(data != NULL){
2364     *data = 0;
2365 
2366     switch(buffer[delta_time_size + 2]){
2367     case 3:
2368       {
2369 	*data |= (buffer[delta_time_size + 6] << 16);
2370       }
2371     case 2:
2372       {
2373 	*data |= buffer[delta_time_size + 4];
2374 	*data |= (buffer[delta_time_size + 5] << 8);
2375       }
2376     }
2377   }
2378 
2379   return(delta_time_size + buffer[delta_time_size + 2] + 3);
2380 }
2381 
2382 /**
2383  * ags_midi_buffer_util_put_text_event:
2384  * @buffer: the character buffer
2385  * @delta_time: timing information
2386  * @text: the text
2387  * @length: the length
2388  *
2389  * Put text event.
2390  *
2391  * Since: 3.0.0
2392  */
2393 void
ags_midi_buffer_util_put_text_event(guchar * buffer,glong delta_time,gchar * text,glong length)2394 ags_midi_buffer_util_put_text_event(guchar *buffer,
2395 				    glong delta_time,
2396 				    gchar *text, glong length)
2397 {
2398   guint delta_time_size;
2399 
2400   if(buffer == NULL){
2401     return;
2402   }
2403 
2404   /* delta time */
2405   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2406   ags_midi_buffer_util_put_varlength(buffer,
2407 				     delta_time);
2408 
2409   /* status byte */
2410   buffer[delta_time_size] = 0xff;
2411 
2412   /* type */
2413   buffer[delta_time_size + 1] = 0x01;
2414 
2415   /* length */
2416   buffer[delta_time_size + 2] = 0xff & length;
2417 
2418   /* text */
2419   memcpy(buffer + delta_time_size + 3, text, length * sizeof(guchar));
2420 }
2421 
2422 /**
2423  * ags_midi_buffer_util_get_text_event:
2424  * @buffer: the character buffer
2425  * @delta_time: the return location of timing information
2426  * @text: the return location of the text
2427  * @length: the return location of the length
2428  *
2429  * Get text event.
2430  *
2431  * Returns: the number of bytes read.
2432  *
2433  * Since: 3.0.0
2434  */
2435 guint
ags_midi_buffer_util_get_text_event(guchar * buffer,glong * delta_time,gchar ** text,glong * length)2436 ags_midi_buffer_util_get_text_event(guchar *buffer,
2437 				    glong *delta_time,
2438 				    gchar **text, glong *length)
2439 {
2440   glong val;
2441   guint text_size;
2442   guint delta_time_size;
2443 
2444   if(buffer == NULL){
2445     if(delta_time != NULL){
2446       *delta_time = 0;
2447     }
2448 
2449     if(text != NULL){
2450       *text = NULL;
2451     }
2452 
2453     if(length != NULL){
2454       *length = 0;
2455     }
2456 
2457     return(0);
2458   }
2459 
2460   /* delta time */
2461   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2462 						       &val);
2463 
2464   if(delta_time != NULL){
2465     *delta_time = val;
2466   }
2467 
2468   /* length */
2469   text_size = 0x7f & buffer[delta_time_size + 2];
2470 
2471   if(length != NULL){
2472     *length = text_size;
2473   }
2474 
2475   /* text */
2476   if(text != NULL){
2477     text[0] = (gchar *) malloc(text_size * sizeof(gchar));
2478     memcpy(text[0], buffer + delta_time_size + 3, text_size * sizeof(gchar));
2479   }
2480 
2481   return(delta_time_size + text_size + 3);
2482 }
2483 
2484 /**
2485  * ags_midi_buffer_util_put_end_of_track:
2486  * @buffer: the character buffer
2487  * @delta_time: timing information
2488  *
2489  * Put end of track.
2490  *
2491  * Since: 3.0.0
2492  */
2493 void
ags_midi_buffer_util_put_end_of_track(guchar * buffer,glong delta_time)2494 ags_midi_buffer_util_put_end_of_track(guchar *buffer,
2495 				      glong delta_time)
2496 {
2497   guint delta_time_size;
2498 
2499   if(buffer == NULL){
2500     return;
2501   }
2502 
2503   /* delta time */
2504   delta_time_size = ags_midi_buffer_util_get_varlength_size(delta_time);
2505   ags_midi_buffer_util_put_varlength(buffer,
2506 				     delta_time);
2507 
2508   /* status byte */
2509   buffer[delta_time_size] = 0xff;
2510 
2511   /* type */
2512   buffer[delta_time_size + 1] = 0x2f;
2513 
2514   /* length */
2515   buffer[delta_time_size + 2] = 0;
2516 }
2517 
2518 /**
2519  * ags_midi_buffer_util_get_end_of_track:
2520  * @buffer: the character buffer
2521  * @delta_time: the return location of timing information
2522  *
2523  * Get end of track.
2524  *
2525  * Returns: the number of bytes read.
2526  *
2527  * Since: 3.0.0
2528  */
2529 guint
ags_midi_buffer_util_get_end_of_track(guchar * buffer,glong * delta_time)2530 ags_midi_buffer_util_get_end_of_track(guchar *buffer,
2531 				      glong *delta_time)
2532 {
2533   glong val;
2534   guint delta_time_size;
2535 
2536   if(buffer == NULL){
2537     if(delta_time != NULL){
2538       *delta_time = 0;
2539     }
2540 
2541     return(0);
2542   }
2543 
2544   /* delta time */
2545   delta_time_size = ags_midi_buffer_util_get_varlength(buffer,
2546 						       &val);
2547 
2548   if(delta_time != NULL){
2549     *delta_time = val;
2550   }
2551 
2552   return(delta_time_size + 3);
2553 }
2554 
2555 /**
2556  * ags_midi_buffer_util_seek_message:
2557  * @buffer: the buffer to seek
2558  * @message_count: seek count messages
2559  * @delta_time: the return location of current delta time
2560  *
2561  * Seek MIDI messages from @buffer
2562  *
2563  * Returns: the buffer at offset at @message_count ahead
2564  *
2565  * Since: 3.0.0
2566  */
2567 guchar*
ags_midi_buffer_util_seek_message(guchar * buffer,guint message_count,glong * delta_time)2568 ags_midi_buffer_util_seek_message(guchar *buffer,
2569 				  guint message_count,
2570 				  glong *delta_time)
2571 {
2572   static const gchar header[] = "MThd";
2573   static const gchar track[] = "MTrk";
2574 
2575   guchar *offset;
2576 
2577   glong current_delta_time, tmp_delta_time;
2578   glong next_delta_time;
2579   guint delta_time_size;
2580   guchar status, prev_status;
2581   guchar meta_type;
2582   guint n;
2583   guint i;
2584   gboolean initial_run;
2585 
2586   if(buffer == NULL){
2587     return(NULL);
2588   }
2589 
2590   offset = buffer;
2591 
2592   /* check for header */
2593   if(!g_ascii_strncasecmp(offset,
2594 			  header,
2595 			  4)){
2596     offset += 14;
2597   }
2598 
2599   /* seek message count */
2600   current_delta_time = 0;
2601   initial_run = TRUE;
2602 
2603   prev_status = 0;
2604 
2605   for(i = 0; i < message_count; i++){
2606     /* check for track */
2607     if(initial_run){
2608       if(!g_ascii_strncasecmp(offset,
2609 			      track,
2610 			      4)){
2611 	offset += 8;
2612       }
2613 
2614       initial_run = FALSE;
2615     }
2616 
2617     /* read delta time */
2618     tmp_delta_time = 0;
2619 
2620     delta_time_size = ags_midi_buffer_util_get_varlength(offset,
2621 							 &tmp_delta_time);
2622 
2623     if(delta_time_size > 0){
2624       current_delta_time = tmp_delta_time;
2625     }
2626 
2627     /* read status byte */
2628     status = offset[delta_time_size];
2629 
2630     n = 1;
2631   ags_midi_buffer_util_seek_message_REPEAT_STATUS:
2632 
2633     if((0xf0 & status) != 0xf0){
2634       switch(status & 0xf0){
2635       case 0x80:
2636 	{
2637 	  n += delta_time_size + 2;
2638 
2639 	  prev_status = status;
2640 	}
2641 	break;
2642       case 0x90:
2643 	{
2644 	  n += delta_time_size + 2;
2645 
2646 	  prev_status = status;
2647 	}
2648 	break;
2649       case 0xa0:
2650 	{
2651 	  n += delta_time_size + 2;
2652 
2653 	  prev_status = status;
2654 	}
2655 	break;
2656       case 0xb0:
2657 	{
2658 	  n += delta_time_size + 2;
2659 
2660 	  prev_status = status;
2661 	}
2662 	break;
2663       case 0xc0:
2664 	{
2665 	  n += delta_time_size + 1;
2666 
2667 	  prev_status = status;
2668 	}
2669 	break;
2670       case 0xd0:
2671 	{
2672 	  n += delta_time_size + 1;
2673 
2674 	  prev_status = status;
2675 	}
2676 	break;
2677       case 0xe0:
2678 	{
2679 	  n += delta_time_size + 2;
2680 
2681 	  prev_status = status;
2682 	}
2683 	break;
2684       default:
2685 	{
2686 #ifdef AGS_DEBUG
2687 	  g_message("repeat status=0x%x", prev_status);
2688 #endif
2689 	  status = prev_status;
2690 
2691 	  goto ags_midi_buffer_util_seek_message_REPEAT_STATUS;
2692 	}
2693       }
2694 
2695       offset += n;
2696 
2697       /* check if status is omitted */
2698       next_delta_time = 0;
2699 
2700       delta_time_size = ags_midi_buffer_util_get_varlength(offset,
2701 							   &next_delta_time);
2702 
2703       if((0xf0 & offset[delta_time_size]) != 0xf0){
2704 	switch(status & 0xf0){
2705 	case 0x80:
2706 	case 0x90:
2707 	case 0xa0:
2708 	case 0xb0:
2709 	case 0xc0:
2710 	case 0xd0:
2711 	case 0xe0:
2712 	  break;
2713 	default:
2714 	  {
2715 	    n = 0;
2716 	    current_delta_time = next_delta_time;
2717 
2718 	    goto ags_midi_buffer_util_seek_message_REPEAT_STATUS;
2719 	  }
2720 	}
2721       }
2722     }else{
2723       status = offset[delta_time_size];
2724 
2725       switch(status){
2726       case 0xf0:
2727 	{
2728 	  /* start of system exclusive */
2729 	  n = ags_midi_buffer_util_get_sysex(offset,
2730 					     NULL,
2731 					     NULL, NULL);
2732 
2733 	  offset += n;
2734 	}
2735 	break;
2736       case 0xf1:
2737 	{
2738 	  /* quarter frame */
2739 	  n = ags_midi_buffer_util_get_quarter_frame(offset,
2740 						     NULL,
2741 						     NULL, NULL);
2742 
2743 	  offset += n;
2744 	}
2745 	break;
2746       case 0xf2:
2747 	{
2748 	  /* song position */
2749 	  n = ags_midi_buffer_util_get_song_position(offset,
2750 						     NULL,
2751 						     NULL);
2752 
2753 	  offset += n;
2754 	}
2755 	break;
2756       case 0xf3:
2757 	{
2758 	  /* song select */
2759 	  n = ags_midi_buffer_util_get_song_select(offset,
2760 						   NULL,
2761 						   NULL);
2762 
2763 	  offset += n;
2764 	}
2765 	break;
2766       case 0xf4:
2767       case 0xf5:
2768 	{
2769 #ifdef AGS_DEBUG
2770 	  g_message("undefined");
2771 #endif
2772 
2773 	  offset += delta_time_size;
2774 	}
2775 	break;
2776       case 0xf6:
2777 	{
2778 	  /* tune request */
2779 	  n = ags_midi_buffer_util_get_tune_request(offset,
2780 						    NULL);
2781 
2782 	  offset += n;
2783 	}
2784 	break;
2785       case 0xf7:
2786 	{
2787 	  /* sysex continuation or arbitrary stuff */
2788 #ifdef AGS_DEBUG
2789 	  g_message("sysex end");
2790 #endif
2791 	}
2792 	break;
2793       case 0xff:
2794 	{
2795 	  guint meta_type;
2796 
2797 	  meta_type = offset[delta_time_size + 1];
2798 
2799 
2800 
2801 	  switch(meta_type){
2802 	  case 0x00:
2803 	    {
2804 	      int c;
2805 
2806 	      //	  c = offset[delta_time_size + 1];
2807 
2808 	      //	  if(c == 0x02){
2809 	      n = ags_midi_buffer_util_get_sequence_number(offset,
2810 							   NULL,
2811 							   NULL);
2812 
2813 	      offset += n;
2814 	      //	  }
2815 	    }
2816 	    break;
2817 	  case 0x01:      /* Text event */
2818 	  case 0x02:      /* Copyright notice */
2819 	  case 0x03:      /* Sequence/Track name */
2820 	  case 0x04:      /* Instrument name */
2821 	  case 0x05:      /* Lyric */
2822 	  case 0x06:      /* Marker */
2823 	  case 0x07:      /* Cue point */
2824 	  case 0x08:
2825 	  case 0x09:
2826 	  case 0x0a:
2827 	  case 0x0b:
2828 	  case 0x0c:
2829 	  case 0x0d:
2830 	  case 0x0e:
2831 	  case 0x0f:
2832 	    {
2833 	      /* These are all text events */
2834 	      n = ags_midi_buffer_util_get_text_event(offset,
2835 						      NULL,
2836 						      NULL, NULL);
2837 
2838 	      offset += n;
2839 	    }
2840 	    break;
2841 	  case 0x2f:
2842 	    {
2843 	      int c;
2844 
2845 	      //	      c = buffer[delta_time_size];
2846 
2847 	      //	      if(c == 0x0){
2848 	      /* End of Track */
2849 	      n = ags_midi_buffer_util_get_end_of_track(offset,
2850 							NULL);
2851 
2852 	      offset = NULL;
2853 	    }
2854 	    break;
2855 	  case 0x51:
2856 	    {
2857 	      int c;
2858 
2859 	      //	      c = offset[delta_time_size];
2860 
2861 	      //	      if(c == 0x03){
2862 	      /* Set tempo */
2863 	      n = ags_midi_buffer_util_get_tempo(offset,
2864 						 NULL,
2865 						 NULL);
2866 
2867 	      offset += n;
2868 	      //	      }
2869 	    }
2870 	    break;
2871 	  case 0x54:
2872 	    {
2873 	      int c;
2874 
2875 	      c = offset[delta_time_size];
2876 
2877 	      //	      if(c == 0x05){
2878 	      n = ags_midi_buffer_util_get_smtpe(offset,
2879 						 NULL,
2880 						 NULL, NULL, NULL, NULL, NULL);
2881 
2882 	      offset += n;
2883 	      //	      }
2884 	    }
2885 	    break;
2886 	  case 0x58:
2887 	    {
2888 	      int c;
2889 
2890 	      //      c = ags_midi_parser_midi_getc(midi_parser);
2891 
2892 	      n = ags_midi_buffer_util_get_time_signature(offset,
2893 							  NULL,
2894 							  NULL, NULL, NULL, NULL);
2895 
2896 	      offset += n;
2897 
2898 	      //      if(c == 0x04){
2899 	      //      }
2900 	    }
2901 	    break;
2902 	  case 0x59:
2903 	    {
2904 	      int c;
2905 
2906 	      //	      c = offset[delta_time_size];
2907 
2908 	      //	      if(c == 0x02){
2909 	      n = ags_midi_buffer_util_get_key_signature(offset,
2910 							 NULL,
2911 							 NULL, NULL);
2912 
2913 	      offset += n;
2914 	      //	      }
2915 	    }
2916 	    break;
2917 	  case 0x7f:
2918 	    {
2919 	      n = ags_midi_buffer_util_get_sequencer_meta_event(NULL,
2920 								NULL,
2921 								NULL, NULL, NULL);
2922 
2923 	      offset += n;
2924 	    }
2925 	    break;
2926 	  default:
2927 	    offset += 5;
2928 	  }
2929 	}
2930 	break;
2931       default:
2932 	g_warning("bad byte");
2933       }
2934     }
2935   }
2936 
2937   if(delta_time != NULL){
2938     *delta_time = current_delta_time;
2939   }
2940 
2941   return(offset);
2942 }
2943 
2944 /**
2945  * ags_midi_buffer_util_decode:
2946  * @buffer: the midi buffer
2947  * @event: the ALSA sequencer event
2948  *
2949  * Decode @event to @buffer
2950  *
2951  * Returns: the bytes written
2952  *
2953  * Since: 3.0.0
2954  */
2955 guint
ags_midi_buffer_util_decode(guchar * buffer,snd_seq_event_t * event)2956 ags_midi_buffer_util_decode(guchar *buffer,
2957 			    snd_seq_event_t *event)
2958 {
2959   guint count;
2960 
2961   if(buffer == NULL ||
2962      event == NULL){
2963     return(0);
2964   }
2965 
2966   count = 0;
2967 
2968   switch(event->type){
2969   case SND_SEQ_EVENT_NOTEON:
2970     {
2971       guchar tmp[8];
2972 
2973       ags_midi_buffer_util_put_key_on(tmp,
2974 				      0,
2975 				      event->data.note.channel,
2976 				      event->data.note.note,
2977 				      event->data.note.velocity);
2978 
2979       count = ags_midi_buffer_util_get_varlength_size(0);
2980       memcpy(buffer, tmp + count, 3 * sizeof(guchar));
2981 
2982       count = 3;
2983     }
2984     break;
2985   case SND_SEQ_EVENT_NOTEOFF:
2986     {
2987       guchar tmp[8];
2988 
2989       ags_midi_buffer_util_put_key_off(tmp,
2990 				       0,
2991 				       event->data.note.channel,
2992 				       event->data.note.note,
2993 				       event->data.note.velocity);
2994 
2995       count = ags_midi_buffer_util_get_varlength_size(0);
2996       memcpy(buffer, tmp + count, 3 * sizeof(guchar));
2997 
2998       count = 3;
2999     }
3000     break;
3001   default:
3002     g_warning("ags_midi_buffer_util_decode() - unsupported MIDI event");
3003     break;
3004   }
3005 
3006   return(count);
3007 }
3008