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 "MIDIDevice.hxx" 00023 #include "MIDIIn.hxx" 00024 #include "MIDIOut.hxx" 00025 #include "MIDIClocker.hxx" 00026 #include "MIDIEnums.hxx" 00027 #include <algorithm> 00028 #include <cstdio> 00029 00030 using std::find; 00031 00032 using namespace CLAM; 00033 00034 MIDIManager& MIDIDevice::_MIDIManager(void) 00035 { 00036 if (mMIDIManager==0) 00037 throw Err("This MIDIDevice is not associated with any MIDIManager"); 00038 00039 return *mMIDIManager; 00040 } 00041 00042 void MIDIDevice::_SetMIDIManager(MIDIManager* am) 00043 { 00044 if (mMIDIManager==0) mMIDIManager = am; 00045 else if (mMIDIManager!=am) 00046 { 00047 throw Err("An MIDIDevice can only be associated with one MIDIManager"); 00048 } 00049 } 00050 00051 bool MIDIDevice::Register(MIDIManager* mm,MIDIIn& in) 00052 { 00055 mInputs.push_back(&in); 00056 _SetMIDIManager(mm); 00057 in.mpDevice = this; 00058 return true; 00059 } 00060 00061 bool MIDIDevice::Register(MIDIManager* mm,MIDIClocker& in) 00062 { 00063 _SetMIDIManager(mm); 00064 in.mpDevice = this; 00065 return true; 00066 } 00067 00068 bool MIDIDevice::Register(MIDIManager* mm,MIDIOut& out) 00069 { 00070 mOutputs.push_back(&out); 00071 _SetMIDIManager(mm); 00072 out.mpDevice = this; 00073 return true; 00074 } 00075 00076 void MIDIDevice::Unregister(MIDIIn& in) 00077 { 00078 if (in.mpDevice != this) 00079 { 00080 throw(Err("MIDIDevice::Unregister(): I am not this MIDIIn object's device.")); 00081 } 00082 std::vector<MIDIIn*>::iterator it = std::find(mInputs.begin(),mInputs.end(),&in); 00083 if (it == mInputs.end()) 00084 { 00085 throw(Err("MIDIDevice::Unregister(): MIDIIn object not registered in this device.")); 00086 } 00087 00090 for (int status = 0;status<8;status++) 00091 { 00092 for (int channel = 0;channel<16;channel++) 00093 { 00094 for (int i=0;i<128;i++) 00095 { 00096 if (target[status][channel][i]==&in) 00097 target[status][channel][i] = 0; 00098 } 00099 } 00100 } 00101 00102 mInputs.erase(it); 00103 in.mpDevice = 0; 00104 } 00105 00106 void MIDIDevice::Unregister(MIDIClocker& in) 00107 { 00108 in.mpDevice = 0; 00109 } 00110 00111 00112 void MIDIDevice::Unregister(MIDIOut& out) 00113 { 00114 std::vector<MIDIOut*>::iterator it = std::find(mOutputs.begin(),mOutputs.end(),&out); 00115 if (it == mOutputs.end()) 00116 { 00117 throw(Err("MIDIDevice::Unregister(): MIDIOut object not registered in this device.")); 00118 } 00119 mOutputs.erase(it); 00120 out.mpDevice = 0; 00121 } 00122 00123 00124 void MIDIDevice::GetInfo(MIDIDevice::TInfo &info) 00125 { 00126 info.mName = mName; 00127 } 00128 00129 void MIDIDevice::SetTarget( 00130 MIDI::Message msg, 00131 unsigned char chn,unsigned char firstData, 00132 MIDIIn* inp) 00133 { 00134 if (msg==MIDI::eNoteOnOff) 00135 { 00136 SetTarget(MIDI::eNoteOn, chn, firstData, inp); 00137 SetTarget(MIDI::eNoteOff,chn, firstData, inp); 00138 return; 00139 } 00140 00141 if (firstData==0x80) 00142 { 00143 for (firstData=0;firstData<128;firstData++) 00144 { 00145 SetTarget(msg,chn,firstData,inp); 00146 } 00147 return; 00148 } 00149 00150 if (msg==MIDI::eSystem) 00151 { 00152 if (chn==0) 00153 { 00154 fprintf(stderr,"SysEx not yet implemented\n"); 00155 exit(-1); 00156 } 00157 }else{ 00158 if (chn==0) 00159 { 00160 for (chn = 1;chn<=16;chn++) 00161 { 00162 SetTarget(msg,chn,firstData,inp); 00163 } 00164 return; 00165 } 00166 chn--; 00167 } 00168 target[msg][chn][firstData] = inp; 00169 } 00170 00171 void MIDIDevice::Start(void) 00172 { 00173 int status ; 00174 00177 for (status = 0;status<8;status++) 00178 { 00179 for (int channel = 0;channel<16;channel++) 00180 { 00181 for (int byte=0;byte<128;byte++) 00182 { 00183 target[status][channel][byte] = 0; 00184 } 00185 } 00186 } 00187 00188 for (unsigned int i=0; i<mInputs.size(); i++) 00189 { 00190 const MIDIIOConfig &cfg = 00191 dynamic_cast<const MIDIIOConfig&>(mInputs[i]->GetConfig()); 00192 00193 SetTarget( 00194 MIDI::Message(cfg.GetMessage()), 00195 cfg.GetChannel(), 00196 cfg.GetFirstData(), 00197 mInputs[i]); 00198 } 00199 00200 ConcreteStart(); 00201 } 00202 00203 void MIDIDevice::Stop(void) 00204 { 00205 ConcreteStop(); 00206 } 00207 00208 int MIDIDevice::GetMessageLength(unsigned char byte) 00209 { 00210 MIDI::Message cm = MIDI::StatusByteToMessage(byte); 00211 if (cm == MIDI::eSystem) 00212 { 00213 MIDI::SysMsg sm = MIDI::StatusByteToSysMsg(mData[0]); 00214 return MIDI::sNBytesPerSysMsg[int(sm)]; 00215 } 00216 else 00217 { 00218 mLastStatus = mData[0]; 00219 return MIDI::GetMessageInfo(cm).length; 00220 } 00221 } 00222 00223 void MIDIDevice::HandleRawByte(unsigned char byte) 00224 { 00225 if (byte==0xfe) return; 00226 if (mIndex==0) 00227 { 00228 if (byte&0x80) 00229 { 00230 mData[0] = byte; 00231 mIndex = 1; 00232 } 00233 else 00234 { 00235 if (mLastStatus) 00236 { 00237 mData[0] = mLastStatus; 00238 mData[1] = byte; 00239 mIndex = 2; 00240 } 00241 } 00242 mLength = GetMessageLength(mData[0]); 00243 }else 00244 { 00245 mData[mIndex++] = byte; 00246 } 00247 if (mLength && mIndex == mLength) 00248 { 00250 int status = ((mData[0]&0xF0)>>4)-8; 00251 int channel = mData[0]&0x0F; 00252 if (status == MIDI::eNoteOn && mData[2]==0) 00253 { 00254 status = MIDI::eNoteOff; 00255 mData[0] = 0x80|channel; 00257 } 00258 MIDIIn* t = target[status][channel][mData[1]]; 00260 if (t) 00261 { 00262 t->Handle(mData,mLength); 00263 } 00264 mIndex = 0; 00265 } 00266 } 00267