home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / scc_smf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-11-28  |  20.1 KB  |  736 lines

  1. /* ScummC
  2.  * Copyright (C) 2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /** @file scc_smf.c
  21.  *  @brief A simple Standard MIDI File parser/writer.
  22.  */
  23.  
  24. #include "config.h"
  25.  
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <inttypes.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <stdio.h>
  33. #include <errno.h>
  34. #include <string.h>
  35.  
  36. #include "scc_util.h"
  37. #include "scc_fd.h"
  38. #include "scc_smf.h"
  39.  
  40.  
  41. unsigned scc_fd_read_smf_int(scc_fd_t* fd, unsigned max_size,
  42.                              uint32_t* ret) {
  43.   unsigned v = 0x80, val = 0, n = 0;
  44.   while((v & 0x80) && n < max_size) {
  45.     v = scc_fd_r8(fd);
  46.     val <<= 7;
  47.     val |= v&0x7F;
  48.     n++;
  49.   }
  50.   if(v & 0x80) return 0;
  51.   *ret = val;
  52.   return n;
  53. }
  54.  
  55. int scc_fd_write_smf_int(scc_fd_t* fd, unsigned v) {
  56.   int i;
  57.   if(!v) return scc_fd_w8(fd,v);
  58.   // Find the start
  59.   for(i = 4 ; i >= 0 ; i--)
  60.     if(v & (0x7F << (i*7))) break;
  61.   for( ; i > 0 ; i--)
  62.     scc_fd_w8(fd,0x80 | (v >> (i*7)));
  63.   return scc_fd_w8(fd,v & 0x7F);
  64. }
  65.  
  66. static int scc_smf_parse_track(scc_fd_t* fd, scc_smf_track_t* track,
  67.                                unsigned size) {
  68.   scc_smf_event_t* ev = NULL;
  69.   unsigned pos = 0;
  70.   uint64_t time = 0;
  71.   
  72.   while(pos < size) {
  73.     uint32_t delta, arg_size;
  74.     uint8_t cmd, meta = 0, runaway = 0;
  75.     int n = scc_fd_read_smf_int(fd,size-pos,&delta);
  76.     if(!n || pos + n + 2 > size) return 0;
  77.     cmd = scc_fd_r8(fd);
  78.     pos += n+1;
  79.     // Meta and sysex events
  80.     switch(cmd) {
  81.     case SMF_META_EVENT:
  82.       if(pos + 2 > size) {
  83.         scc_log(LOG_ERR,"Invalid Meta Event size.\n");
  84.         return 0;
  85.       }
  86.       meta = scc_fd_r8(fd), pos++;
  87.     case SMF_SYSEX_EVENT:
  88.     case SMF_SYSEX_CONTINUATION:
  89.       // Read the event length
  90.       if(!(n = scc_fd_read_smf_int(fd,size-pos,&arg_size))) {
  91.         scc_log(LOG_ERR,"Failed to read SysEx length.\n");
  92.         return 0;
  93.       }
  94.       pos += n;
  95.       break;
  96.     default:
  97.       if(cmd & 0x80) { // Normal event
  98.         if((cmd & 0xF0) == 0xC0 ||
  99.            (cmd & 0xF0) == 0xD0)
  100.           arg_size = 1;
  101.         else
  102.           arg_size = 2;
  103.       } else { // Runaway event
  104.         if(!track->last_event) {
  105.           scc_log(LOG_ERR,"Runaway event without a preceding event.\n");
  106.           return 0;
  107.         }
  108.         arg_size = track->last_event->args_size-1;
  109.         runaway = 1;
  110.         //vent = track->last_event->event;
  111.       }
  112.     }
  113.  
  114.     if(pos + arg_size > size) {
  115.       scc_log(LOG_ERR,"Invalid argument size.\n");
  116.       return 0;
  117.     }
  118.  
  119.     ev = malloc(sizeof(scc_smf_event_t) + runaway + arg_size);
  120.     ev->next = NULL;
  121.     ev->time = time + delta;
  122.     if(runaway) {
  123.       ev->cmd = track->last_event->cmd;
  124.       ev->args[0] = cmd;
  125.     } else
  126.       ev->cmd = cmd;
  127.     ev->meta = meta;
  128.     ev->args_size = runaway + arg_size;
  129.     if(arg_size > 0 && scc_fd_read(fd,&ev->args[runaway],arg_size) != arg_size) {
  130.       scc_log(LOG_ERR,"Failed to read arguments.\n");
  131.       free(ev);
  132.       return 0;
  133.     }
  134.     pos += arg_size;
  135.     SCC_LIST_ADD(track->events,track->last_event,ev);
  136.     time += delta;
  137.   }
  138.   
  139.   // Compute the size ourself in case the input data
  140.   // is not encoded in the shortest possible way.
  141.   track->size = scc_smf_track_get_size(track);
  142.  
  143.   return 1;
  144. }
  145.  
  146. scc_smf_t* scc_smf_parse(scc_fd_t* fd) {
  147.   scc_smf_t* smf;
  148.   uint32_t chunk, size;
  149.  
  150.   while(1) {
  151.       chunk = scc_fd_r32(fd);
  152.       // Skip scumm chunk headers
  153.       if(chunk == MKID('A','D','L',' ') ||
  154.          chunk == MKID('R','O','L',' ') ||
  155.          chunk == MKID('G','M','D',' ')) {
  156.           scc_fd_r32(fd);
  157.           continue;
  158.       }
  159.       if(chunk == MKID('M','D','h','d') ||
  160.          chunk == MKID('M','D','p','g')) {
  161.           size = scc_fd_r32be(fd);
  162.           scc_fd_seek(fd,size,SEEK_CUR);
  163.           continue;
  164.       }
  165.  
  166.       if(chunk != MKID('M','T','h','d') ||
  167.          scc_fd_r32be(fd) != 6) {
  168.           scc_log(LOG_ERR,"%s doesn't seem to be a valid MIDI file.\n",fd->filename);
  169.           return 0;
  170.       }
  171.       break;
  172.   }
  173.   
  174.   smf = calloc(1,sizeof(scc_smf_t));
  175.   smf->size = 8 + 6;
  176.   smf->type = scc_fd_r16be(fd);
  177.   scc_fd_r16be(fd); //smf->num_track = scc_fd_r16be(fd);
  178.   smf->division = scc_fd_r16be(fd);
  179.  
  180.   // Read the tracks
  181.   while(1) {
  182.     chunk = scc_fd_r32(fd);
  183.     size = scc_fd_r32be(fd);
  184.   
  185.     // EOF
  186.     if(!chunk || !size) break;
  187.  
  188.     // Not a MIDI track: skip it
  189.     if(chunk != MKID('M','T','r','k')) {
  190.       scc_log(LOG_WARN,"Skipping unknown midi chunk: %c%c%c%c\n",UNMKID(chunk));
  191.       scc_fd_seek(fd,SEEK_CUR,size);
  192.       continue;
  193.     }
  194.     smf->track = realloc(smf->track,(smf->num_track+1)*sizeof(scc_smf_track_t));
  195.     memset(&smf->track[smf->num_track],0,sizeof(scc_smf_track_t));
  196.     if(!scc_smf_parse_track(fd,&smf->track[smf->num_track],size)) {
  197.       scc_log(LOG_ERR,"Failed to parse MIDI track %d\n",smf->num_track);
  198.       scc_smf_free(smf);
  199.       return NULL;
  200.     }
  201.     smf->size += smf->track[smf->num_track].size;
  202.     smf->num_track++;
  203.   }
  204.  
  205.   return smf;
  206. }
  207.  
  208. scc_smf_t* scc_smf_parse_file(char* file) {
  209.   scc_fd_t* fd = new_scc_fd(file,O_RDONLY,0);
  210.   scc_smf_t* smf;
  211.   if(!fd) {
  212.     scc_log(LOG_ERR,"Failed to open %s: %s\n",file,strerror(errno));
  213.     return NULL;
  214.   }
  215.   smf = scc_smf_parse(fd);
  216.   scc_fd_close(fd);
  217.   return smf;
  218. }
  219.  
  220. void scc_smf_free(scc_smf_t* smf) {
  221.   if(smf->track) {
  222.     int i;
  223.     for(i = 0 ; i < smf->num_track ; i++) {
  224.       scc_smf_event_t* ev;
  225.       SCC_LIST_FREE(smf->track[i].events,ev);
  226.     }
  227.     free(smf->track);
  228.   }
  229.   free(smf);
  230. }
  231.  
  232.  
  233. unsigned scc_smf_get_int_size(unsigned v) {
  234.   int r = sizeof(v)*8/7;
  235.   if(!v) return 1;
  236.   while(!(v & (0x7F<<(7*r))))
  237.     r--;
  238.   return r+1;
  239. }
  240.  
  241. int scc_smf_track_get_size(scc_smf_track_t* track) {
  242.   unsigned size = 8; // Header
  243.   scc_smf_event_t* ev, *last = NULL;
  244.  
  245.   for(ev = track->events ; ev ; last = ev, ev = ev->next) {
  246.     // Delta
  247.     size += scc_smf_get_int_size(last ? ev->time - last->time : 0);
  248.     // Events
  249.     switch(ev->cmd) {
  250.     case SMF_META_EVENT:
  251.       size++; // Meta event type
  252.     case SMF_SYSEX_EVENT:
  253.     case SMF_SYSEX_CONTINUATION:
  254.       size++; // No runaway
  255.       size += scc_smf_get_int_size(ev->args_size);
  256.       break;
  257.     default:
  258.       // Event (if it is not a runaway)
  259.       if(!last || last->cmd != ev->cmd)
  260.         size++;
  261.     }
  262.     // Arguments
  263.     size += ev->args_size;
  264.   }
  265.  
  266.   return size;
  267. }
  268.  
  269. int scc_smf_get_size(scc_smf_t* smf) {
  270.   unsigned size = 8+6; // Header
  271.   unsigned i;
  272.  
  273.   for(i = 0 ; i < smf->num_track ; i++)
  274.     size += scc_smf_track_get_size(&smf->track[i]);
  275.  
  276.   return size;
  277. }
  278.  
  279. int scc_smf_track_write(scc_smf_track_t* track, scc_fd_t* fd) {
  280.   scc_smf_event_t* ev, *last = NULL;
  281.   // Write the header
  282.   scc_fd_w32(fd,MKID('M','T','r','k'));
  283.   scc_fd_w32be(fd,track->size-8);
  284.   for(ev = track->events ; ev ; last = ev, ev = ev->next) {
  285.     scc_fd_write_smf_int(fd,last ? ev->time - last->time : 0);
  286.     switch(ev->cmd) {
  287.     case SMF_META_EVENT:
  288.     case SMF_SYSEX_EVENT:
  289.     case SMF_SYSEX_CONTINUATION:
  290.       scc_fd_w8(fd,ev->cmd);
  291.       if(ev->cmd == SMF_META_EVENT)
  292.         scc_fd_w8(fd,ev->meta);
  293.       scc_fd_write_smf_int(fd,ev->args_size);
  294.       break;
  295.     default:
  296.       if(!last || last->cmd != ev->cmd)
  297.         scc_fd_w8(fd,ev->cmd);
  298.             
  299.     }
  300.     if(ev->args_size > 0)
  301.       scc_fd_write(fd,ev->args,ev->args_size);
  302.   }
  303.   return 1;
  304. }
  305.  
  306. int scc_smf_write(scc_smf_t* smf, scc_fd_t* fd) {
  307.   int i;
  308.   // Write the header
  309.   scc_fd_w32(fd,MKID('M','T','h','d'));
  310.   scc_fd_w32be(fd,6);
  311.   scc_fd_w16be(fd,smf->type);
  312.   scc_fd_w16be(fd,smf->num_track);
  313.   scc_fd_w16be(fd,smf->division);
  314.   // Write the tracks
  315.   for(i = 0 ; i < smf->num_track ; i++)
  316.     scc_smf_track_write(&smf->track[i],fd);
  317.   return 1;
  318. }
  319.  
  320. int scc_smf_write_file(scc_smf_t* smf, char* path) {
  321.   scc_fd_t* fd = new_scc_fd(path,O_WRONLY|O_CREAT|O_TRUNC,0);
  322.  
  323.   if(!fd) {
  324.     printf("Failed to open %s for writing.\n",path);
  325.     return 0;
  326.   }
  327.   
  328.   if(!scc_smf_write(smf,fd)) {
  329.     printf("Failed to write MIDI file %s.\n",path);
  330.     scc_fd_close(fd);
  331.     return 0;
  332.   }
  333.   
  334.   scc_fd_close(fd);
  335.   return 1;
  336. }
  337.  
  338.  
  339. int scc_smf_remove_track(scc_smf_t* smf, unsigned track) {
  340.   scc_smf_event_t* ev;
  341.  
  342.   if(track >= smf->num_track) return 0;
  343.  
  344.   SCC_LIST_FREE(smf->track[track].events,ev);
  345.   smf->size -= smf->track[track].size;
  346.  
  347.   if(track < smf->num_track-1)
  348.     memmove(&smf->track[track],&smf->track[track+1],
  349.             (smf->num_track-track-1)*sizeof(scc_smf_track_t));
  350.  
  351.   smf->num_track--;
  352.  
  353.   return 1;
  354. }
  355.  
  356. int scc_smf_merge_track(scc_smf_t* smf, unsigned trackA, unsigned trackB) {
  357.   scc_smf_event_t *evA,*evB = NULL,*evBnext = NULL,*evEnd = NULL;
  358.   
  359.   if(trackA == trackB ||
  360.      trackA >= smf->num_track ||
  361.      trackB >= smf->num_track)
  362.     return 0;
  363.   
  364.   if(smf->track[trackA].last_event->cmd == SMF_META_EVENT &&
  365.      smf->track[trackA].last_event->meta == 0x2F) {
  366.     evEnd = smf->track[trackA].last_event;
  367.     for(evA = smf->track[trackA].events ; evA->next ; evB = evA, evA = evA->next);
  368.     evB->next = NULL;
  369.     smf->track[trackA].last_event = evB;
  370.   }
  371.   if(smf->track[trackB].last_event->cmd == SMF_META_EVENT &&
  372.      smf->track[trackB].last_event->meta == 0x2F) {
  373.     for(evA = smf->track[trackB].events ; evA->next ; evB = evA, evA = evA->next);
  374.     if(evB) {
  375.       evB->next = NULL;
  376.       smf->track[trackB].last_event = evB;
  377.     } else
  378.       smf->track[trackB].last_event = smf->track[trackB].events = NULL;
  379.     if(!evEnd) evEnd = evA->next;
  380.     else free(evA);
  381.   }
  382.     
  383.   evA = smf->track[trackA].events;
  384.   for(evB = smf->track[trackB].events ; evB ; evB = evBnext) {
  385.     evBnext = evB->next;
  386.     if(!evA) {
  387.       evB->next = NULL;
  388.       smf->track[trackA].last_event = smf->track[trackA].events = evB;
  389.     } else {
  390.       while(evA->next && evA->next->time <= evB->time)
  391.         evA = evA->next;
  392.       evB->next = evA->next;
  393.       evA->next = evB;
  394.       if(!evB->next)
  395.         smf->track[trackA].last_event = evB;
  396.     }
  397.   }
  398.   
  399.   if(evEnd) {
  400.     while(evA->next)
  401.       evA = evA->next;
  402.     evA->next = evEnd;
  403.     smf->track[trackA].last_event = evEnd;
  404.   }
  405.  
  406.   smf->track[trackA].size = scc_smf_track_get_size(&smf->track[trackA]);
  407.   smf->track[trackB].events = smf->track[trackB].last_event = NULL;
  408.  
  409.   return scc_smf_remove_track(smf,trackB);
  410. }
  411.  
  412. void scc_smf_dump(scc_smf_t* smf) {
  413.   int i,j;
  414.   scc_smf_event_t* ev;
  415.   
  416.   scc_log(LOG_MSG,"Total size: %d\n",smf->size);
  417.   scc_log(LOG_MSG,"Type: %d\n",smf->type);
  418.   scc_log(LOG_MSG,"Division: %d\n",smf->division);
  419.   
  420.   for(i = 0 ; i < smf->num_track ; i++) {
  421.     scc_log(LOG_MSG,"Track %d (%d):\n",i,smf->track[i].size);
  422.     for(ev = smf->track[i].events ; ev ; ev = ev->next) {
  423.       scc_log(LOG_MSG,"%6" PRIu64 "  : %02X    - ",ev->time, ev->cmd);
  424.       switch(ev->cmd & 0xF0) {
  425.       case 0x80:
  426.         scc_log(LOG_MSG,"Note off (chan: %d)",ev->cmd & 0x0F);
  427.         break;
  428.       case 0x90:
  429.         scc_log(LOG_MSG,"Note on (chan: %d)",ev->cmd & 0x0F);
  430.         break;
  431.       case 0xA0:
  432.         scc_log(LOG_MSG,"Aftertouch (chan: %d)",ev->cmd & 0x0F);
  433.         break;
  434.       case 0xB0:
  435.         if(ev->args[0] > 0x77) {
  436.           scc_log(LOG_MSG,"Chan mode (%02X)",ev->cmd & 0x0F);
  437.           switch(ev->args[0]) {
  438.           case 0x79:
  439.             scc_log(LOG_MSG," [Reset All Controllers]");
  440.             break;
  441.           case 0x7A:
  442.             scc_log(LOG_MSG," [Local Control]");
  443.             break;
  444.           case 0x7B:
  445.             scc_log(LOG_MSG," [All Notes Off]");
  446.             break;
  447.           case 0x7C:
  448.             scc_log(LOG_MSG," [Omni Mode Off]");
  449.             break;
  450.           case 0x7D:
  451.             scc_log(LOG_MSG," [Omni Mode On]");
  452.             break;
  453.           case 0x7E:
  454.             scc_log(LOG_MSG," [Mono Mode On]");
  455.             break;
  456.           case 0x7F:
  457.             scc_log(LOG_MSG," [Poly Mode On]");
  458.             break;
  459.           }
  460.         } else {
  461.           scc_log(LOG_MSG,"Control change (chan: %d)",ev->cmd & 0x0F);
  462.           switch(ev->args[0]) {
  463.           case 0x01:
  464.             scc_log(LOG_MSG," [Mod Wheel]");
  465.             break;
  466.           case 0x02:
  467.             scc_log(LOG_MSG," [Breath ctrl]");
  468.             break;
  469.           case 0x04:
  470.             scc_log(LOG_MSG," [Foot ctrl]");
  471.             break;
  472.           case 0x05:
  473.             scc_log(LOG_MSG," [Portamento Time]");
  474.             break;
  475.           case 0x06:
  476.             scc_log(LOG_MSG," [Data Entry MSB]");
  477.             break;
  478.           case 0x07:
  479.             scc_log(LOG_MSG," [Volume]");
  480.             break;
  481.           case 0x08:
  482.             scc_log(LOG_MSG," [Balance]");
  483.             break;
  484.           case 0x0A:
  485.             scc_log(LOG_MSG," [Pan]");
  486.             break;
  487.           case 0x0B:
  488.             scc_log(LOG_MSG," [Expression ctrl]");
  489.             break;
  490.           case 0x10:
  491.             scc_log(LOG_MSG," [General Purpose 1]");
  492.             break;
  493.           case 0x11:
  494.             scc_log(LOG_MSG," [General Purpose 2]");
  495.             break;
  496.           case 0x12:
  497.             scc_log(LOG_MSG," [General Purpose 3]");
  498.             break;
  499.           case 0x13:
  500.             scc_log(LOG_MSG," [General Purpose 4]");
  501.             break;
  502.           case 0x40:
  503.             scc_log(LOG_MSG," [Sustain]");
  504.             break;
  505.           case 0x41:
  506.             scc_log(LOG_MSG," [Portamento]");
  507.             break;
  508.           case 0x42:
  509.             scc_log(LOG_MSG," [Sustenuto]");
  510.             break;
  511.           case 0x43:
  512.             scc_log(LOG_MSG," [Soft Pedal]");
  513.             break;
  514.           case 0x45:
  515.             scc_log(LOG_MSG," [Hold 2]");
  516.             break;
  517.           case 0x50:
  518.             scc_log(LOG_MSG," [General Purpose 5]");
  519.             break;
  520.           case 0x51:
  521.             scc_log(LOG_MSG," [Temp Change (General Purpose 6)]");
  522.             break;
  523.           case 0x52:
  524.             scc_log(LOG_MSG," [General Purpose 7]");
  525.             break;
  526.           case 0x53:
  527.             scc_log(LOG_MSG," [General Purpose 8]");
  528.             break;
  529.           case 0x5B:
  530.             scc_log(LOG_MSG," [Ext Effects Depth]");
  531.             break;
  532.           case 0x5C:
  533.             scc_log(LOG_MSG," [Tremelo Depth]");
  534.             break;
  535.           case 0x5D:
  536.             scc_log(LOG_MSG," [Chorus Depth]");
  537.             break;
  538.           case 0x5E:
  539.             scc_log(LOG_MSG," [Detune Depth (Celeste Depth)]");
  540.             break;
  541.           case 0x5F:
  542.             scc_log(LOG_MSG," [Phaser Depth]");
  543.             break;
  544.           case 0x60:
  545.             scc_log(LOG_MSG," [Data Increment]");
  546.             break;
  547.           case 0x61:
  548.             scc_log(LOG_MSG," [Data Decrement]");
  549.             break;
  550.           case 0x62:
  551.             scc_log(LOG_MSG," [Non-Registered Param LSB]");
  552.             break;
  553.           case 0x63:
  554.             scc_log(LOG_MSG," [Non-Registered Param MSB]");
  555.             break;
  556.           case 0x64:
  557.             scc_log(LOG_MSG," [Registered Param LSB]");
  558.             break;
  559.           case 0x65:
  560.             scc_log(LOG_MSG," [Registered Param MSB]");
  561.             break;
  562.           }
  563.           if(ev->args[0] >= 0x20 &&
  564.              ev->args[0] <  0x40)
  565.             scc_log(LOG_MSG," [Set MSB]");
  566.         }
  567.         break;
  568.       case 0xC0:
  569.         scc_log(LOG_MSG,"Program Change (chan: %d)",ev->cmd & 0x0F);
  570.         break;
  571.       case 0xD0:
  572.         scc_log(LOG_MSG,"Chan. Pressure (chan: %d)",ev->cmd & 0x0F);
  573.         break;
  574.       case 0xE0:
  575.         scc_log(LOG_MSG,"Pitch Wheel (chan: %d)",ev->cmd & 0x0F);
  576.         break;
  577.       case 0xF0:
  578.         switch(ev->cmd & 0x0F) {
  579.         case 0x00:
  580.         case 0x07:
  581.           scc_log(LOG_MSG,"SysEx");
  582.           switch(ev->args[0]) {
  583.           case 0x41:
  584.               scc_log(LOG_MSG," - Roland");
  585.               break;
  586.           case 0x7C:
  587.               scc_log(LOG_MSG," - YM2612");
  588.               break;
  589.           case 0x7D:
  590.               scc_log(LOG_MSG," - iMUSE - ");
  591.               switch(ev->args[1]) {
  592.               case 0x00:
  593.                   scc_log(LOG_MSG,"Allocate new part");
  594.                   break;
  595.               case 0x01:
  596.                   scc_log(LOG_MSG,"Shut down a part");
  597.                   break;
  598.               case 0x02:
  599.                   scc_log(LOG_MSG,"Start of song");
  600.                   break;
  601.               case 0x10:
  602.                   scc_log(LOG_MSG,"Adlib instrument definition (Part)");
  603.                   break;
  604.               case 0x11:
  605.                   scc_log(LOG_MSG,"Adlib instrument definition (Global)");
  606.                   break;
  607.               case 0x21:
  608.                   scc_log(LOG_MSG,"Parameter adjust");
  609.                   break;
  610.               case 0x30:
  611.                   scc_log(LOG_MSG,"Hook - jump");
  612.                   break;
  613.               case 0x31:
  614.                   scc_log(LOG_MSG,"Hook - global transpose");
  615.                   break;
  616.               case 0x32:
  617.                   scc_log(LOG_MSG,"Hook - part on/off");
  618.                   break;
  619.               case 0x33:
  620.                   scc_log(LOG_MSG,"Hook - set volume");
  621.                   break;
  622.               case 0x34:
  623.                   scc_log(LOG_MSG,"Hook - set program");
  624.                   break;
  625.               case 0x35:
  626.                   scc_log(LOG_MSG,"Hook - set transpose");
  627.                   break;
  628.               case 0x40:
  629.                   scc_log(LOG_MSG,"Marker");
  630.                   break;
  631.               case 0x50:
  632.                   scc_log(LOG_MSG,"Set loop");
  633.                   break;
  634.               case 0x51:
  635.                   scc_log(LOG_MSG,"Clear loop");
  636.                   break;
  637.               case 0x60:
  638.                   scc_log(LOG_MSG,"Set instrument");
  639.                   break;
  640.               }
  641.           }
  642.           break;
  643.         case 0x08:
  644.           scc_log(LOG_MSG,"Timing clock");
  645.           break;
  646.         case 0x09:
  647.           scc_log(LOG_MSG,"Reserved");
  648.           break;
  649.         case 0x0A:
  650.           scc_log(LOG_MSG,"Start");
  651.           break;
  652.         case 0x0B:
  653.           scc_log(LOG_MSG,"Continue");
  654.           break;
  655.         case 0x0C:
  656.           scc_log(LOG_MSG,"Stop");
  657.           break;
  658.         case 0x0D:
  659.           scc_log(LOG_MSG,"Reserved");
  660.           break;
  661.         case 0x0E:
  662.           scc_log(LOG_MSG,"Active Sensing");
  663.           break;
  664.         case 0x0F:
  665.           scc_log(LOG_MSG,"\b\b\b\b\b%02X - Meta event ",ev->meta);
  666.           switch(ev->meta) {
  667.           case 0x00:
  668.             scc_log(LOG_MSG,"(Seq Num)");
  669.             break;
  670.           case 0x01:
  671.             scc_log(LOG_MSG,"(Text)");
  672.             break;
  673.           case 0x02:
  674.             scc_log(LOG_MSG,"(Copyright)");
  675.             break;
  676.           case 0x03:
  677.             scc_log(LOG_MSG,"(Seq name)");
  678.             break;
  679.           case 0x04:
  680.             scc_log(LOG_MSG,"(Instrument name)");
  681.             break;
  682.           case 0x05:
  683.             scc_log(LOG_MSG,"(Lyric)");
  684.             break;
  685.           case 0x06:
  686.             scc_log(LOG_MSG,"(Marker)");
  687.             break;
  688.           case 0x07:
  689.             scc_log(LOG_MSG,"(Cue point)");
  690.             break;
  691.           case 0x20:
  692.             scc_log(LOG_MSG,"(Chan prefix)");
  693.             break;
  694.           case 0x21:
  695.             scc_log(LOG_MSG,"(Port prefix)");
  696.             break;
  697.           case 0x2F:
  698.             scc_log(LOG_MSG,"(End of track)");
  699.             break;
  700.           case 0x51:
  701.             scc_log(LOG_MSG,"(Set tempo)");
  702.             break;
  703.           case 0x54:
  704.             scc_log(LOG_MSG,"(SMPTE Offset)");
  705.             break;
  706.           case 0x58:
  707.             scc_log(LOG_MSG,"(Time sig)");
  708.             break;
  709.           case 0x59:
  710.             scc_log(LOG_MSG,"(Key sig)");
  711.             break;
  712.           case 0x7F:
  713.             scc_log(LOG_MSG,"(Sequencer-Specific event)");
  714.             break;
  715.           default:
  716.             scc_log(LOG_MSG,"(%02X)",ev->meta);
  717.           }
  718.         default:
  719.           // Fallback
  720.           ; // kill gcc warning
  721.         }
  722.         break;
  723.       default:
  724.         scc_log(LOG_MSG,"%02X (%d)",ev->cmd,ev->args_size);
  725.       }
  726.       for(j = 0 ; j < ev->args_size ; j++) {
  727.         if(j % 16 == 0) scc_log(LOG_MSG,"\n         ");
  728.         scc_log(LOG_MSG," %02X",ev->args[j]);
  729.       }
  730.       scc_log(LOG_MSG,"\n");
  731.     }
  732.     scc_log(LOG_MSG,"\n");
  733.   }
  734.  
  735. }
  736.