PortMIDIDevice.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 #ifndef __PortMIDIDevice__
00022 #define __PortMIDIDevice__
00023
00024 #include "MIDIManager.hxx"
00025 #include <portmidi.h>
00026 #include <porttime.h>
00027 #include <iostream>
00028
00029 namespace CLAM {
00030
00031 std::ostream& operator<<( std::ostream& out_str, const PmDeviceInfo* dev_info )
00032 {
00033
00034 out_str << "Device Name: " << dev_info->name << std::endl;
00035 out_str << "Interface Name: " << dev_info->interf << std::endl;
00036 if ( dev_info->output == 1 ) out_str << "Output device" << std::endl ;
00037 else out_str << "Input device" << std::endl ;
00038
00039 return out_str;
00040 }
00041
00042 class PortMIDIDevice: public MIDIDevice
00043 {
00044 private:
00045 std::string mDevice;
00046 PmStream *mHandleIn;
00048 PmStream *mHandleOut;
00050 public:
00051 PortMIDIDevice(const std::string& name,const std::string& device);
00052
00053 ~PortMIDIDevice();
00054
00055 void ConcreteStart(void) throw(Err);
00056 void ConcreteStop(void) throw(Err);
00057 void Read(void) throw(Err);
00058 void Write(unsigned char* msg,int size) throw(Err);
00059 void OpenInput(int dev) throw(Err);
00060 void OpenOutput(int dev) throw(Err);
00061 };
00062
00063
00064 PortMIDIDevice::PortMIDIDevice(const std::string& name,const std::string& device):
00065 MIDIDevice(name)
00066 {
00067 mDevice = device;
00069 mHandleIn = NULL;
00070 mHandleOut = NULL;
00071 }
00072
00073 void PortMIDIDevice::OpenInput(int dev) throw(Err)
00074 {
00075 PmError err = Pm_OpenInput( &mHandleIn,
00076 dev,
00077 NULL,
00078 100,
00079 NULL,
00080 0 );
00081
00082 if (err)
00083 {
00084 std::string str("Could not open PortMIDIDevice ");
00085 str += mDevice;
00086 throw Err(str.c_str());
00087 }
00088 }
00089
00090 void PortMIDIDevice::OpenOutput(int dev) throw(Err)
00091 {
00092 PmError err = Pm_OpenOutput(&mHandleOut,
00093 dev,
00094 NULL,
00095 0,
00096 NULL,
00097 NULL,
00098 0);
00099 if (err)
00100 {
00101 std::string str("Could not open PortMIDIDevice ");
00102 str += mDevice;
00103 throw Err(str.c_str());
00104 }
00105 }
00106
00107 void PortMIDIDevice::ConcreteStart(void) throw(Err)
00108 {
00109 int dev;
00110
00111 if (mDevice == "default")
00112 {
00113 if (mInputs.size())
00114 {
00115 OpenInput(Pm_GetDefaultInputDeviceID());
00116 }
00117 if (mOutputs.size())
00118 {
00119 OpenOutput(Pm_GetDefaultOutputDeviceID());
00120 }
00121 return;
00122 }
00123
00124 std::string type = mDevice.substr(0,mDevice.find(":",0));
00125 std::string name = mDevice.substr(mDevice.find(":",0)+1,mDevice.size());
00126
00127 if (mInputs.size())
00128 {
00129 if (type == "input")
00130 {
00131 for ( dev = 0; dev < Pm_CountDevices(); dev++)
00132 {
00133 const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
00134 if (info->input && name == info->name)
00135 {
00136 OpenInput(dev);
00137 return;
00138 }
00139 }
00140 }
00141 std::string str("Could not find PortMIDIDevice ");
00142 str += mDevice;
00143 throw Err(str.c_str());
00144 }
00145
00146 if (mOutputs.size())
00147 {
00148 if (type == "output")
00149 {
00150 for ( dev = 0; dev < Pm_CountDevices(); dev++)
00151 {
00152 const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
00153 if (info->output && name == info->name)
00154 {
00155 OpenOutput(dev);
00156 return;
00157 }
00158 }
00159 }
00160 std::string str("Could not find PortMIDIDevice ");
00161 str += mDevice;
00162 throw Err(str.c_str());
00163 }
00164 }
00165
00166 void PortMIDIDevice::ConcreteStop(void) throw(Err)
00167 {
00168
00169 if ( mHandleIn )
00170 {
00171 Pm_Close(mHandleIn);
00172 mHandleIn = 0 ;
00173 }
00174
00175 if ( mHandleOut )
00176 {
00177 Pm_Close(mHandleOut);
00178 mHandleOut = 0 ;
00179 }
00180
00181 }
00182
00183 void PortMIDIDevice::Write(unsigned char* msg,int size) throw(Err)
00184 {
00185 int m = msg[0]&0xff;
00186
00187 if(m == 0xf0)
00188 {
00189 #ifdef WIN32
00190 Pm_WriteSysEx(mHandleOut,0,(char*) msg);
00191 #else
00192 Pm_WriteSysEx(mHandleOut,0,msg);
00193 #endif
00194
00195 }
00196 else
00197 {
00198 if(size == 3)
00199 {
00200 Pm_WriteShort(mHandleOut,0,Pm_Message(msg[0],msg[1],msg[2]));
00201 }
00202 else
00203 {
00204 Pm_WriteShort(mHandleOut,0,Pm_Message(msg[0],msg[1],0));
00205 }
00206 }
00207 }
00208
00209 void PortMIDIDevice::Read(void) throw(Err)
00210 {
00211 PmEvent buffer;
00212 unsigned char status, data1, data2;
00213
00215 while (Pm_Poll(mHandleIn) == TRUE)
00216 {
00218 if (Pm_Read(mHandleIn, &buffer, 1) == pmBufferOverflow) continue;
00221 status = ( unsigned char ) Pm_MessageStatus(buffer.message);
00222
00223 if ( GetMessageLength( status ) == 3 )
00224 {
00225 data1 = ( unsigned char ) Pm_MessageData1(buffer.message);
00226 data2 = ( unsigned char ) Pm_MessageData2(buffer.message);
00227
00228 HandleRawByte(status);
00229 HandleRawByte(data1);
00230 HandleRawByte(data2);
00231 }
00232 else
00233 {
00234 data1 = ( unsigned char ) Pm_MessageData1(buffer.message);
00235
00236 HandleRawByte(status);
00237 HandleRawByte(data1);
00238 }
00239
00240 }
00241
00242 }
00243
00244 PortMIDIDevice::~PortMIDIDevice()
00245 {
00246 Stop();
00247 }
00248
00249 class PortMIDIDeviceList: public MIDIDeviceList
00250 {
00251 static PortMIDIDeviceList sDevices;
00252
00253 PortMIDIDeviceList()
00254 :MIDIDeviceList(std::string("portmidi"))
00255 {
00256
00257 int dev = 0 ;
00258
00259 Pm_Initialize() ;
00260
00262 for ( dev = 0; dev < Pm_CountDevices(); dev++)
00263 {
00264 const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
00265
00266 std::string name(info->name);
00267
00268 if (info->input)
00269 mAvailableDevices.push_back(std::string("input:")+name);
00270
00271 if (info->output)
00272 mAvailableDevices.push_back(std::string("output:")+name);
00273 }
00274
00275 AddMe();
00276 }
00277
00278 public:
00279 ~PortMIDIDeviceList()
00280 {
00281 Pm_Terminate() ;
00282 }
00283
00284 std::string DefaultDevice(void)
00285 {
00286 return std::string("default");
00287 }
00288
00289 MIDIDevice* Create(
00290 const std::string& name,const std::string& device)
00291 {
00292 return new PortMIDIDevice(name,device);
00293 }
00294 };
00295
00296 PortMIDIDeviceList PortMIDIDeviceList::sDevices;
00297
00298
00299 }
00300
00301 #endif
00302
00303