CLAM-Development
1.1
|
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