MIDIDevice.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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