home *** CD-ROM | disk | FTP | other *** search
/ Computer Music Interactif…cial Edition 1999 Winter / cd 3.iso / mac / Mac / Shares / Midishare™1.68 / Development Tools / Sources Examples / Other MidiShare Examples / midiplay / MidiFile.c next >
Encoding:
C/C++ Source or Header  |  1992-05-14  |  41.4 KB  |  1,380 lines  |  [TEXT/MPS ]

  1. /*
  2.  *
  3.  *    MIDIFILE.C
  4.  *
  5.  *    fonctions de lecture d'un fichier au format MIDIFILE 1.00
  6.  *
  7.  *    GRAME
  8.  *  sources originales développées sur Atari St                    D.F.
  9.  *     Octobre 91    fonctions d'écriture                               B. MERLIER
  10.  *    Janvier 92    refonte et redéfinition des routines de base       D.F.
  11.  *  Mars    92  intégration des événements MidiFile dans MidiShare D.F.
  12.  *    Avril    92  ajout des fonction de lecture/écriture d'un événement
  13.  *              ouverture, fermeture et création de piste          D.F.
  14.  *
  15.  */
  16.  
  17. #include <Stdio.h>
  18. #include <StdLib.h>
  19. #include <String.h>
  20. #include <MidiShare.h>
  21.  
  22. #include "MidiFile.h"
  23.  
  24.  
  25. /*--------------------------------------------------------------------------*/
  26. /* définition de constantes                                                    */
  27.  
  28. #define MDF_MThd    "MThd"                    /* en-tête de fichier            */
  29. #define MDF_MTrk    "MTrk"                    /* en-tête de piste                */
  30.  
  31. #define SRC_VERSION    110                        /* version des sources            */
  32. #define MDF_VERSION 100                        /* version du standard MidiFile    */
  33.  
  34. #define offset_ntrks    10                    /* offset du nombre de pistes    */
  35.                                             /* rel. au début du fichier        */
  36. #define offset_trkLen    4                    /* offset du la longueur de     */
  37.                                             /* piste, rel. au header        */
  38.  
  39.  
  40. /*--------------------------------------------------------------------------*/
  41. /* déclaration de fonctions                                                    */
  42. static MidiEvPtr read_undef( midiFILE *fd, short status);
  43. static MidiEvPtr read_sysex( midiFILE *fd, short status);
  44. static MidiEvPtr read_2DataEv( midiFILE *fd, short status);
  45. static MidiEvPtr read_1DataEv( midiFILE *fd, short status);
  46. static MidiEvPtr read_0DataEv( midiFILE *fd, short status);
  47.  
  48. static MidiEvPtr read_text( midiFILE *fd, long len, short type);
  49. static MidiEvPtr read_endTrack( midiFILE *fd, long len, short);
  50. static MidiEvPtr read_tempo( midiFILE *fd, long len, short);
  51. static MidiEvPtr read_keySign( midiFILE *fd, long len, short);
  52. static MidiEvPtr read_timeSign( midiFILE *fd, long len, short);
  53. static MidiEvPtr read_seqNum( midiFILE *fd, long len, short);
  54. static MidiEvPtr read_chanPref( midiFILE *fd, long len, short);
  55. static MidiEvPtr read_smpte( midiFILE *fd, long len, short);
  56.  
  57. static Boolean write_note( midiFILE *fd, MidiEvPtr ev, short status);
  58. static Boolean write_2DataEv( midiFILE *fd, MidiEvPtr ev, short status);
  59. static Boolean write_1DataEv( midiFILE *fd, MidiEvPtr ev, short status);
  60. static Boolean write_0DataEv( midiFILE *fd, MidiEvPtr ev, short status);
  61. static Boolean dont_write( midiFILE *, MidiEvPtr , short);
  62. static Boolean write_sysex( midiFILE *fd, MidiEvPtr ev, short);
  63. static Boolean write_Ctrl14b( midiFILE *fd, MidiEvPtr ev, short);
  64. static Boolean write_RegP( midiFILE *fd, MidiEvPtr ev, short);
  65. static Boolean write_NRegP( midiFILE *fd, MidiEvPtr ev, short);
  66.  
  67. static Boolean write_SeqNum( midiFILE *fd, MidiEvPtr ev, short);
  68. static Boolean write_texte( midiFILE *fd, MidiEvPtr ev, short status);
  69. static Boolean write_chanPref( midiFILE *fd, MidiEvPtr ev, short);
  70. static Boolean write_endTrack( midiFILE *fd, MidiEvPtr, short);
  71. static Boolean write_tempo( midiFILE *fd, MidiEvPtr ev, short);
  72. static Boolean write_smpte( midiFILE *fd, MidiEvPtr ev, short);
  73. static Boolean write_timeSign( midiFILE *fd, MidiEvPtr, short);
  74. static Boolean write_keySign( midiFILE *fd, MidiEvPtr, short);
  75.  
  76.  
  77. /*--------------------------------------------------------------------------*/
  78. /* variables globales du module                                                */
  79.  
  80. int MidiFile_errno;                            /* pour le gestion des erreurs    */
  81.  
  82.  
  83. typedef MidiEvPtr (* ReadFunc)( midiFILE *fd, short status);
  84. typedef MidiEvPtr (* ReadMetaFunc)( midiFILE *fd, long len, short type);
  85. typedef Boolean (* WriteFunc)( midiFILE *fd, MidiEvPtr ev, short status);
  86.  
  87.  
  88. /*------------------- correspondance type/octet de status ------------------*/
  89. static unsigned char codeTbl[]=
  90.     { 0x90, 0x90, 0x80, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0,
  91.       0xf2, 0xf3, 0xf8, 0xfa, 0xfb, 0xfc, 0xf6, 0xfe,
  92.       0xff, 0xf0, 0xf7
  93.     };
  94.     
  95. /*------------------- correspondance octet de status/type ------------------*/
  96. static char typeTbl[]=
  97.     { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  98.       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  99.       3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  100.       4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  101.       5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  102.       6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  103.       7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  104.       17,130,8,9,0,0,14,18,10,0,11,12,13,0,15,16
  105.      };
  106.  
  107. /*------------------- correspondance type/méta event -----------------------*/
  108. /* cette table prend en charge également les événements de type QFrame        */
  109. /* Ctrl14Bits, NonRegParam et RegParam                                        */
  110.  
  111. static char metaCodeTbl[]=
  112.     { 
  113.         0xf1, 0xb0, 0xb0, 0xb0,
  114.         0, 1, 2, 3, 4, 5, 6, 7,
  115.         0x20, 0x2f, 0x51, 0x54,
  116.         0x58, 0x59, 0x7f
  117.     };
  118.  
  119. /*------------------- correspondance méta event/type ----------------------*/
  120. static char metaTypeTbl[]=
  121.     { 1,2,3,4,5,6,7,8,                /*  0-7            */
  122.       0,0,0,0,0,0,0,0,                /*  8-15 undefs    */
  123.       0,0,0,0,0,0,0,0,                /* 16-23 undefs    */
  124.       0,0,0,0,0,0,0,0,                /* 24-31        */
  125.       9,0,0,0,0,0,0,0,                /* 32-39 undefs    */
  126.       0,0,0,0,0,0,0,10,                /* 40-47        */
  127.       0,0,0,0,0,0,0,0,                /* 48-55 undefs    */
  128.       0,0,0,0,0,0,0,0,                /* 56-63 undefs    */
  129.       0,0,0,0,0,0,0,0,                /* 64-71 undefs    */
  130.       0,0,0,0,0,0,0,0,                /* 72-79 undefs    */
  131.       0,11,0,0,12,0,0,0,            /* 80-87        */
  132.       13,14,0,0,0,0,0,0,            /* 88-95        */
  133.       0,0,0,0,0,0,0,0,                /* 96-103  undefs     */
  134.       0,0,0,0,0,0,0,0,                /* 104-111 undefs    */
  135.       0,0,0,0,0,0,0,0,                /* 112-119 undefs    */
  136.       0,0,0,0,0,0,0,15                /* 120-126 undefs    */
  137.      };
  138.  
  139.  
  140. /*------------------- les fonctions de lecture d'un événement --------------*/
  141. static ReadFunc ReadEvTbl[]=
  142.     {
  143.             read_2DataEv,        /* $80 : 1 typeKeyOff        */
  144.             read_2DataEv,        /* $90 : 2 typeKeyOn        */
  145.             read_2DataEv,        /* $a0 : 3 typeKeyPress        */
  146.             read_2DataEv,        /* $b0 : 4 typeCtrlChange    */
  147.             read_1DataEv,        /* $c0 : 5 typeProgChange    */
  148.             read_1DataEv,        /* $d0 : 6 typeChanPress    */
  149.             read_2DataEv,        /* $e0 : 7 typePitchWheel    */
  150.  
  151.             read_sysex,            /* $f0 :  17 typeSysEx            */
  152.             read_1DataEv,        /* $f1 : 130 typeQuarterFrame    */    
  153.             read_2DataEv,        /* $f2 :   8 typeSongPos        */
  154.             read_1DataEv,        /* $f3 :   9 typeSongSel        */
  155.             read_undef,            /* $f4                            */
  156.             read_undef,            /* $f5                            */
  157.             read_0DataEv,        /* $f6 :  14 typeTune            */
  158.             read_sysex,            /* $f7 :  18 typeStream            */
  159.             read_0DataEv,        /* $f8 :  10 typeClock            */
  160.             read_undef,            /* $f9                            */
  161.             read_0DataEv,        /* $fa :  11 typeStart            */
  162.             read_0DataEv,        /* $fb :  12 typeContinue        */
  163.             read_0DataEv,        /* $fc :  13 typeStop            */
  164.             read_undef,            /* $fd                            */
  165.             read_0DataEv,        /* $fe :  15 typeActiveSens        */
  166.             read_undef,            /* $ff :  16 typeReset            */
  167.     };
  168.     
  169. static ReadMetaFunc ReadExtTbl[]=
  170.     {
  171.             read_undef,            /* type non défini        */
  172.             read_seqNum,        /* 134 typeSeqNum        */
  173.             read_text,            /* 135 typeText            */
  174.             read_text,            /* 136 typeCopyright    */
  175.             read_text,            /* 137 typeSeqName        */
  176.             read_text,            /* 138 typeInstrName    */
  177.             read_text,            /* 139 typeLyric        */
  178.             read_text,            /* 140 typeMarker        */
  179.             read_text,            /* 141 typeCuePoint        */
  180.             read_chanPref,        /* 142 typeChanPrefix    */
  181.             read_endTrack,        /* 143 typeEndTrack        */
  182.             read_tempo,            /* 144 typeTempo        */
  183.             read_smpte,            /* 145 typeSMPTEOffset    */
  184.             read_timeSign,        /* 146 typeTimeSign        */
  185.             read_keySign,        /* 147 typeKeySign        */
  186.             read_text            /* 148 typeSpecific        */
  187.     };
  188.  
  189. static WriteFunc WriteEvTbl[]=
  190.     {
  191.             write_note,            /* 0 typeNote            */
  192.             write_2DataEv,        /* 1 typeKeyOn            */
  193.             write_2DataEv,        /* 2 typeKeyOff            */
  194.             write_2DataEv,        /* 3 typeKeyPress        */
  195.             write_2DataEv,        /* 4 typeCtrlChange        */
  196.             write_1DataEv,        /* 5 typeProgChange        */
  197.             write_1DataEv,        /* 6 typeChanPress        */
  198.             write_2DataEv,        /* 7 typePitchWheel        */
  199.             write_2DataEv,        /* 8 typeSongPos        */
  200.             write_1DataEv,        /* 9 typeSongSel        */
  201.             write_0DataEv,        /* 10 typeClock            */
  202.             write_0DataEv,        /* 11 typeStart            */
  203.             write_0DataEv,        /* 12 typeContinue        */
  204.             write_0DataEv,        /* 13 typeStop            */
  205.             write_0DataEv,        /* 14 typeTune            */
  206.             write_0DataEv,        /* 15 typeActiveSens    */
  207.             dont_write,            /* 16 typeReset            */
  208.             write_sysex,        /* 17 typeSysEx            */
  209.             write_sysex,        /* 18 typeStream        */
  210.     };
  211.  
  212.  
  213. static WriteFunc WriteExtTbl[]=
  214.     {
  215.             write_1DataEv,        /* 130 typeQuarterFrame    */    
  216.             write_Ctrl14b,        /* 131 typeCtrl14b        */
  217.             write_NRegP,        /* 132 typeNonRegParam    */
  218.             write_RegP,            /* 133 typeRegParam        */
  219.  
  220.             write_SeqNum,        /* 134 typeSeqNum        */
  221.             write_texte,        /* 135 typeText            */
  222.             write_texte,        /* 136 typeCopyright    */
  223.             write_texte,        /* 137 typeSeqName        */
  224.             write_texte,        /* 138 typeInstrName    */
  225.             write_texte,        /* 139 typeLyric        */
  226.             write_texte,        /* 140 typeMarker        */
  227.             write_texte,        /* 141 typeCuePoint        */
  228.  
  229.             write_chanPref,        /* 142 typeChanPrefix    */
  230.             write_endTrack,        /* 143 typeEndTrack        */
  231.             write_tempo,        /* 144 typeTempo        */
  232.             write_smpte,        /* 145 typeSMPTEOffset    */
  233.             write_timeSign,        /* 146 typeTimeSign        */
  234.             write_keySign,        /* 147 typeKeySign        */
  235.             write_texte            /* 148 typeSpecific        */
  236.     };
  237.  
  238.  
  239. /*--------------------------------------------------------------------------*/
  240. /* Lecture et d'écriture des données codées en longueur variable            */
  241. /*--------------------------------------------------------------------------*/
  242.  
  243. /*--------------------------------------------------------------------------*/
  244. static unsigned long ReadVarLen( register midiFILE *fd)
  245. {
  246.     register FILE *fp;
  247.     register unsigned long val;
  248.     register short c;
  249.  
  250.     fp= fd->fd;
  251.     if ((val = (unsigned long) getc(fp)) & 0x80)
  252.     {
  253.         val &= 0x7F;
  254.         do {
  255.             val=  (val<< 7) + ((c= getc(fp)) & 0x7F);
  256.             fd->_cnt--;                            /* m.a.j. de reste à lire    */
  257.         } while (c & 0x80 && !feof( fp));
  258.     }
  259.     fd->_cnt--;                                    /* m.a.j. de reste à lire    */
  260.     return val;
  261. }
  262.  
  263. /*--------------------------------------------------------------------------*/
  264. static Boolean WriteVarLen( register unsigned long val, register FILE *fd)
  265. {
  266.     register unsigned long buf;
  267.  
  268.     buf= val & 0x7F;
  269.     while( val >>= 7)
  270.     {
  271.         buf <<= 8;
  272.         buf |= 0x80;
  273.         buf += (val & 0x7F);
  274.     }
  275.     while( true)
  276.     {
  277.         putc( buf, fd);
  278.         if( buf & 0x80) buf >>= 8;
  279.         else             break;
  280.     }
  281.     return !ferror( fd);
  282. }
  283.  
  284.  
  285.  
  286. /*--------------------------------------------------------------------------*/
  287. /* Lecture et écriture d'un en-tête de fichier MidiFile                        */
  288. /*    header =  'MThd'    00 06    format    nbtracks    division/battue            */
  289. /*--------------------------------------------------------------------------*/
  290.  
  291. /*--------------------------------------------------------------------------*/
  292. static Boolean ReadMdfHeader( register midiFILE *fd)
  293. {
  294.     MDF_Header h;
  295.     register Boolean ret= true;                /* code de retour                */
  296.     
  297.     if( fread( &h, sizeof( MDF_Header),1, fd->fd)== 1)     /* lit l'en-tête    */
  298.     {
  299.         if( strncmp( h.id, MDF_MThd, 4) || h.len!= 6)
  300.         {
  301.             MidiFile_errno= MidiFileErrFrmt;/* erreur de format du fichier    */
  302.             ret= false;
  303.         }
  304.         else 
  305.         {
  306.             fd->format= h.format;            /* format du fichier            */
  307.             fd->ntrks= h.ntrks;                /* nbre de pistes du fichier     */
  308.             fd->time= h.time;                /* représentation du temps        */
  309.         }
  310.     }
  311.     else ret= false;
  312.     return ret;
  313. }
  314.  
  315. /*--------------------------------------------------------------------------*/
  316. static Boolean Create_mdfHeader( register midiFILE *fd,  short format, short time)
  317. {
  318.     MDF_Header h;
  319.     register Boolean ret;                    /* code de retour                */
  320.  
  321.     strcpy( h.id, MDF_MThd);                /* recopie de l'en-tête            */
  322.     h.len= 6;                                /* longueur des données            */
  323.     h.ntrks= 0;                                /* nbre de pistes = 0            */
  324.     h.format= format;                        /* format du fichier            */
  325.     h.time= time;                            /* représentation du temps        */
  326.     ret= (fwrite( &h, sizeof( MDF_Header), 1, fd->fd)== 1);
  327.     return ret;
  328. }
  329.  
  330.  
  331.  
  332. /*--------------------------------------------------------------------------*/
  333. /* Lecture et écriture d'un en-tête de piste                                */
  334. /*    header =  'MTrk' <long len>                                                */
  335. /*--------------------------------------------------------------------------*/
  336.  
  337. /*--------------------------------------------------------------------------*/
  338. static Boolean ReadTrkHeader( register FILE *fd,  register MDF_Trk *h)
  339. {
  340.     Boolean ret= true;                        /* code de retour                */
  341.     
  342.     if( fread( h, sizeof( MDF_Trk), 1, fd)== 1)  /* lecture de l'en-tête    */
  343.     {
  344.         if( strncmp( h->id, MDF_MTrk, 4))
  345.         {
  346.             MidiFile_errno= MidiFileErrFrmt;/* erreur de format du fichier    */
  347.             ret= false;
  348.         }
  349.     }
  350.     else ret= false;
  351.     return ret;
  352. }
  353.  
  354. /*--------------------------------------------------------------------------*/
  355. static Boolean Create_trkHeader( register FILE *fd,  long len)
  356. {
  357.     Boolean ret= true;                        /* code de retour                */
  358.     MDF_Trk h;                                /* en-tête de piste                */
  359.  
  360.     strcpy( h.id, MDF_MTrk);                /* recopie de l'en-tête            */
  361.     h.len= len;                                /* longueur des données            */
  362.     ret= (fwrite( &h, sizeof( MDF_Trk), 1, fd)== 1);
  363.     return ret;
  364. }
  365.  
  366.  
  367. /*--------------------------------------------------------------------------*/
  368. /* Fonction de positionnement dans un fichier                                */
  369. /*--------------------------------------------------------------------------*/
  370.  
  371. /*--------------------------------------------------------------------------*/
  372. Boolean MidiFileChooseTrack( midiFILE *fd, short numPiste)
  373. {
  374.     MDF_Trk h;
  375.  
  376.     MidiFile_errno= MidiFileNoErr;
  377.     if( numPiste >= fd->ntrks)
  378.     {
  379.         MidiFile_errno= MidiFileErrNoTrack;
  380.         return false;
  381.     }
  382.     if( fseek( fd->fd, sizeof( MDF_Header), SEEK_SET))    /* pos = piste 0    */
  383.         return false;
  384.     while( numPiste--)
  385.         if( !ReadTrkHeader( fd->fd, &h) || fseek( fd->fd, h.len, SEEK_CUR))
  386.             return false;
  387.     return true;
  388. }
  389.  
  390.  
  391. /*--------------------------------------------------------------------------*/
  392. /*                                                                            */
  393. /*                       Fonctions d'écriture des événements                    */
  394. /*                                                                            */
  395. /*--------------------------------------------------------------------------*/
  396.  
  397. /*--------------------------------------------------------------------------*/
  398. /*     Ecriture des méta-événements                                            */
  399. /*--------------------------------------------------------------------------*/
  400.  
  401. /*--------------------------------------------------------------------------*/
  402. static Boolean write_keySign( midiFILE *f, register MidiEvPtr ev, short)
  403. {
  404.     register FILE *fd;
  405.     
  406.     fd= f->fd;
  407.     putc( META, fd);                        /* header du méta evt    */
  408.     putc( MDF_Ton, fd);                        /* type de méta evt        */
  409.     putc( MDF_TonLen, fd);                    /* longueur                */
  410.     putc( KSTon(ev), fd);                    /* les altérations        */
  411.     putc( KSMode(ev), fd);                    /* le mode: maj/min        */
  412.     return !ferror( fd);    
  413. }
  414.  
  415. /*--------------------------------------------------------------------------*/
  416. static Boolean write_timeSign( midiFILE *f, register MidiEvPtr ev, short)
  417. {
  418.     register FILE *fd;
  419.     
  420.     fd= f->fd;
  421.     putc( META, fd);                        /* header du méta evt    */
  422.     putc( MDF_Meas, fd);                    /* type de méta evt        */
  423.     putc( MDF_MeasLen, fd);                    /* longueur                */
  424.     putc( TSNum(ev), fd);                    /* le numerateur        */
  425.     putc( TSDenom(ev), fd);                    /* le dénominateur        */
  426.     putc( TSClocks(ev), fd);                /* nbre de clocks        */
  427.     putc( TS32nd(ev), fd);                    /* nbre de 32ieme de note*/
  428.     return !ferror( fd);    
  429. }
  430.  
  431. /*--------------------------------------------------------------------------*/
  432. static Boolean write_smpte( midiFILE *f, register MidiEvPtr ev, short)
  433. {
  434.     register unsigned long l;
  435.     register FILE *fd;
  436.     
  437.     fd= f->fd;
  438.     putc( META, fd);                        /* header du méta evt    */
  439.     putc( MDF_Offset, fd);                    /* type de méta evt        */
  440.     putc( MDF_OffsetLen, fd);                /* longueur                */
  441.     l= MidiGetField( ev, 0);                /* offset temps en sec    */
  442.     putc( l/3600, fd);                        /* les heures            */
  443.     l%= 3600;
  444.     putc( l/60, fd);                        /* les minutes            */
  445.     putc( l%60, fd);                        /* les secondes            */
  446.     l= MidiGetField( ev, 1);                /* offset frame et div    */
  447.     putc( l/100, fd);                        /* la frame                */
  448.     putc( l%100, fd);                        /* division de la frame */
  449.     return !ferror( fd);    
  450. }
  451.  
  452. /*--------------------------------------------------------------------------*/
  453. static Boolean write_tempo( midiFILE *f, MidiEvPtr ev, short)
  454. {
  455.     register unsigned long l;
  456.     register unsigned short s;
  457.     register FILE *fd;
  458.     
  459.     fd= f->fd;
  460.      putc( META, fd);                        /* header du méta evt    */
  461.       putc( MDF_Tempo, fd);                    /* type de méta evt        */
  462.        putc( MDF_TempoLen, fd);                /* longueur                */
  463.        s= l= Tempo( ev);
  464.        putc( l >> 16, fd);
  465.        putc( s >> 8, fd);
  466.        putc( s & 0xF, fd);
  467.     return !ferror( fd);    
  468. }
  469.  
  470. /*--------------------------------------------------------------------------*/
  471. static Boolean write_endTrack( midiFILE *f, MidiEvPtr, short)
  472. {
  473.     register FILE *fd;
  474.     
  475.     fd= f->fd;
  476.     putc( META, fd);                        /* header du méta evt    */
  477.     putc( MDF_EndTrk, fd);                    /* type de méta evt        */
  478.     putc( MDF_EndTrkLen, fd);                /* longueur                */
  479.     return !ferror( fd);    
  480. }
  481.  
  482. /*--------------------------------------------------------------------------*/
  483. static Boolean write_chanPref( midiFILE *f, MidiEvPtr ev, short)
  484. {
  485.     register FILE *fd;
  486.     
  487.     fd= f->fd;
  488.     putc( META, fd);                        /* header du méta evt    */
  489.     putc( MDF_ChanPref, fd);                /* type de méta evt        */
  490.     putc( MDF_ChanPrefLen, fd);                /* longueur                */
  491.     putc( ChanPrefix(ev), fd);
  492.     return !ferror( fd);    
  493. }
  494.  
  495. /*--------------------------------------------------------------------------*/
  496. static Boolean write_texte( midiFILE *f, MidiEvPtr ev, short status)
  497. {
  498.     register long len, i;
  499.     register FILE *fd;
  500.     
  501.     fd= f->fd;
  502.     putc( META, fd);                        /* header du méta evt    */
  503.     putc( status, fd);                        /* type de méta evt        */
  504.     len= MidiCountFields( ev);
  505.     WriteVarLen( len, fd);
  506.     for( i=0; i<len; i++)
  507.         putc( MidiGetField( ev, i), fd);
  508.     return !ferror( fd);    
  509. }
  510.  
  511. /*--------------------------------------------------------------------------*/
  512. static Boolean write_SeqNum( midiFILE *f, MidiEvPtr ev, short)
  513. {
  514.     register unsigned short s;
  515.     register FILE *fd;
  516.     
  517.     fd= f->fd;
  518.     putc( META, fd);                        /* header du méta evt    */
  519.     putc( MDF_NumSeq, fd);                    /* type de méta evt        */
  520.     putc( MDF_NumSeqLen, fd);                /* longueur                */
  521.     s= SeqNum(ev);
  522.     putc( s >> 8, fd);
  523.     putc( s & 0xF, fd);
  524.     return !ferror( fd);    
  525. }
  526.  
  527.  
  528. /*--------------------------------------------------------------------------*/
  529. /*     Ecriture des événements    midi                                            */
  530. /*--------------------------------------------------------------------------*/
  531.  
  532. /*--------------------------------------------------------------------------*/
  533. static Boolean write_param( register FILE *fd, register short num, register short val, register short type)
  534. {
  535.     putc( type, fd);                        /* NRP number msb            */
  536.     putc( num >> 7, fd);                    /* numéro msb valeur        */
  537.     WriteVarLen( 0, fd);                    /* ev suivant, status courant */
  538.     putc( type-1, fd);                        /* NRP number lsb            */
  539.     putc( num & 0x7F, fd);                    /* numéro lsb valeur        */
  540.     WriteVarLen( 0, fd);                    /* ev suivant, status courant */
  541.     putc( 6, fd);                            /* data entry msb             */
  542.     putc( val >> 7, fd);                    /* envoi msb                */
  543.     WriteVarLen( 0, fd);                    /* ev suivant, status courant */
  544.     putc( 38, fd);                            /* data entry lsb            */
  545.     putc( val & 0x7F, fd);                    /* envoi lsb                */
  546.     return !ferror( fd);    
  547. }
  548.  
  549. /*--------------------------------------------------------------------------*/
  550. static Boolean write_NRegP( register midiFILE *fd, register MidiEvPtr ev, short)
  551. {
  552.     register short num, val;
  553.  
  554.     num= MidiGetField( ev, 0);                    /* num du controleur    */
  555.     val= MidiGetField( ev, 1);                    /* valeur sur 14 bits    */
  556.     putc( ControlChg + Canal( ev), fd->fd);        /* octet de status        */
  557.     return write_param( fd->fd, num, val, 99);
  558. }
  559.  
  560. /*--------------------------------------------------------------------------*/
  561. static Boolean write_RegP( register midiFILE *fd, register MidiEvPtr ev, short)
  562. {
  563.     register short num, val;
  564.  
  565.     num= MidiGetField( ev, 0);                    /* num du controleur    */
  566.     val= MidiGetField( ev, 1);                    /* valeur sur 14 bits    */
  567.     putc( ControlChg + Canal( ev), fd->fd);            /* octet de status        */
  568.     return write_param( fd->fd, num, val, 101);
  569. }
  570.  
  571. /*--------------------------------------------------------------------------*/
  572. static Boolean write_Ctrl14b( midiFILE *f, register MidiEvPtr ev, short)
  573. {
  574.     register short num, val;
  575.     register FILE *fd;
  576.     
  577.     fd= f->fd;
  578.     num= MidiGetField( ev, 0);                    /* num du controleur    */
  579.     val= MidiGetField( ev, 1);                    /* valeur sur 14 bits    */
  580.     putc( ControlChg + Canal( ev), fd);            /* octet de status        */
  581.     putc( num, fd);                                /* envoi numéro de ctrl */
  582.     putc( val >> 7, fd);                        /* envoi msb            */
  583.     WriteVarLen( 0, fd);                    /* ev suivant, status courant */
  584.     putc( num+32, fd);                            /* num ctrl associé        */
  585.     putc( val & 0x7F, fd);                        /* envoi lsb            */
  586.     return !ferror( fd);    
  587. }
  588.  
  589. /*--------------------------------------------------------------------------*/
  590. static Boolean write_sysex( midiFILE *f, register MidiEvPtr ev, short)
  591. {
  592.     register short count, i;
  593.     register FILE *fd;
  594.     
  595.     fd= f->fd;
  596.     count= MidiCountFields( ev);
  597.     if( EvType( ev)== typeSysEx)            /* c'est un sysex            */
  598.         putc( 0xF0, fd);                    /* en tête message sysex    */
  599.     else                                    /* c'est un stream            */
  600.         putc( 0xF7, fd);                    /* en tête suite de sysex    */
  601.     WriteVarLen( count, fd);                /* longueur du message        */
  602.     for( i=0; i< count; i++)
  603.         putc( MidiGetField( ev, i), fd);    /* et datas                    */
  604.     return !ferror( fd);    
  605. }
  606.  
  607. /*--------------------------------------------------------------------------*/
  608. static Boolean dont_write( midiFILE *, MidiEvPtr , short)
  609. {
  610.     return true;
  611. }
  612.  
  613. /*--------------------------------------------------------------------------*/
  614. static Boolean write_0DataEv( register midiFILE *fd, MidiEvPtr, short status)
  615. {
  616.     putc( status, fd->fd);
  617.     return !ferror( fd->fd);    
  618. }
  619.  
  620. /*--------------------------------------------------------------------------*/
  621. static Boolean write_1DataEv( midiFILE *f, register MidiEvPtr ev, short status)
  622. {
  623.     register FILE *fd;
  624.     
  625.     fd= f->fd;
  626.     putc( status, fd);
  627.     putc( Data( ev)[0], fd);
  628.     return !ferror( fd);    
  629. }
  630.  
  631. /*--------------------------------------------------------------------------*/
  632. static Boolean write_2DataEv( midiFILE *f, register MidiEvPtr ev, short status)
  633. {
  634.     register FILE *fd;
  635.     
  636.     fd= f->fd;
  637.     putc( status, fd);
  638.     putc( Data( ev)[0], fd);
  639.     putc( Data( ev)[1], fd);
  640.     return !ferror( fd);    
  641. }
  642.  
  643. /*--------------------------------------------------------------------------*/
  644. static Boolean write_note( midiFILE *f, register MidiEvPtr ev, short status)
  645. {
  646.     register MidiEvPtr c;
  647.     register FILE *fd;
  648.     
  649.     fd= f->fd;
  650.     if( c = MidiCopyEv( ev))
  651.     {
  652.         EvType(c)= typeKeyOff;
  653.         Vel(c) = 0;
  654.         Date(c) = Date( ev) + Dur( ev);
  655.         Dur(c) = 0;
  656.         MidiAddSeq( f->keyOff, c);
  657.         putc( status, fd);
  658.         putc( Data( ev)[0], fd);
  659.         putc( Data( ev)[1], fd);
  660.     }
  661.     else
  662.     {
  663.         MidiFile_errno= MidiFileErrEvs;
  664.         return false;
  665.     }
  666.     return !ferror( fd);    
  667. }
  668.  
  669. /*--------------------------------------------------------------------------*/
  670. static Boolean WriteEv( register midiFILE *fd, register MidiEvPtr ev)
  671. {
  672.     register short type;
  673.     register Boolean ret= true;
  674.     
  675.     type= EvType( ev);
  676.     if( type < typePrivate)
  677.         ret= (* WriteEvTbl[type])( fd, ev, (type < typeSongPos ? codeTbl[type]+Canal(ev) : codeTbl[type]));
  678.     else if( type >= typeQuarterFrame && type < typeReserved)
  679.     {
  680.         type-= typeQuarterFrame;
  681.         ret= (* WriteExtTbl[type])( fd, ev, metaCodeTbl[type]);
  682.     }
  683.     return ret;
  684. }
  685.  
  686. /*--------------------------------------------------------------------------*/
  687. static Boolean FlushKeyOff( register midiFILE *fd)
  688. {
  689.     register MidiSeqPtr seq;
  690.     register MidiEvPtr ev;
  691.     register Boolean ret= true;
  692.     register long date;
  693.     
  694.     seq= fd->keyOff;                        /* la séquence des key off    */
  695.     ev= seq->first;                            /* son premier événement    */
  696.     date= fd->curDate;                        /* date courante            */
  697.     while( ev && ret)
  698.     {
  699.         seq->first= Link(ev);                /* premier = suivant        */
  700.         ret= (WriteVarLen( Date( ev)- date, fd->fd) 
  701.               && WriteEv( fd, ev));            /* écrit l'événement        */
  702.         date= Date( ev);                    /* m.a.j. date courante        */
  703.         MidiFreeEv( ev);                    /* le libère                */
  704.         ev= seq->first;                        /* événement suivant        */
  705.     }
  706.     if( ret) seq->last= nil;                /* maj de la séquence        */
  707.     fd->curDate= date;                        /* m.a.j. date courante        */
  708.     return ret;
  709. }
  710.  
  711. /*--------------------------------------------------------------------------*/
  712. Boolean MidiFileNewTrack( midiFILE *fd)
  713. {
  714.     MidiFile_errno= MidiFileNoErr;
  715.     if( isTrackOpen( fd) && !MidiFileCloseTrack( fd))     /* piste ouverte    */
  716.         return false;                                    /* on la referme    */
  717.     if( fseek( fd->fd, 0, SEEK_END))         /* position en fin de fichier    */
  718.         return false;
  719.     if( !Create_trkHeader( fd->fd, 0))          /* écriture en-tête de piste     */
  720.         return false;
  721.     if( fgetpos(fd->fd,&fd->trkHeadOffset))    /* position de début de piste     */
  722.         return false;
  723.     fd->curDate= 0;                            /* date courante = 0            */
  724.     return true;
  725. }
  726.  
  727. /*--------------------------------------------------------------------------*/
  728. Boolean MidiFileOpenTrack( register midiFILE *fd)
  729. {
  730.     MDF_Trk h;
  731.  
  732.     MidiFile_errno= MidiFileNoErr;
  733.     if( fd->mode)
  734.     {
  735.         MidiFile_errno= MidiFileErrNoTrack;
  736.         return false;
  737.     }
  738.     if( isTrackOpen( fd))                    /* piste déja ouverte            */
  739.         return true;
  740.     if( ReadTrkHeader( fd->fd, &h))        /* on lit l'en-tête de piste    */
  741.     {
  742.         fd->_cnt= h.len;                    /* longueur de piste=0 => fin    */
  743.         fd->curDate= 0;                        /* date courante = 0            */
  744.         fd->trkHeadOffset= true;            /* signale piste ouverte        */
  745.     }
  746.     else return false;
  747.     return true;
  748. }
  749.  
  750. /*--------------------------------------------------------------------------*/
  751. Boolean MidiFileCloseTrack( register midiFILE *fd)
  752. {
  753.     fpos_t offset1, offset2;                /* offset début et fin de piste */
  754.     long trkLen;                            /* longueur de la piste            */
  755.     register Boolean ret;
  756.  
  757.     MidiFile_errno= MidiFileNoErr;
  758.     offset1= fd->trkHeadOffset;
  759.     if( fd->mode )                            /* fichier en écriture            */
  760.     {
  761.         if( offset1= fd->trkHeadOffset)        /* piste ouverte                */
  762.         {
  763.             ret= FlushKeyOff( fd);                /* écrit les keyOff restants    */
  764.             if( fgetpos( fd->fd, &offset2))         /* position de fin de piste     */
  765.                 return false;
  766.             trkLen= offset2- offset1;            /* calcule la longueur            */
  767.             offset1-= offset_trkLen;
  768.             if( fsetpos( fd->fd, &offset1))         /* pos = longueur de piste         */
  769.                 return false;
  770.                                                 /* m.a.j. longueur de la piste     */
  771.             if( fwrite( &trkLen, sizeof( trkLen), 1, fd->fd)!= 1)
  772.                 return false;
  773.             if( fseek( fd->fd, offset_ntrks, SEEK_SET))    /* pos = nbre de pistes    */
  774.                 return false;
  775.             fd->ntrks++;                        /* incrémente nbre de pistes     */
  776.                                                 /* m.a.j. du nombre de pistes      */
  777.             if( fwrite( &fd->ntrks, sizeof( fd->ntrks), 1, fd->fd)!= 1)
  778.                 return false;    
  779.         }
  780.     }
  781.     else if( isTrackOpen( fd))                    /* fichier en lecture            */
  782.                                             /* position = début piste suivante     */
  783.         ret= ( fseek( fd->fd, fd->_cnt, SEEK_CUR)== 0);
  784.     fd->trkHeadOffset= nil;                        /* signale piste fermée            */
  785.     return ret;
  786. }
  787.  
  788. /*--------------------------------------------------------------------------*/
  789. Boolean MidiFileWriteEv( register midiFILE *fd, MidiEvPtr ev)
  790. {
  791.     register MidiSeqPtr seq;
  792.     register MidiEvPtr off;
  793.     register long date;
  794.     
  795.     if( fd->trkHeadOffset)
  796.         MidiFile_errno= MidiFileNoErr;
  797.     else
  798.     {
  799.         MidiFile_errno= MidiFileErrTrackClose;
  800.         return false;
  801.     }
  802.     date= fd->curDate;                                    /* date courante    */
  803.     seq= fd->keyOff;                                    /* seq des key off    */
  804.     off= seq->first;                                    /* prochain key off */
  805.     while( off && (Date(ev) >= Date(off)))    /* key off précède l'evt courant*/
  806.     {
  807.         if( !WriteVarLen( Date(off)- date, fd->fd) ||    /* ecrit l'offset    */
  808.             !WriteEv( fd, off))                            /* et le key off    */
  809.             return false;
  810.         date= Date( off);                            /* m.a.j. date courante    */
  811.         seq->first= Link(off);                        /* m.a.j. de la séquence*/
  812.         MidiFreeEv( off);                            /* libère le key off    */
  813.         if( !(off= seq->first))                        /* key off = suivant    */
  814.             seq->last= nil;
  815.     }
  816.     if( !WriteVarLen( Date( ev)- date, fd->fd) ||        /* ecrit l'offset    */
  817.         !WriteEv( fd, ev))                                /* et l'evt            */
  818.         return false;
  819.     fd->curDate= Date( ev);                            /* m.a.j. date courante    */
  820.     return true;
  821. }
  822.  
  823. /*--------------------------------------------------------------------------*/
  824. Boolean MidiFileWriteTrack( register midiFILE *fd, MidiSeqPtr seq)
  825. {
  826.     register MidiEvPtr ev;
  827.     register Boolean ret= true;
  828.     
  829.     MidiFile_errno= MidiFileNoErr;
  830.     if( !MidiFileNewTrack( fd))                  /* écriture en-tête de piste     */
  831.         return false;
  832.  
  833.     ev= seq->first;
  834.     while( ev && ret)
  835.     {
  836.         ret= MidiFileWriteEv( fd, ev);                /* écriture de l'evt    */
  837.         ev= Link( ev);                                /* evt suivant            */
  838.     }
  839.  
  840.     if( !MidiFileCloseTrack( fd))            /* mise à jour en-tête de piste */
  841.         ret= false;                            /* et en-tête de fichier        */
  842.     return ret;
  843. }
  844.  
  845.  
  846. /*--------------------------------------------------------------------------*/
  847. /* Lecture d'une piste                                                        */
  848. /*--------------------------------------------------------------------------*/
  849.  
  850. /*--------------------------------------------------------------------------*/
  851. static Boolean mdf_GetDate( register midiFILE *fd)
  852. {
  853.     register long offset;
  854.     
  855.     offset= ReadVarLen( fd);             /* lit l'offset de l'evt suivant    */
  856.     if( feof( fd->fd))                    /* contrôle d'erreur de structure    */
  857.     {
  858.         MidiFile_errno= MidiFileErrFrmt;
  859.         return false;
  860.     }
  861.     if( ferror( fd->fd))                /* contrôle d'erreur                */
  862.         return false;
  863.     fd->curDate+= offset;            /* ajoute l'offset à la date courante    */
  864.     return true;
  865. }
  866.  
  867. /*--------------------------------------------------------------------------*/
  868. static void mdf_ignoreEv( register midiFILE *fd, register long len)
  869. {
  870.     fd->_cnt-= len;
  871.     while( len--)
  872.         getc( fd->fd);
  873. }
  874.  
  875.  
  876. /*--------------------------------------------------------------------------*/
  877. /* fonctions de lecture d'un méta-événement                                    */
  878. /*--------------------------------------------------------------------------*/
  879.  
  880. /*--------------------------------------------------------------------------*/
  881. static MidiEvPtr read_text( register midiFILE *fd, register long len, short type)
  882. {
  883.     register MidiEvPtr ev=nil;
  884.  
  885.     if( ev= MidiNewEv( type + 133))
  886.     {
  887.         fd->_cnt-= len;
  888.         while( len--)
  889.             MidiAddField( ev, (long)getc( fd->fd));
  890.     }
  891.     else MidiFile_errno= MidiFileErrEvs;
  892.     return ev;
  893. }
  894.  
  895. /*--------------------------------------------------------------------------*/
  896. static MidiEvPtr read_endTrack( register midiFILE *fd, register long len, short)
  897. {
  898.     register MidiEvPtr ev=nil;
  899.     
  900.     if( len!= MDF_EndTrkLen)            /* longueur du message        */
  901.         mdf_ignoreEv( fd, len);
  902.     else if( !(ev= MidiNewEv( typeEndTrack)))
  903.         MidiFile_errno= MidiFileErrEvs;
  904.     return ev;
  905. }
  906.  
  907. /*--------------------------------------------------------------------------*/
  908. static MidiEvPtr read_tempo( register midiFILE *fd, register long len, short)
  909. {
  910.     register MidiEvPtr ev=nil;
  911.     register long tempo;
  912.     
  913.     if (len != MDF_TempoLen)             /* longueur du message        */
  914.         mdf_ignoreEv( fd, len);
  915.     else if( ev= MidiNewEv( typeTempo))
  916.     {
  917.         tempo= (long)getc(fd->fd);
  918.         tempo <<= 8;
  919.         tempo|= getc(fd->fd);
  920.         tempo <<= 8;
  921.         tempo|= getc(fd->fd);
  922.         Tempo(ev)= tempo;
  923.         fd->_cnt-= len;
  924.     }
  925.     else MidiFile_errno= MidiFileErrEvs;
  926.     return ev;
  927. }
  928.  
  929. /*--------------------------------------------------------------------------*/
  930. static MidiEvPtr read_keySign( register midiFILE *fd, register long len, short)
  931. {
  932.     register MidiEvPtr ev=nil;
  933.  
  934.     if (len != MDF_TonLen)                 /* longueur du message        */
  935.         mdf_ignoreEv( fd, len);
  936.     else if( ev= MidiNewEv( typeKeySign))
  937.     {
  938.         KSTon( ev)= getc(fd->fd);
  939.         KSMode( ev)= getc(fd->fd);
  940.         fd->_cnt-= len;
  941.     }
  942.     else MidiFile_errno= MidiFileErrEvs;
  943.     return ev;
  944. }
  945.  
  946. /*--------------------------------------------------------------------------*/
  947. static MidiEvPtr read_timeSign( register midiFILE *fd, register long len, short)
  948. {
  949.     register MidiEvPtr ev=nil;
  950.  
  951.     if (len != MDF_MeasLen)             /* longueur du message        */
  952.         mdf_ignoreEv( fd, len);
  953.     else if( ev= MidiNewEv( typeTimeSign))
  954.     {
  955.         TSNum( ev)= getc(fd->fd);
  956.         TSDenom( ev)= getc(fd->fd);
  957.         TSClocks( ev)= getc(fd->fd);
  958.         TS32nd( ev)= getc(fd->fd);
  959.         fd->_cnt-= len;
  960.     }
  961.     else MidiFile_errno= MidiFileErrEvs;
  962.     return ev;
  963. }
  964.  
  965. /*--------------------------------------------------------------------------*/
  966. static MidiEvPtr read_seqNum( register midiFILE *fd, register long len, short)
  967. {
  968.     register MidiEvPtr ev=nil;
  969.     register short num;
  970.  
  971.     if (len != MDF_NumSeqLen)             /* longueur du message        */
  972.         mdf_ignoreEv( fd, len);
  973.     else if( ev= MidiNewEv( typeSeqNum))
  974.     {
  975.         num= getc(fd->fd);
  976.         num <<= 8;
  977.         num|= getc(fd->fd);
  978.         SeqNum(ev)= num;
  979.         fd->_cnt-= len;
  980.     }
  981.     else MidiFile_errno= MidiFileErrEvs;
  982.     return ev;
  983. }
  984.  
  985. /*--------------------------------------------------------------------------*/
  986. static MidiEvPtr read_chanPref( register midiFILE *fd, register long len, short)
  987. {
  988.     register MidiEvPtr ev=nil;
  989.  
  990.     if (len != MDF_ChanPrefLen)         /* longueur du message        */
  991.         mdf_ignoreEv( fd, len);
  992.     else if( ev= MidiNewEv( typeChanPrefix))
  993.     {
  994.         ChanPrefix(ev)= getc(fd->fd);
  995.         fd->_cnt-= len;
  996.     }
  997.     else MidiFile_errno= MidiFileErrEvs;
  998.     return ev;
  999. }
  1000.  
  1001. /*--------------------------------------------------------------------------*/
  1002. static MidiEvPtr read_smpte( register midiFILE *fd, register long len, short)
  1003. {
  1004.     register MidiEvPtr ev=nil;
  1005.     register long tmp;
  1006.  
  1007.     if (len != MDF_OffsetLen)             /* longueur du message        */
  1008.         mdf_ignoreEv( fd, len);
  1009.     else if( ev= MidiNewEv( typeSMPTEOffset))
  1010.     {
  1011.         tmp= getc(fd->fd)* 3600;        /* heure -> sec.        */
  1012.         tmp+= getc(fd->fd)* 60;            /* minutes -> sec.        */
  1013.         tmp+= getc(fd->fd);                /* secondes                */
  1014.         MidiAddField( ev, tmp);
  1015.         tmp= getc(fd->fd)* 100;            /* nbre de frame *100     */
  1016.         tmp+= getc(fd->fd);                /* division de la frame    */
  1017.         MidiAddField( ev, tmp);
  1018.         fd->_cnt-= len;
  1019.     }
  1020.     else MidiFile_errno= MidiFileErrEvs;
  1021.     return ev;
  1022. }
  1023.  
  1024. /*--------------------------------------------------------------------------*/
  1025. static MidiEvPtr mdf_read_meta( register midiFILE *fd)
  1026. {
  1027.     register short type;
  1028.     register unsigned long len;
  1029.  
  1030.     type= getc(fd->fd);                        /* lit le type du message        */
  1031.     fd->_cnt--;                                /* m.a.j. de reste à lire        */
  1032.     len= ReadVarLen(fd);                    /* lit la longueur du message    */
  1033.  
  1034.     if( type & 0x80) type=0;                /* type > 127 => inconnu        */
  1035.     else type= metaTypeTbl[type];
  1036.     return (*ReadExtTbl[type])( fd, len, type);
  1037. }
  1038.  
  1039.  
  1040. /*--------------------------------------------------------------------------*/
  1041. static MidiEvPtr read_undef( midiFILE *,  short)
  1042. {
  1043.     MidiFile_errno= MidiFileErrUnknow;
  1044.     return nil;
  1045. }
  1046.  
  1047.  
  1048. /*--------------------------------------------------------------------------*/
  1049. /* fonctions de lecture d'un événement midi                                    */
  1050. /*--------------------------------------------------------------------------*/
  1051.  
  1052. /*--------------------------------------------------------------------------*/
  1053. static MidiEvPtr read_sysex( register midiFILE *fd, register short status)
  1054. {
  1055.     register MidiEvPtr ev;
  1056.     register unsigned long len;
  1057.     register short c;
  1058.  
  1059.     if( ev= MidiNewEv( status== 0xF0 ? typeSysEx : typeStream))
  1060.     {
  1061.         len= ReadVarLen( fd);                /* longueur du message    */
  1062.         while( len--)
  1063.         {
  1064.             c= getc( fd->fd);                /* lit les données        */
  1065.             fd->_cnt--;
  1066.             MidiAddField( ev, c);            /* et les range dans ev */
  1067.         }
  1068.     }
  1069.     else MidiFile_errno= MidiFileErrEvs;
  1070.     return ev;
  1071. }
  1072.  
  1073. /*--------------------------------------------------------------------------*/
  1074. static MidiEvPtr read_2DataEv( register midiFILE *fd, register short status)
  1075. {
  1076.     register MidiEvPtr ev;
  1077.  
  1078.     if( ev= MidiNewEv( typeTbl[status & 0x7F]))    /* alloue l'événement    */
  1079.     {
  1080.         Data( ev)[0]= getc( fd->fd);            /* range la 1ière donnée*/
  1081.         Data( ev)[1]= getc( fd->fd);            /* et la 2ième donnée    */
  1082.         fd->_cnt-= 2;
  1083.     }
  1084.     else MidiFile_errno= MidiFileErrEvs;
  1085.     return ev;
  1086. }
  1087.  
  1088. /*--------------------------------------------------------------------------*/
  1089. static MidiEvPtr read_1DataEv( register midiFILE *fd, register short status)
  1090. {
  1091.     register MidiEvPtr ev;
  1092.     
  1093.     if( ev= MidiNewEv( typeTbl[status & 0x7F]))    /* alloue l'événement    */
  1094.     {
  1095.         Data( ev)[0]= getc( fd->fd);            /* range la donnée        */
  1096.         fd->_cnt--;
  1097.     }
  1098.     else MidiFile_errno= MidiFileErrEvs;
  1099.     return ev;
  1100. }
  1101.  
  1102. /*--------------------------------------------------------------------------*/
  1103. static MidiEvPtr read_0DataEv( midiFILE *, register short status)
  1104. {
  1105.     register MidiEvPtr ev;
  1106.     
  1107.     if( !(ev= MidiNewEv( typeTbl[status & 0x7F])))/* alloue l'événement    */
  1108.         MidiFile_errno= MidiFileErrEvs;
  1109.     return ev;
  1110. }
  1111.  
  1112. /*--------------------------------------------------------------------------*/
  1113. static MidiEvPtr ReadEv( register midiFILE *fd)
  1114. {
  1115.     register MidiEvPtr ev= nil;
  1116.     register short c;
  1117.     static short status= nil;
  1118.     
  1119.     c= getc( fd->fd);
  1120.     fd->_cnt--;                                /* m.a.j. de reste à lire    */
  1121.     
  1122.     if( c== META)                                    /* méta evt            */
  1123.     {
  1124.         ev= mdf_read_meta( fd);
  1125.         c= status= nil;
  1126.     }
  1127.     else if( c & 0x80)                                /* octet de status    */
  1128.         status= c;
  1129.     else if( status)                                /* status courant    */
  1130.     {
  1131.         ungetc (c, fd->fd);                            /* rend le char        */
  1132.         fd->_cnt++;
  1133.         c= status;
  1134.     }
  1135.     else 
  1136.     {
  1137.         MidiFile_errno= MidiFileErrFrmt;
  1138.         c= nil;
  1139.     }
  1140.     if( c)
  1141.     {
  1142.         if( ev= (* ReadEvTbl[(c<SysEx) ? (c & 0x7F)/16 : c- SysEx+7])( fd, c))
  1143.             if( c < SysEx)
  1144.                 Canal(ev)= c%16;
  1145.     }
  1146.     if( (ferror( fd->fd) || feof( fd->fd)) && ev)
  1147.     {
  1148.         MidiFreeEv( ev);
  1149.         ev= nil;
  1150.         if( feof( fd->fd))
  1151.             MidiFile_errno= MidiFileErrFrmt;
  1152.     }
  1153.     return ev;
  1154. }
  1155.  
  1156. /*--------------------------------------------------------------------------*/
  1157. MidiEvPtr MidiFileReadEv( register midiFILE *fd)
  1158. {
  1159.     register MidiEvPtr ev= nil;
  1160.  
  1161.     MidiFile_errno= MidiFileNoErr;
  1162.     if( isTrackOpen( fd))                    /* si la piste est ouverte        */
  1163.     {
  1164.         if( fd->_cnt > 0)                    /* s'il reste des evts à lire    */
  1165.         {
  1166.             if( mdf_GetDate( fd))            /* lit date de l'evt suivant    */
  1167.                 if( ev= ReadEv( fd))        /* lit l'événement                */
  1168.                     Date( ev)= fd->curDate;    /* stocke sa date                */
  1169.         }
  1170.         else fd->trkHeadOffset= 0;            /* sinon on referme la piste    */
  1171.     }
  1172.     else MidiFile_errno= MidiFileErrTrackClose;
  1173.     return ev;
  1174. }
  1175.  
  1176. /*--------------------------------------------------------------------------*/
  1177. MidiSeqPtr MidiFileReadTrack( register midiFILE *fd)
  1178. {
  1179.     register MidiSeqPtr seq= nil;
  1180.     register MidiEvPtr ev;
  1181.     
  1182.     MidiFile_errno= MidiFileNoErr;
  1183.     if( MidiFileOpenTrack( fd))                    /* on ouvre la piste        */
  1184.     {
  1185.         if( seq= MidiNewSeq())                    /* alloue une séquence         */
  1186.         {
  1187.             while( isTrackOpen( fd))            /* tant qu'il y a des evts    */
  1188.             {
  1189.                 if( ev= MidiFileReadEv( fd))    /* on lit les événements    */
  1190.                 {
  1191.                     if( !seq->first)            /* on les range dans la seq */
  1192.                         seq->first= seq->last= ev;
  1193.                     else
  1194.                     {
  1195.                         Link(seq->last)= ev;
  1196.                         seq->last= ev;
  1197.                     }
  1198.                 }
  1199.                 else if( isMidiFileError( fd))    /* sinon si erreur            */
  1200.                 {
  1201.                     MidiFreeSeq( seq);            /* libère la séquence        */
  1202.                     seq= nil;                    /* pour renvoi erreur        */
  1203.                     break;
  1204.                 }                                /* sinon c'est un evt ignoré */
  1205.             }
  1206.         }
  1207.         else MidiFile_errno= MidiFileErrEvs;
  1208.     }
  1209.     return seq;
  1210. }
  1211.  
  1212.  
  1213.  
  1214. /*--------------------------------------------------------------------------*/
  1215. /* Ouverture et fermeture d'un fichier MidiFile                                */
  1216. /*--------------------------------------------------------------------------*/
  1217.  
  1218. /*--------------------------------------------------------------------------*/
  1219. static const char *mdf_getStdMode( register short mode)
  1220. {
  1221.     switch( mode)
  1222.     {
  1223.         case MidiFileRead:
  1224.             return "r";
  1225.         case MidiFileAppend:
  1226.             return "r+";
  1227.         default:
  1228.             MidiFile_errno= MidiFileErrMode;
  1229.             return nil;
  1230.     }
  1231. }
  1232.  
  1233. /*--------------------------------------------------------------------------*/
  1234. static void ErrOpen( register midiFILE *fd)
  1235. {
  1236.     if( fd)
  1237.     {
  1238.         if( fd->fd) fclose( fd->fd);            /* fichier ouvert: on ferme */
  1239.         if( fd->mode && fd->keyOff) 
  1240.             MidiFreeSeq( fd->keyOff);            /* seq allouée: on libère    */
  1241.         free( fd);
  1242.     }
  1243. }
  1244.  
  1245. /*--------------------------------------------------------------------------*/
  1246. static Boolean stdInit( register midiFILE *fd)
  1247. {
  1248.     fd->trkHeadOffset= nil;
  1249.     fd->curDate= 0;
  1250.     if( fd->mode)
  1251.     {
  1252.         if( !(fd->keyOff= MidiNewSeq()))
  1253.             return false;
  1254.     }
  1255.     else fd->keyOff= nil;
  1256.     return true;
  1257. }
  1258.  
  1259. /*--------------------------------------------------------------------------*/
  1260. midiFILE *MidiFileOpen( const char *filename, short mode)
  1261. {
  1262.     register midiFILE *fd;    /* pour le descripteur de mon fichier MidiFile    */
  1263.     Boolean ok= true;        /* pour savoir si tout s'est bien passé            */
  1264.     const char *stdMode;    /* mode d'ouverture standard                    */
  1265.     
  1266.     MidiFile_errno= MidiFileNoErr;
  1267.     if( fd= (midiFILE *)malloc( sizeof( midiFILE)))
  1268.     {
  1269.         fd->fd= nil;
  1270.         stdInit( fd);                                /* initialisation standard    */
  1271.         if( (stdMode= mdf_getStdMode( mode)) &&        /* ctrl mode d'ouverture     */
  1272.             (fd->fd= fopen( filename, stdMode)))    /* ouverture du fichier        */
  1273.         {            
  1274.             if( ok= ReadMdfHeader( fd))            /* lit l'en-tête du fichier */
  1275.             {
  1276.                 if( fd->format== midifile0 && mode== MidiFileAppend)
  1277.                 {                                    /* erreur :                    */
  1278.                     MidiFile_errno= MidiFileErrAdd0;/* tentative d'ajout à un     */
  1279.                     ok= false;                        /* fichier au format 0        */
  1280.                 }
  1281.                 fd->mode= (mode== MidiFileAppend ? true : false);
  1282.                 ok= stdInit( fd);                    /* initialisation standard    */
  1283.             }
  1284.         }
  1285.         else ok= false;
  1286.     }
  1287.     if( !ok)                                        /* il y a eut erreur        */
  1288.     {
  1289.         ErrOpen( fd);
  1290.         fd= nil;
  1291.     }
  1292.     return fd;
  1293. }
  1294.  
  1295.  
  1296. /*--------------------------------------------------------------------------*/
  1297. midiFILE *MidiFileCreate( const char *name, short format, short timeDef, short ticks)
  1298. {
  1299.     register midiFILE *fd;    /* pour le descripteur de mon fichier MidiFile    */
  1300.     Boolean ok= true;        /* pour savoir si tout s'est bien passé            */
  1301.     short time;                /* représentation du temps                        */
  1302.     
  1303.     MidiFile_errno= MidiFileNoErr;
  1304.     if( fd= (midiFILE *)malloc( sizeof( midiFILE)))
  1305.     {
  1306.         if( fd->fd= fopen( name, "w+"))            /* ouverture du fichier        */
  1307.         {
  1308.             fd->mode= true;                        /* on est en écriture        */
  1309.             fd->ntrks= 0;                        /* nbre de pistes = 0        */
  1310.             fd->format= format;                    /* format du fichier        */
  1311.             if( timeDef)                        /* temps smpte                */
  1312.             {
  1313.                 time= (timeDef | 0x80) << 8;
  1314.                 time|= (char) ticks;
  1315.             }
  1316.             else time= ticks & 0x7FFF;
  1317.             if( ok= stdInit( fd))                /* initialisation standard    */
  1318.                 ok= Create_mdfHeader( fd, format, fd->time= time);
  1319.         }
  1320.         else ok= false;
  1321.     }
  1322.     if( !ok)                                    /* il y a eut erreur        */
  1323.     {
  1324.         ErrOpen( fd);
  1325.         fd= nil;
  1326.     }
  1327.     return fd;
  1328. }
  1329.  
  1330. /*--------------------------------------------------------------------------*/
  1331. Boolean MidiFileClose( register midiFILE *fd)
  1332. {
  1333.     register int ret1= true, ret2;                /* codes de retour            */
  1334.     
  1335.     MidiFile_errno= MidiFileNoErr;
  1336.     if( fd->mode)                                /* fichier en écriture        */
  1337.     {
  1338.         if( fd->trkHeadOffset)                    /* piste encore ouverte        */
  1339.             ret1= MidiFileCloseTrack( fd);        /* on la referme            */
  1340.         if( fd->keyOff)
  1341.             MidiFreeSeq( fd->keyOff);            /* libère la séquence        */
  1342.     }
  1343.     ret2= fclose( fd->fd);                        /* ferme le fichier            */
  1344.     free( fd);                                    /* libère la mémoire         */
  1345.     return ret1 && ret2== 0;
  1346. }
  1347.  
  1348. /*--------------------------------------------------------------------------*/
  1349. const MDF_versions *MidiFileGetVersion(void)
  1350. {
  1351.     static MDF_versions versions;
  1352.     
  1353.     versions.src= SRC_VERSION;
  1354.     versions.MidiFile= MDF_VERSION;
  1355.     return (const MDF_versions *)&versions;
  1356. }
  1357.  
  1358. /*--------------------------------------------------------------------------*/
  1359. /* main présent uniquement pour link -uf et élaboration de la librairie        */
  1360.  
  1361. #ifdef LIB
  1362.  
  1363. void main()
  1364. {
  1365.     MidiFileGetVersion();
  1366.     MidiFileOpen( nil, nil);
  1367.     MidiFileCreate( nil, nil, nil, nil);
  1368.     MidiFileClose( nil);
  1369.     MidiFileSetPos( nil, nil);
  1370.     MidiFileReadTrack( nil);
  1371.     MidiFileWriteTrack( nil, nil);
  1372.     MidiFileCloseTrack( nil);
  1373.     MidiFileNewTrack( nil);
  1374.     MidiFileWriteEv( nil, nil);
  1375. }
  1376.  
  1377. #endif
  1378.  
  1379. /*********************************** fin ************************************/
  1380.