PortMIDIDevice.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 #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 
Generated by  doxygen 1.6.3