jdkmidi class library documentation

Copyright © 2004 J.D. Koftinoff Software, Ltd.

Released under the GNU General Public License (GPL)




Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

src/jdkmidi_parser.cpp

Go to the documentation of this file.
00001 /*
00002  *  libjdkmidi-2004 C++ Class Library for MIDI
00003  *
00004  *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
00005  *  www.jdkoftinoff.com
00006  *  jeffk@jdkoftinoff.com
00007  *
00008  *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 /*
00025 **  Copyright 1986 to 1998 By J.D. Koftinoff Software, Ltd.
00026 **
00027 **  All rights reserved.
00028 **
00029 **  No one may duplicate this source code in any form for any reason
00030 **  without the written permission given by J.D. Koftinoff Software, Ltd.
00031 **
00032 */
00033 
00034 
00035 #include "jdkmidi/world.h"
00036 
00037 #include "jdkmidi/parser.h"
00038 
00039 
00040 #ifndef DEBUG_MDPARSER
00041 # define DEBUG_MDPARSER 0
00042 #endif
00043 
00044 #if DEBUG_MDPARSER
00045 # undef DBG
00046 # define DBG(a) a
00047 #endif
00048 
00049 
00050 namespace jdkmidi
00051 {
00052   
00053   
00054   MIDIParser::MIDIParser( ushort max_sysex_size )
00055   {
00056     ENTER( "MIDIParser::MIDIParser" );
00057     sysex = new MIDISystemExclusive(max_sysex_size);
00058     state=FIND_STATUS;
00059   }
00060   
00061   MIDIParser::~MIDIParser()
00062   {
00063     ENTER( "MIDIParser::~MIDIParser" );
00064     
00065     delete sysex;
00066   }
00067   
00068   
00069   bool MIDIParser::Parse( uchar b, MIDIMessage *msg )
00070   {
00071     ENTER( "MIDIParser::Parse()" );
00072     
00073     //
00074     // No matter what state we are currently in we must deal
00075     // with bytes with the high bit set first.
00076     //
00077     
00078     if( b&0x80 )
00079     {
00080       //
00081       // check for system messages (>=0xf0)
00082       //
00083       
00084       uchar stat=(uchar)(b&0xf0);
00085       
00086       if( stat==0xf0 )
00087       {
00088         //
00089         // System messages get parsed by
00090         // ParseSystemByte()
00091         //
00092         
00093         return ParseSystemByte( b, msg );
00094       }
00095       else
00096       {
00097         //
00098         // Otherwise, this is a new status byte.
00099         //
00100         
00101         ParseStatusByte( b );
00102         return false;
00103       }
00104     }
00105     else
00106     {
00107       //
00108       // Try to parse the data byte
00109       //
00110       
00111       return ParseDataByte( b, msg );
00112     }
00113   }
00114   
00115   
00116   
00117   
00118   bool MIDIParser::ParseSystemByte( uchar b, MIDIMessage *msg )
00119   {
00120     ENTER( "MIDIParser::ParseSystemByte" );
00121     
00122     switch( b )
00123     {
00124     case RESET:
00125     {
00126       //
00127       // a reset byte always re-initializes our state 
00128       // machine.
00129       //
00130       
00131       state=FIND_STATUS;
00132       
00133       
00134       return false;
00135     }
00136     
00137     case SYSEX_START:
00138     {
00139       //
00140       // start receiving sys-ex data
00141       //
00142       
00143       state=SYSEX_DATA;
00144       
00145       //
00146       // Prepare sysex buffer.
00147       //
00148       
00149       sysex->Clear();
00150       sysex->PutEXC();
00151       
00152       return false;
00153     }
00154     
00155     case SYSEX_END:
00156     {
00157       //
00158       // We are finished receiving a sysex message.
00159       //
00160       
00161       
00162       //
00163       // If we were not in SYSEX_DATA mode, this
00164       // EOX means nothing.
00165       //
00166       
00167       if( state!=SYSEX_DATA )
00168       {
00169         
00170         return false;
00171       }
00172       
00173       //
00174       // reset the state machine
00175       //
00176       
00177       state=FIND_STATUS;
00178       
00179       
00180       //
00181       // finish up sysex buffer
00182       //
00183       
00184       sysex->PutEOX();
00185       
00186       //
00187       // return a MIDIMessage with status=SYSEX_START
00188       // so calling program can know to look at
00189       // the sysex buffer with GetSystemExclusive().
00190       //
00191       
00192       msg->SetStatus( SYSEX_START );
00193       
00194       
00195       return true;
00196     }
00197     
00198     case MTC:
00199     {
00200       //
00201       // Go into FIRST_OF_ONE_NORUN state.
00202       // this is required because MTC (F1) is not
00203       // allowed to be running status.
00204       //
00205       
00206       tmp_msg.SetStatus( MTC );
00207       
00208       state=FIRST_OF_ONE_NORUN;
00209       
00210       return false;
00211     }
00212     
00213     case SONG_POSITION:
00214     {
00215       //
00216       // This is a two data byte message, so go into
00217       // FIRST_OF_TWO state. 
00218       //
00219       
00220       state=FIRST_OF_TWO;
00221       
00222       tmp_msg.SetStatus( SONG_POSITION );
00223       
00224       return false;
00225     }
00226     
00227     case SONG_SELECT:
00228     {
00229       //
00230       // This is a one data byte message, so go into
00231       // the FIRST_OF_ONE state.
00232       //
00233       
00234       state=FIRST_OF_ONE;
00235       tmp_msg.SetStatus( SONG_SELECT );
00236       
00237       return false;
00238     }
00239     
00240     
00241     //
00242     // the one byte system messages.
00243     // these messages may interrupt any other message,
00244     // and therefore do not affect the current state or
00245     // running status.
00246     //
00247     
00248     case TUNE_REQUEST:
00249     case TIMING_CLOCK:
00250     case MEASURE_END:
00251     case START:
00252     case CONTINUE:
00253     case STOP:
00254     case ACTIVE_SENSE:
00255     {
00256       msg->SetStatus( b );
00257       return true;
00258     }
00259     
00260     default:
00261     {
00262       //
00263       // any other byte must be ignored.
00264       // It is either a communicatin error or
00265       // a new type of MIDI message.
00266       // go into FIND_STATUS state to ignore
00267       // any possible data bytes for this unknown message
00268       //
00269       
00270       state=FIND_STATUS;
00271       return false;
00272     }
00273     }
00274     
00275     
00276   }
00277   
00278   
00279   void MIDIParser::ParseStatusByte( uchar b )
00280   {
00281     ENTER( "MIDIParser::ParseStatusByte" );
00282     
00283     char len=GetMessageLength( b );
00284     
00285     if( len==2 )
00286     {
00287       state=FIRST_OF_ONE;
00288       tmp_msg.SetStatus( b );
00289     }
00290     else if( len==3 )
00291     {
00292       state=FIRST_OF_TWO;
00293       tmp_msg.SetStatus( b );
00294     }
00295     else
00296     {
00297       state=FIND_STATUS;
00298       tmp_msg.SetStatus( 0 );
00299     }
00300   }
00301   
00302   
00303   bool MIDIParser::ParseDataByte( uchar b, MIDIMessage *msg )
00304   {
00305     ENTER( "MIDIParser::ParseDataByte" );
00306     
00307     switch( state )
00308     {
00309     case FIND_STATUS:
00310     {
00311       //
00312       // just eat data bytes until we get a status byte
00313       //
00314       
00315       return false;
00316     }
00317     
00318     case FIRST_OF_ONE:
00319     {
00320       //
00321       // this is the only data byte of a message.
00322       // form the message and return it.
00323       //
00324       
00325       tmp_msg.SetByte1( b );
00326       *msg = tmp_msg;
00327       
00328       //
00329       // stay in this state for running status 
00330       //
00331       
00332       return true;
00333     }
00334     
00335     case FIRST_OF_TWO:
00336     {
00337       //
00338       // this is the first byte of a two byte message.
00339       // read it in. go to SECOND_OF_TWO state. do not 
00340       // return anything.
00341       //
00342       
00343       tmp_msg.SetByte1( b );
00344       state=SECOND_OF_TWO;
00345       return false;
00346     }
00347     
00348     case SECOND_OF_TWO:
00349     {
00350       //
00351       // this is the second byte of a two byte message.
00352       // read it in. form the message, and return in.
00353       // go back to FIRST_OF_TWO state to allow
00354       // running status.
00355       //
00356       
00357       tmp_msg.SetByte2( b );
00358       state=FIRST_OF_TWO;
00359       *msg=tmp_msg;
00360       
00361       return true;
00362     }
00363     
00364     case FIRST_OF_ONE_NORUN:
00365     {
00366       //
00367       // Single data byte system message, like MTC.
00368       // form the message, return it, and go to FIND_STATUS
00369       // state. Do not allow running status.
00370       //
00371       
00372       tmp_msg.SetByte1( b );
00373       state=FIND_STATUS;
00374       *msg=tmp_msg;
00375       
00376       return true;
00377     }
00378     
00379     case SYSEX_DATA:
00380     {
00381       //
00382       // store the byte into the sysex buffer. Stay
00383       // in this state. Only a status byte can
00384       // change our state.
00385       //
00386       
00387       sysex->PutByte( b );
00388       return false;
00389     }
00390     
00391     default:
00392     {
00393       //
00394       // UNKNOWN STATE! go into FIND_STATUS state
00395       //
00396       
00397       state=FIND_STATUS;
00398       return false;
00399     }
00400     
00401     }
00402   }
00403   
00404   
00405   
00406 }