00001
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "Alsa.hpp"
00030 #include "../libH/Debug.hpp"
00031 #include "../libH/Exception.hpp"
00032 #include "../libH/stringconverter.hpp"
00033 #include <boost/format.hpp>
00034 #include <boost/mem_fn.hpp>
00035 #include <boost/bind.hpp>
00036 #include <string>
00037
00038 using namespace std;
00039 using namespace boost;
00040 using namespace H;
00041 using namespace Gizmod;
00042
00044
00046
00048
00050
00054 Alsa::Alsa() {
00055 mpDefaultMixerSwitch = NULL;
00056 mpDefaultMixerVolume = NULL;
00057 mDefaultMixerVolumePriority = -1;
00058 mDefaultMixerSwitchPriority = -1;
00059 mMuted = false;
00060 }
00061
00065 Alsa::~Alsa() {
00066 shutdown();
00067 }
00068
00070
00072
00077 AlsaMixer const * Alsa::getDefaultMixerSwitch() {
00078 return mpDefaultMixerSwitch;
00079 }
00080
00085 AlsaMixer const * Alsa::getDefaultMixerVolume() {
00086 return mpDefaultMixerVolume;
00087 }
00088
00093 size_t Alsa::getNumSoundCards() {
00094 return mSoundCards.size();
00095 }
00096
00100 AlsaSoundCard const * Alsa::getSoundCard(int Index) {
00101 if ( (Index < 0) || (size_t(Index) >= mSoundCards.size()) )
00102 return NULL;
00103 return mSoundCards[Index].get();
00104 }
00105
00109 void Alsa::init() {
00110
00111 shutdown();
00112
00113
00114 int ret = -1, CardID;
00115 do {
00116
00117 if ((CardID = snd_card_next(&ret)) < 0) {
00118 cerr << "Failed to Query Sound Card [" << ret + 1 << "] -- Error Code: " << CardID;
00119 continue;
00120 }
00121 if (ret > -1) {
00122 try {
00123 shared_ptr<AlsaSoundCard> pSoundCard = shared_ptr<AlsaSoundCard>(new AlsaSoundCard(this, CardID));
00124 mSoundCards.push_back(pSoundCard);
00125 } catch (H::Exception & e) {
00126
00127 cdbg1 << e.getExceptionMessage() << endl;
00128 }
00129 }
00130 } while (ret != -1);
00131 }
00132
00139 void Alsa::onAlsaEventMixerElementAttach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
00140
00141 cdbg1 << "Mixer Element Attached [" << Mixer.getName() << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;
00142 }
00143
00150 void Alsa::onAlsaEventMixerElementChange(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
00151
00152 if (Event.Type == ALSAEVENT_MIXERELEMENT_CHANGE)
00153 cdbg2 << "Mixer Element Changed [" << Mixer.getName() << "] with Mask [" << stringconverter(Event.IsActiveChanged) << stringconverter(Event.ElementsChanged) << stringconverter(Event.VolumePlaybackChanged) << "] on Sound Card [" << SoundCard.getCardName() << "] " << Mixer.VolumePlaybackPercent << endl;
00154 else
00155 cdbg2 << "Mixer Element Changed [" << Mixer.getName() << "] with Mask [" << stringconverter(Event.Mask) << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;
00156 }
00157
00166 void Alsa::_onAlsaEventMixerElementChange(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer & Mixer) {
00167
00168 int Priority = INT_MAX, CurPriority = 0;
00169 for (list<string>::iterator iter = mDefaultMixerPriorities.begin(); iter != mDefaultMixerPriorities.end(); iter ++, CurPriority ++) {
00170 if (stringconverter::toLower(Mixer.getName()) == stringconverter::toLower(*iter)) {
00171 Priority = CurPriority;
00172 break;
00173 }
00174 }
00175
00176
00177 if ( (!mpDefaultMixerVolume) || (Priority < mDefaultMixerVolumePriority) ) {
00178 if (Mixer.HasPlaybackVolume) {
00179 cdbg1 << "Setting Default Mixer Volume: " << Mixer.getName() << endl;
00180 mpDefaultMixerVolume = &Mixer;
00181 mDefaultMixerVolumePriority = Priority;
00182 }
00183 } else if ( (mpDefaultMixerVolume == &Mixer) && (!Mixer.HasPlaybackVolume) ) {
00184 mpDefaultMixerVolume = NULL;
00185 }
00186
00187
00188 if ( (!mpDefaultMixerSwitch) || (Priority < mDefaultMixerSwitchPriority) ) {
00189 if (Mixer.HasPlaybackSwitch) {
00190 cdbg1 << "Setting Default Mixer Switch: " << Mixer.getName() << endl;
00191 mpDefaultMixerSwitch = &Mixer;
00192 mDefaultMixerSwitchPriority = Priority;
00193 }
00194 } else if ( (mpDefaultMixerSwitch == &Mixer) && (!Mixer.HasPlaybackSwitch) ) {
00195 mpDefaultMixerSwitch = NULL;
00196 }
00197 }
00198
00205 void Alsa::onAlsaEventMixerElementDetach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard, AlsaMixer const & Mixer) {
00206
00207 cdbg3 << "Mixer Element Detached [" << Mixer.getName() << "] on Sound Card [" << SoundCard.getCardName() << "]" << endl;
00208 }
00209
00215 void Alsa::onAlsaEventSoundCardAttach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard) {
00216
00217 cdbg << "Attached to Sound Card [" << SoundCard.getCardHardwareID() << "] -- " << SoundCard.getCardName() << endl;
00218 }
00219
00225 void Alsa::onAlsaEventSoundCardDetach(AlsaEvent const & Event, AlsaSoundCard const & SoundCard) {
00226
00227 cdbg1 << "Sound Card Detached [" << SoundCard.getCardHardwareID() << "] -- " << SoundCard.getCardName() << endl;
00228 }
00229
00240 void Alsa::registerDefaultMixerPriority(std::string MixerName) {
00241 cdbg1 << "Registering Default Mixer Priority: " << MixerName << endl;
00242 mDefaultMixerPriorities.push_back(MixerName);
00243 }
00244
00248 void Alsa::shutdown() {
00249 if (mSoundCards.size()) {
00250 cdbg1 << "Shutting down [" << mSoundCards.size() << "] sound card connections..." << endl;
00251 for (size_t lp = 0; lp < mSoundCards.size(); lp ++)
00252 mSoundCards[lp]->shutdown();
00253 mSoundCards.clear();
00254 }
00255 }
00256
00262 void Alsa::toggleMuteAllCards() {
00263 for (size_t lp = 0; lp < mSoundCards.size(); lp ++)
00264 mSoundCards[lp]->setAllPlaybackSwitches(mMuted);
00265 mMuted = !mMuted;
00266 }