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