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 #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