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 00022 #include "MIDIIn.hxx" 00023 #include <alsa/asoundlib.h> 00024 #include "MIDIDeviceList.hxx" 00025 #include "MIDIDevice.hxx" 00026 #include <sstream> 00027 00028 namespace CLAM { 00029 00030 class ALSAMIDIDevice: public MIDIDevice 00031 { 00032 private: 00033 std::string mDevice; 00034 snd_rawmidi_t *mHandleIn; 00035 snd_rawmidi_t *mHandleOut; 00036 snd_rawmidi_status_t *mStatusIn; 00037 public: 00038 ALSAMIDIDevice(const std::string& name,const std::string& device); 00039 ~ALSAMIDIDevice(); 00040 00041 void ConcreteStart(void) throw(Err); 00042 void ConcreteStop(void) throw(Err); 00043 00044 void Read(void) throw(Err); 00045 void Write(unsigned char* msg,int size) throw(Err); 00046 }; 00047 00048 ALSAMIDIDevice::ALSAMIDIDevice(const std::string& name,const std::string& device): 00049 MIDIDevice(name) 00050 { 00051 mHandleIn = NULL; 00052 mHandleOut = NULL; 00053 mStatusIn = NULL; 00054 mDevice = device; 00055 } 00056 00057 void ALSAMIDIDevice::ConcreteStart(void) throw(Err) 00058 { 00059 snd_rawmidi_t** handleInRef = NULL; 00060 snd_rawmidi_t** handleOutRef = NULL; 00061 00062 if (mInputs.size()) handleInRef = &mHandleIn; 00063 if (mOutputs.size()) handleOutRef = &mHandleOut; 00064 00065 int err = snd_rawmidi_open(handleInRef,handleOutRef,mDevice.c_str(), 00066 SND_RAWMIDI_NONBLOCK); 00067 if (err) 00068 { 00069 std::string str("Could not open ALSAMIDIDevice "); 00070 str += mDevice; 00071 throw Err(str.c_str()); 00072 } 00073 snd_rawmidi_status_malloc(&mStatusIn); 00074 00075 } 00076 00077 void ALSAMIDIDevice::ConcreteStop(void) throw(Err) 00078 { 00079 if (mHandleIn) { 00080 snd_rawmidi_drain(mHandleIn); 00081 snd_rawmidi_close(mHandleIn); 00082 snd_rawmidi_status_free(mStatusIn); 00083 } 00084 00085 if(mHandleOut){ 00086 snd_rawmidi_drain(mHandleOut); 00087 snd_rawmidi_close(mHandleOut); 00088 } 00089 } 00090 00091 void ALSAMIDIDevice::Write(unsigned char* msg,int size) throw(Err) 00092 { 00093 snd_rawmidi_write(mHandleOut,msg,size); 00094 snd_rawmidi_drain(mHandleOut); 00095 } 00096 00097 void ALSAMIDIDevice::Read(void) throw(Err) 00098 { 00099 unsigned char ch; 00100 size_t n; 00101 do 00102 { 00103 int err = snd_rawmidi_read(mHandleIn,&ch,1); 00104 if (err!=-EAGAIN) 00105 { 00106 HandleRawByte(ch); 00107 } 00108 snd_rawmidi_status(mHandleIn,mStatusIn); 00109 n = snd_rawmidi_status_get_avail(mStatusIn); 00110 } while (n); 00111 } 00112 00113 ALSAMIDIDevice::~ALSAMIDIDevice() 00114 { 00115 Stop(); 00116 } 00117 00118 class ALSAMIDIDeviceList: public MIDIDeviceList 00119 { 00120 static ALSAMIDIDeviceList sDevices; 00121 00122 ALSAMIDIDeviceList() 00123 :MIDIDeviceList(std::string("alsa")) 00124 { 00125 int card, dev; 00126 snd_ctl_t *handle; 00127 snd_ctl_card_info_t *info; 00128 00129 snd_ctl_card_info_alloca(&info); 00130 card = -1; 00131 if (snd_card_next(&card) < 0 || card < 0) 00132 return; // No cards found 00133 while (card >= 0) { 00134 std::stringstream namestr; 00135 namestr << "hw:" << card; 00136 std::string name(namestr.str()); 00137 if (snd_ctl_open(&handle, name.c_str(), 0) < 0) 00138 continue; // Card control open error! 00139 00140 if (snd_ctl_card_info(handle, info) < 0) { 00141 snd_ctl_close(handle); // Card control read error! 00142 continue; 00143 } 00144 dev = -1; 00145 while (1) { 00146 snd_ctl_rawmidi_next_device(handle, &dev); 00147 if (dev < 0) 00148 break; 00149 std::stringstream dname; 00150 dname << name << "," << dev; 00151 mAvailableDevices.push_back(dname.str()); 00152 } 00153 snd_ctl_close(handle); 00154 if (snd_card_next(&card) < 0) 00155 break; 00156 } 00157 00158 AddMe(); 00159 } 00160 public: 00161 00162 std::string DefaultDevice(void) 00163 { 00164 return "hw:0,0"; 00165 } 00166 00167 MIDIDevice* Create( 00168 const std::string& name,const std::string& device) 00169 { 00170 return new ALSAMIDIDevice(name,device); 00171 } 00172 }; 00173 00174 ALSAMIDIDeviceList ALSAMIDIDeviceList::sDevices; 00175 } 00176