MIDIDevice.cxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3