FileMIDIDevice.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "MIDIIn.hxx"
00023 #include "MIDIDeviceList.hxx"
00024 #include "MIDIDevice.hxx"
00025 
00026 #include "MIDIEvent.hxx"
00027 #include "MIDITrack.hxx"
00028 #include "MIDISong.hxx"
00029 #include "MIDITempo.hxx"
00030 #include "MIDIReader.hxx"
00031 #include "MIDISongPlayer.hxx"
00032 
00033 namespace CLAM {
00034 
00035         class FileMIDIDevice: public MIDIDevice
00036         {
00037         private:
00038                 std::string mFilename;
00039 		::MIDI::Song mSong;
00040 		::MIDI::SongPlayer mSongPlayer;
00041 		::MIDI::Tempo mTempo;
00042                 bool  mHavePendingEvent;
00043 		::MIDI::Event mPendingEvent;
00044                 int   mPendingTrackId;
00045 		::MIDI::Milliseconds mPendingTime;
00046 		::MIDI::Milliseconds mCurTime;
00047                 bool mReadDone;
00048         public:
00049                 FileMIDIDevice(const std::string& name,const std::string& device);
00050                 ~FileMIDIDevice();
00051 
00052                 void ConcreteStart(void) throw(Err);
00053                 void ConcreteStop(void) throw(Err);
00054 
00055                 void Read(void) throw(Err);
00056                 void Write(unsigned char* msg,int size) throw(Err);
00057                 void SetClock(TControlData val);
00058         };
00059 
00060         FileMIDIDevice::FileMIDIDevice(const std::string& name,const std::string& fname): 
00061                 MIDIDevice(name)
00062         {
00063                 mFilename = fname;
00064                 mHavePendingEvent = false;
00065                 mReadDone = false;
00066                 mCurTime = 0;
00067         }
00068 
00069         void FileMIDIDevice::ConcreteStart(void) throw(Err)
00070         {
00071                 if (!mReadDone)
00072                 {
00073                         
00074                         mReadDone = true;
00075 			::MIDI::Reader reader(mFilename.c_str());
00076                         
00077                         if (!reader.Ok())
00078                         {
00079                                         std::string str("Could not open FileMIDIDevice with file ");
00080                                         str += mFilename;
00081                                         throw Err(str.c_str());
00082                         }
00083                         try{
00084                                 reader.Read(mSong);
00085                         }
00086                         catch(::MIDI::Reader::Error err)
00087                         {
00088                                 throw Err(err.mStr);
00089                         }
00090                         mSongPlayer.Init(&mSong);
00091                         mTempo.Init(&mSong);
00092 
00093                 }
00094         }
00095 
00096         void FileMIDIDevice::ConcreteStop(void) throw(Err)
00097         {
00098         }
00099 
00100         void FileMIDIDevice::SetClock(TControlData val)
00101         {
00102                 mCurTime = (::MIDI::Milliseconds) val;
00103         }
00104 
00105         void FileMIDIDevice::Write(unsigned char* msg,int size) throw(Err)
00106         {
00107                 throw Err("FileMIDIDevice::Write not implemented yet");
00108         }
00109 
00110         void FileMIDIDevice::Read(void) throw(Err)
00111         {
00112                 bool flag;
00113                 static int nbytesPerChnMsg[7] =
00114                 { 3,3,3,3,2,3,3 };
00115                 do
00116                 {
00117                         flag = false;
00118                         if (!mHavePendingEvent)
00119                         {
00120                                 mHavePendingEvent = 
00121                                         mSongPlayer.GetEvent(mPendingEvent,mPendingTrackId);
00122                                 if (mHavePendingEvent)
00123                                 {
00124                                         mPendingTime = mTempo.TicksToTime(mPendingEvent.GetTicks());
00125                                 }else{
00126                                   HandleRawByte(0xF0|int(MIDI::eStop)); // system stop
00127                                 }
00128                         }
00129                         if (mHavePendingEvent) {
00130                                 if (mCurTime >= mPendingTime)
00131                                 {
00132                                         if (
00133                                                 mPendingEvent[0] != 0xF0 && 
00134                                                 mPendingEvent[0] != 0xF7 && 
00135                                                 mPendingEvent[0] != 0xFF)
00136                                         // skip meta events
00137                                         {
00138                                                 int nbytes = nbytesPerChnMsg[((mPendingEvent[0]&0xF0)>>4)-8];
00139                                                 if ((mPendingEvent[0]&0xF0)==0x80)
00140                                                 {
00141                                                         HandleRawByte((mPendingEvent[0]&0x0F)|0x90);                            
00142                                                         HandleRawByte(mPendingEvent[1]);                                
00143                                                         HandleRawByte(0);                                                                               
00144                                                 }else
00145                                                 for (int i = 0; i < nbytes; i++)
00146                                                 {
00147                                                         HandleRawByte(mPendingEvent[i]);                                
00148                                                 }
00149                                         }
00150                                         mHavePendingEvent = false;
00151                                         flag = true;
00152                                 }
00153                         }
00154                 } while (flag);
00155         }
00156 
00157         FileMIDIDevice::~FileMIDIDevice()
00158         {
00159         }
00160 
00161         class FileMIDIDeviceList: public MIDIDeviceList
00162         {
00163                 static FileMIDIDeviceList sDevices;
00164 
00165                 FileMIDIDeviceList()
00166                         :MIDIDeviceList(std::string("file"))
00167                 {
00168                         AddMe();
00169                         mAvailableDevices.push_back("*.mid");
00170                 }
00171         public:
00172 
00173                 std::string DefaultDevice(void)
00174                 {
00175                         return "file:unknown.mid";
00176                 }
00177 
00178                 MIDIDevice* Create(
00179                         const std::string& name,const std::string& device)
00180                 {
00181                         return new FileMIDIDevice(name,device);
00182                 }
00183         };
00184 
00185         FileMIDIDeviceList FileMIDIDeviceList::sDevices;
00186 }
00187 
00188 
00189 
00190 
00191 
00192 
00193 
Generated by  doxygen 1.6.3