CLAM-Development
1.1
|
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 #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) // SysEx 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 //char name[64]; 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