CLAM-Development  1.4.0
PortMIDIDevice.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 #ifndef __PortMIDIDevice__
22 #define __PortMIDIDevice__
23 
24 #include "MIDIManager.hxx"
25 #include <portmidi.h>
26 #include <porttime.h>
27 #include <iostream>
28 
29 namespace CLAM {
30 
31  std::ostream& operator<<( std::ostream& out_str, const PmDeviceInfo* dev_info )
32  {
33 
34  out_str << "Device Name: " << dev_info->name << std::endl;
35  out_str << "Interface Name: " << dev_info->interf << std::endl;
36  if ( dev_info->output == 1 ) out_str << "Output device" << std::endl ;
37  else out_str << "Input device" << std::endl ;
38 
39  return out_str;
40  }
41 
42  class PortMIDIDevice: public MIDIDevice
43  {
44  private:
45  std::string mDevice;
46  PmStream *mHandleIn;
48  PmStream *mHandleOut;
50  public:
51  PortMIDIDevice(const std::string& name,const std::string& device);
52 
53  ~PortMIDIDevice();
54 
55  void ConcreteStart(void) throw(Err);
56  void ConcreteStop(void) throw(Err);
57  void Read(void) throw(Err);
58  void Write(unsigned char* msg,int size) throw(Err);
59  void OpenInput(int dev) throw(Err);
60  void OpenOutput(int dev) throw(Err);
61  };
62 
63 
64  PortMIDIDevice::PortMIDIDevice(const std::string& name,const std::string& device):
65  MIDIDevice(name)
66  {
67  mDevice = device;
69  mHandleIn = NULL;
70  mHandleOut = NULL;
71  }
72 
73  void PortMIDIDevice::OpenInput(int dev) throw(Err)
74  {
75  PmError err = Pm_OpenInput( &mHandleIn,
76  dev,
77  NULL,
78  100,
79  NULL,
80  0 );
81 
82  if (err)
83  {
84  std::string str("Could not open PortMIDIDevice ");
85  str += mDevice;
86  throw Err(str.c_str());
87  }
88  }
89 
90  void PortMIDIDevice::OpenOutput(int dev) throw(Err)
91  {
92  PmError err = Pm_OpenOutput(&mHandleOut,
93  dev,
94  NULL,
95  0,
96  NULL,
97  NULL,
98  0);
99  if (err)
100  {
101  std::string str("Could not open PortMIDIDevice ");
102  str += mDevice;
103  throw Err(str.c_str());
104  }
105  }
106 
107  void PortMIDIDevice::ConcreteStart(void) throw(Err)
108  {
109  int dev;
110 
111  if (mDevice == "default")
112  {
113  if (mInputs.size())
114  {
115  OpenInput(Pm_GetDefaultInputDeviceID());
116  }
117  if (mOutputs.size())
118  {
119  OpenOutput(Pm_GetDefaultOutputDeviceID());
120  }
121  return;
122  }
123 
124  std::string type = mDevice.substr(0,mDevice.find(":",0));
125  std::string name = mDevice.substr(mDevice.find(":",0)+1,mDevice.size());
126 
127  if (mInputs.size())
128  {
129  if (type == "input")
130  {
131  for ( dev = 0; dev < Pm_CountDevices(); dev++)
132  {
133  const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
134  if (info->input && name == info->name)
135  {
136  OpenInput(dev);
137  return;
138  }
139  }
140  }
141  std::string str("Could not find PortMIDIDevice ");
142  str += mDevice;
143  throw Err(str.c_str());
144  }
145 
146  if (mOutputs.size())
147  {
148  if (type == "output")
149  {
150  for ( dev = 0; dev < Pm_CountDevices(); dev++)
151  {
152  const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
153  if (info->output && name == info->name)
154  {
155  OpenOutput(dev);
156  return;
157  }
158  }
159  }
160  std::string str("Could not find PortMIDIDevice ");
161  str += mDevice;
162  throw Err(str.c_str());
163  }
164  }
165 
166  void PortMIDIDevice::ConcreteStop(void) throw(Err)
167  {
168 
169  if ( mHandleIn )
170  {
171  Pm_Close(mHandleIn);
172  mHandleIn = 0 ;
173  }
174 
175  if ( mHandleOut )
176  {
177  Pm_Close(mHandleOut);
178  mHandleOut = 0 ;
179  }
180 
181  }
182 
183  void PortMIDIDevice::Write(unsigned char* msg,int size) throw(Err)
184  {
185  int m = msg[0]&0xff;
186 
187  if(m == 0xf0) // SysEx
188  {
189 #ifdef WIN32
190  Pm_WriteSysEx(mHandleOut,0,(char*) msg);
191 #else
192  Pm_WriteSysEx(mHandleOut,0,msg);
193 #endif
194 
195  }
196  else
197  {
198  if(size == 3)
199  {
200  Pm_WriteShort(mHandleOut,0,Pm_Message(msg[0],msg[1],msg[2]));
201  }
202  else
203  {
204  Pm_WriteShort(mHandleOut,0,Pm_Message(msg[0],msg[1],0));
205  }
206  }
207  }
208 
209  void PortMIDIDevice::Read(void) throw(Err)
210  {
211  PmEvent buffer;
212  unsigned char status, data1, data2;
213 
215  while (Pm_Poll(mHandleIn) == TRUE)
216  {
218  if (Pm_Read(mHandleIn, &buffer, 1) == pmBufferOverflow) continue;
221  status = ( unsigned char ) Pm_MessageStatus(buffer.message);
222 
223  if ( GetMessageLength( status ) == 3 )
224  {
225  data1 = ( unsigned char ) Pm_MessageData1(buffer.message);
226  data2 = ( unsigned char ) Pm_MessageData2(buffer.message);
227 
228  HandleRawByte(status);
229  HandleRawByte(data1);
230  HandleRawByte(data2);
231  }
232  else
233  {
234  data1 = ( unsigned char ) Pm_MessageData1(buffer.message);
235 
236  HandleRawByte(status);
237  HandleRawByte(data1);
238  }
239 
240  }
241 
242  }
243 
244  PortMIDIDevice::~PortMIDIDevice()
245  {
246  Stop();
247  }
248 
249  class PortMIDIDeviceList: public MIDIDeviceList
250  {
251  static PortMIDIDeviceList sDevices;
252 
253  PortMIDIDeviceList()
254  :MIDIDeviceList(std::string("portmidi"))
255  {
256  //char name[64];
257  int dev = 0 ;
258 
259  Pm_Initialize() ;
260 
262  for ( dev = 0; dev < Pm_CountDevices(); dev++)
263  {
264  const PmDeviceInfo *info = Pm_GetDeviceInfo(dev);
265 
266  std::string name(info->name);
267 
268  if (info->input)
269  mAvailableDevices.push_back(std::string("input:")+name);
270 
271  if (info->output)
272  mAvailableDevices.push_back(std::string("output:")+name);
273  }
274 
275  AddMe();
276  }
277 
278 public:
279  ~PortMIDIDeviceList()
280  {
281  Pm_Terminate() ;
282  }
283 
284  std::string DefaultDevice(void)
285  {
286  return std::string("default");
287  }
288 
289  MIDIDevice* Create(
290  const std::string& name,const std::string& device)
291  {
292  return new PortMIDIDevice(name,device);
293  }
294  };
295 
296  PortMIDIDeviceList PortMIDIDeviceList::sDevices;
297 
298 
299 }
300 
301 #endif
302 
303