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