Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsaudioctrl.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_MIXER__
00034 #include "mmsmedia/mmsaudioctrl.h"
00035 
00036 snd_mixer_t         *MMSAudioCtrl::handle = NULL;
00037 string              MMSAudioCtrl::card = "default";
00038 int                 MMSAudioCtrl::volume = -1;      /* in percent */
00039 long                MMSAudioCtrl::xval = -1;         /* re-calculated volume for card */
00040 bool                MMSAudioCtrl::muteFlag = false; /* mute on/off */
00041 long                MMSAudioCtrl::pmin;             /* range (not in percent) */
00042 long                MMSAudioCtrl::pmax;             /* range (not in percent) */
00043 string              MMSAudioCtrl::channel = "";
00044 snd_mixer_elem_t    *MMSAudioCtrl::elem = NULL;
00045 bool                MMSAudioCtrl::isSwitchable = false;
00046 
00047 /**
00048  * Constructor of MMSAudioCtrl class.
00049  *
00050  * The first instance of this class assigns
00051  * an audio channel, attaches to the mixer
00052  * of the sound card and gets the current
00053  * settings.
00054  *
00055  * @param   channel [in]    audio channel
00056  */
00057 MMSAudioCtrl::MMSAudioCtrl(string channel) {
00058     int     err;
00059 
00060     if(this->channel=="") {
00061         this->channel=channel;
00062     }
00063 
00064     if (!this->handle) {
00065         /* open the mixer */
00066         if ((err = snd_mixer_open(&(this->handle), 0)) < 0)
00067             throw MMSAudioCtrlError(err,"snd_mixer_open() failed");
00068 
00069         /* attach the card */
00070         if ((err = snd_mixer_attach(this->handle, this->card.c_str())) < 0) {
00071             snd_mixer_close(this->handle);
00072             throw MMSAudioCtrlError(err,"snd_mixer_attach() with card = '"
00073                                             + this->card + "' failed");
00074         }
00075 
00076         /* register */
00077         if ((err = snd_mixer_selem_register(this->handle, NULL, NULL)) < 0) {
00078             snd_mixer_close(this->handle);
00079             string s = snd_strerror(err);
00080             throw MMSAudioCtrlError(err,"snd_mixer_selem_register() failed with '" + s + "'");
00081         }
00082 
00083         /* load */
00084         if ((err = snd_mixer_load(this->handle)) < 0) {
00085             snd_mixer_close(this->handle);
00086             string s = snd_strerror(err);
00087             throw MMSAudioCtrlError(err,"snd_mixer_load() failed with '" + s + "'");
00088         }
00089     }
00090 
00091     if (!this->elem) {
00092         /* searching for the first active element */
00093         for (this->elem = snd_mixer_first_elem(this->handle);
00094              this->elem;
00095              this->elem = snd_mixer_elem_next(this->elem)) {
00096 
00097             string mix = snd_mixer_selem_get_name(this->elem);
00098             DEBUGMSG("MMSMedia", "got mixer channel: %s", mix.c_str());
00099             /* is active? */
00100             if (!snd_mixer_selem_is_active(this->elem))
00101                 continue;
00102 
00103             /* has playback volume? */
00104             if (!snd_mixer_selem_has_playback_volume(this->elem))
00105                 continue;
00106 
00107             if (this->channel!="") {
00108                 if(strcmp(this->channel.c_str(),snd_mixer_selem_get_name(this->elem))!=0)
00109                     continue;
00110             }
00111 
00112             /* we have found our channel*/
00113             /* get volume range */
00114             snd_mixer_selem_get_playback_volume_range(this->elem, &(this->pmin), &(this->pmax));
00115 
00116             /* check if this elem is mutable */
00117             isSwitchable = (snd_mixer_selem_has_playback_switch(elem) > 0);
00118 
00119             /* get the current volume settings */
00120             getVolume();
00121 
00122             return;
00123         }
00124 
00125         throw MMSAudioCtrlError(0,"no element found");
00126     }
00127 }
00128 
00129 /**
00130  * Destructor of MMSAudioCtrl class.
00131  */
00132 MMSAudioCtrl::~MMSAudioCtrl() {
00133     /* release all */
00134 }
00135 
00136 /**
00137  * Sets the volume of the audio device.
00138  *
00139  * @param   count   [in]    volume in percent
00140  *
00141  * @note If count is less than 0 or more than 100
00142  * it will be set correctly to 0 or 100.
00143  */
00144 void MMSAudioCtrl::setVolume(int count) {
00145     /* calculate the new value */
00146     this->xval = -1;
00147     this->volume = count;
00148     if (this->volume < 0) this->volume = 0;
00149     if (this->volume > 100) this->volume = 100;
00150     if (this->volume == 0)
00151         this->xval = this->pmin;
00152     else
00153     if (this->volume == 100)
00154         this->xval = this->pmax;
00155     else
00156         this->xval = this->pmin + ((this->pmax - this->pmin) * (long)this->volume) / 100;
00157 
00158     /* set the new value */
00159     snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, this->xval);
00160     snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, this->xval);
00161 
00162     /* set mute to off */
00163     this->muteFlag = false;
00164 }
00165 
00166 /**
00167  * Returns the currently set volume.
00168  *
00169  * @param   dfCard  [in]    get the volume directly from card?
00170  *
00171  * @return Volume in percent
00172  */
00173 int MMSAudioCtrl::getVolume(bool dfCard) {
00174     long    lval, rval;
00175     int     retval = this->volume;
00176 
00177     if ((!this->muteFlag)||(dfCard)) {
00178         /* get the current volume settings */
00179         snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &lval);
00180         snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &rval);
00181         if ((lval != this->xval)||(rval != this->xval))
00182             retval = (int)(((lval + (rval - lval) / 2) * 100) / (this->pmax - this->pmin));
00183         if (!this->muteFlag) this->volume = retval;
00184         return retval;
00185     }
00186     return this->volume;
00187 }
00188 
00189 /**
00190  * Turns up the volume.
00191  *
00192  * @param   count   [in]    value in percent to increase
00193  */
00194 void MMSAudioCtrl::volumeUp(int count) {
00195     setVolume(getVolume() + count);
00196 }
00197 
00198 /**
00199  * Turns down the volume.
00200  *
00201  * @param   count   [in]    value in percent to decrease
00202  */
00203 void MMSAudioCtrl::volumeDown(int count) {
00204     setVolume(getVolume() - count);
00205 }
00206 
00207 /**
00208  * Checks if sound is muted.
00209  *
00210  * @return  true if sound is muted
00211  */
00212 bool MMSAudioCtrl::isMute() {
00213     if(isSwitchable) {
00214         int valL = 0;
00215         int valR = 0;
00216         snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &valL);
00217         snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, &valR);
00218         if(valL > 0 || valR > 0) {
00219             return false;
00220         }
00221         return true;
00222     }
00223 
00224     if (this->muteFlag) {
00225         if (getVolume(true) > 0) {
00226             /* switch to off */
00227             this->muteFlag = false;
00228         }
00229     }
00230     return this->muteFlag;
00231 }
00232 
00233 /**
00234  * Mutes/unmutes the sound.
00235  */
00236 void MMSAudioCtrl::mute() {
00237     if (isMute()) {
00238         /* switch to on */
00239         if(isSwitchable) {
00240             snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, 1);
00241             snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, 1);
00242         } else {
00243             setVolume(this->volume);
00244         }
00245     } else {
00246         /* set mute */
00247         if(isSwitchable) {
00248             snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, 0);
00249             snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, 0);
00250         } else {
00251             snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, 0);
00252             snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, 0);
00253 
00254             /* set mute to on */
00255             this->muteFlag = true;
00256         }
00257     }
00258 }
00259 
00260 #endif /* __HAVE_MIXER__ */

Generated by doxygen