ALSAMIDIDevice.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
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;
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;
00139
00140 if (snd_ctl_card_info(handle, info) < 0) {
00141 snd_ctl_close(handle);
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