Ejemplo n.º 1
0
static void
gam_slider_pan_update_volume (GamSliderPan *gam_slider_pan)
{
    GamSliderPanPrivate *priv;

    gint left_chn = 0, right_chn = 0;
    glong pmin, pmax;

    priv = GAM_SLIDER_PAN_GET_PRIVATE (gam_slider_pan);

    if (snd_mixer_selem_has_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan))))
        snd_mixer_selem_get_playback_volume_range (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), &pmin, &pmax);
    else
        snd_mixer_selem_get_capture_volume_range (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), &pmin, &pmax);

    left_chn = right_chn = rint ((100 - GTK_ADJUSTMENT (priv->vol_adjustment)->value) / (100 / (gfloat)pmax));

    if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) {
        if (GTK_ADJUSTMENT (priv->pan_adjustment)->value < 0) {
            right_chn = rint (left_chn - ((gfloat)ABS(GTK_ADJUSTMENT (priv->pan_adjustment)->value) / 100) * left_chn);
        } else if (GTK_ADJUSTMENT (priv->pan_adjustment)->value > 0) {
            left_chn = rint (right_chn - ((gfloat)GTK_ADJUSTMENT (priv->pan_adjustment)->value / 100) * right_chn);
        }
    }

    if (snd_mixer_selem_has_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) {
        snd_mixer_selem_set_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_LEFT, left_chn);
        if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan))))
            snd_mixer_selem_set_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, right_chn);
    } else {
        snd_mixer_selem_set_capture_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_LEFT, left_chn);
        if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan))))
            snd_mixer_selem_set_capture_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, right_chn);
    }
}
Ejemplo n.º 2
0
void AmeSystemSound::setVolume(int v)
{
	if (!mixer_element)
		return;
	snd_mixer_selem_set_playback_volume(mixer_element, SND_MIXER_SCHN_FRONT_LEFT, v);
	snd_mixer_selem_set_playback_volume(mixer_element, SND_MIXER_SCHN_FRONT_RIGHT, v);
}
Ejemplo n.º 3
0
static void elem_set_vol_percent(snd_mixer_elem_t *elem, int vol_percent)
{
	int i;
	long pmin, pmax, value;
	
	//sdbg("%s: set mixer element volume\n", __func__);
	for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) {
		if (snd_mixer_selem_has_playback_channel(elem, i) && 
				!snd_mixer_selem_has_common_volume(elem)) {
			snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax);
		/* playback volume */
			if (snd_mixer_selem_has_playback_volume(elem)) {
				value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin));
				snd_mixer_selem_set_playback_volume(elem, i, value);
			}
		} else if (snd_mixer_selem_has_capture_channel(elem, i) && 
				!snd_mixer_selem_has_common_volume(elem)) {
		/* capture volume */
			snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax);
			if (snd_mixer_selem_has_capture_volume(elem)) {
				value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin));
				snd_mixer_selem_set_capture_volume(elem, i, value);
			}
		} else {
		/* Misc. ex: Boost */
			snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax);
			value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin));
			snd_mixer_selem_set_playback_volume(elem, i, value);

			snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax);
			value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin));
			snd_mixer_selem_set_capture_volume(elem, i, value);
		}
	}
}
static void balance_volumes(void)
{
	struct control *control;
	long left, right;
	int err;

	control = get_focus_control(TYPE_PVOLUME | TYPE_CVOLUME);
	if (!control || !(control->flags & HAS_VOLUME_1))
		return;
	if (control->flags & TYPE_PVOLUME) {
		err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[0], &left);
		if (err < 0)
			return;
		err = snd_mixer_selem_get_playback_volume(control->elem, control->volume_channels[1], &right);
		if (err < 0)
			return;
	} else {
		err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[0], &left);
		if (err < 0)
			return;
		err = snd_mixer_selem_get_capture_volume(control->elem, control->volume_channels[1], &right);
		if (err < 0)
			return;
	}
	left = (left + right) / 2;
	if (control->flags & TYPE_PVOLUME) {
		snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[0], left);
		snd_mixer_selem_set_playback_volume(control->elem, control->volume_channels[1], left);
	} else {
		snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[0], left);
		snd_mixer_selem_set_capture_volume(control->elem, control->volume_channels[1], left);
	}
	display_controls();
}
Ejemplo n.º 5
0
static int alsa_mixer_set_muted(snd_mixer_elem_t *elem, gboolean muted) {
  long val, min, max;

  /**if switch is available, get switch status directly*/
  if(snd_mixer_selem_has_playback_switch(elem)) {
    snd_mixer_selem_set_playback_switch(elem, 0, !muted);
    snd_mixer_selem_set_playback_switch(elem, 1, !muted);
    return 0;
  } else if(snd_mixer_selem_has_capture_switch(elem)) {
    snd_mixer_selem_set_capture_switch(elem, 0, !muted);
    snd_mixer_selem_set_capture_switch(elem, 1, !muted);
    return 0;
  }

  if(snd_mixer_selem_has_playback_volume(elem)) {
    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    val = muted ? min : max;
    snd_mixer_selem_set_playback_volume(elem, 0, val);
    snd_mixer_selem_set_playback_volume(elem, 1, val);
    return 0;
  } else if(snd_mixer_selem_has_capture_volume(elem)) {
    snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
    val = muted ? min : max;
    snd_mixer_selem_set_capture_volume(elem, 0, val);
    snd_mixer_selem_set_capture_volume(elem, 1, val);
    return 0;
  }

  return -1;
}
Ejemplo n.º 6
0
/* alsa_set_mixer_volume:
 *  Set mixer volume (0-255)
 */
static int alsa_set_mixer_volume(int volume)
{
   if (alsa_mixer && alsa_mixer_elem) {
      snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 0, volume * alsa_mixer_allegro_ratio);
      snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 1, volume * alsa_mixer_allegro_ratio);
   }
   return 0;
}
Ejemplo n.º 7
0
void VolumeALSA::setVolume(const VolumeSettings &vol)
{
    if (!pcm_element)
        return;

    snd_mixer_selem_set_playback_volume(pcm_element, SND_MIXER_SCHN_FRONT_LEFT, vol.left);
    snd_mixer_selem_set_playback_volume(pcm_element, SND_MIXER_SCHN_FRONT_RIGHT, vol.right);
}
Ejemplo n.º 8
0
static void volume_set(long volume) {
	if(volume<0)
		volume=0;
	if(volume>100L)
		volume=100L;
	
	volume=(volume*((long) (alsa.maxv-alsa.minv)))/100L+alsa.minv;
	snd_mixer_selem_set_playback_volume(alsa.elem, 0, volume);
	snd_mixer_selem_set_playback_volume(alsa.elem, 1, volume);
}
Ejemplo n.º 9
0
static void
alsa_volume( int lvol, int rvol )
{
	if( alsa.pcm_elem ) {
		snd_mixer_selem_set_playback_volume(alsa.pcm_elem,
						    SND_MIXER_SCHN_FRONT_LEFT, lvol);
		snd_mixer_selem_set_playback_volume(alsa.pcm_elem,
						    SND_MIXER_SCHN_FRONT_RIGHT, rvol);
	}
}
Ejemplo n.º 10
0
static void
brightside_volume_alsa_set_volume (BrightsideVolume *vol, int val)
{
	BrightsideVolumeAlsa *self = (BrightsideVolumeAlsa *) vol;

	val = (long) brightside_volume_alsa_vol_check (self,
			val * self->_priv->pmax / 100);
	snd_mixer_selem_set_playback_volume(self->_priv->elem,
			SND_MIXER_SCHN_FRONT_LEFT, val);
	snd_mixer_selem_set_playback_volume(self->_priv->elem,
			SND_MIXER_SCHN_FRONT_RIGHT, val);
}
Ejemplo n.º 11
0
void lamixer_volboxr_changed(GtkObject *adjustment, VolBox *volumebox)
{
	long rangevalue_left,rangevalue_right,increment;

	rangevalue_right = gtk_range_get_value(GTK_RANGE(adjustment));

	if (volumebox->type == 1) {
		snd_mixer_selem_set_playback_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_RIGHT, rangevalue_right);
	}
	else if (volumebox->type == 2) {
		snd_mixer_selem_set_capture_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_RIGHT, rangevalue_right);
	}

	if ((volumebox->lockswitch != NULL) && (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(volumebox->lockswitch)))) {

		if (volumebox->type == 1) {
			snd_mixer_selem_get_playback_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left);
		}
		else if (volumebox->type == 2) {
			snd_mixer_selem_get_capture_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left);
		}

		//TODO: Percent increment will be better?
		increment = rangevalue_right-volumebox->rcurval;

		if ( ((rangevalue_left<volumebox->maxrange) && (rangevalue_left>volumebox->minrange)) || \
		    ((rangevalue_left==volumebox->maxrange) && (increment<0)) || ((rangevalue_left==volumebox->minrange) && (increment>0)) ) {

				if (((rangevalue_left+increment)<=(long)volumebox->maxrange) && ((rangevalue_left+increment)>=(long)volumebox->minrange)) {
					rangevalue_left = rangevalue_left+increment;
				}
				else {
					if ((rangevalue_left+increment) < ((long)volumebox->minrange)) {
						rangevalue_left = volumebox->minrange;
					}
					else {
						rangevalue_left = volumebox->maxrange;
					}
				}
				g_signal_handler_block(G_OBJECT(volumebox->volbar), volumebox->hsignalid);
				gtk_range_set_value(GTK_RANGE(volumebox->volbar), rangevalue_left);
				if (volumebox->type == 1) {
					snd_mixer_selem_set_playback_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_LEFT, rangevalue_left);
				}
				else if (volumebox->type == 2) {
					snd_mixer_selem_set_capture_volume (volumebox->volelem, SND_MIXER_SCHN_FRONT_LEFT, rangevalue_left);
				}
				volumebox->curval = rangevalue_left;
				g_signal_handler_unblock(G_OBJECT(volumebox->volbar), volumebox->hsignalid);
			}
	}
	volumebox->rcurval = rangevalue_right;
}
Ejemplo n.º 12
0
void AlsaMixer::set_volume(int percentage)
{
    percentage = (percentage < 0) ? 0 : (percentage > 100 ? 100 : percentage);
    if (percentage == 0)
        volume = min;
    else if (percentage == 100)
        volume = max;
    else
        volume = min + ((this->max - this->min) * (long)percentage)/100;
    snd_mixer_selem_set_playback_volume(this->active_elem, LEFT, volume);
    snd_mixer_selem_set_playback_volume(this->active_elem, RIGHT, volume);
}
Ejemplo n.º 13
0
Archivo: mixer.c Proyecto: pzanoni/tray
static void _set_volume(snd_mixer_elem_t *elem, int playback, int n, long val)
{
	if (playback)
		snd_mixer_selem_set_playback_volume(elem, n, val);
	else
		snd_mixer_selem_set_capture_volume(elem, n, val);
}
Ejemplo n.º 14
0
static void on_playback_mixer_changed (GtkAdjustment *adj, gpointer data) {
  alsa_mixer_t *mixer = (alsa_mixer_t *)data;
  long min, max, val;
  gdouble newval = gtk_adjustment_get_value(adj);

  if(g_mixer_ui_updated == FALSE && mixer->pcm) {
    DEBUG("playback mixer value changed\n");
    snd_mixer_selem_get_playback_volume_range(mixer->pcm, &min, &max);
    val = ((newval/100) * (max-min) + 0.5);
    snd_mixer_selem_set_playback_volume(mixer->pcm, 0, val);
    snd_mixer_selem_set_playback_volume(mixer->pcm, 1, val);
  }

  DEBUG("mixer->pcm_muted = %d\n", mixer->pcm_muted);
  if(g_mixer_ui_updated) g_mixer_ui_updated = !g_mixer_ui_updated;
}
Ejemplo n.º 15
0
void
gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, GstMixerTrack * track,
    gint * volumes)
{
  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);
  gint i;

  g_return_if_fail (mixer->handle != NULL);

  g_static_rec_mutex_lock (mixer->rec_mutex);

  gst_alsa_mixer_track_update (alsa_track);

  if (track->flags & GST_MIXER_TRACK_OUTPUT) {

    /* Is emulated mute flag activated? */
    if (track->flags & GST_MIXER_TRACK_MUTE &&
        !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) {
      for (i = 0; i < track->num_channels; i++)
        alsa_track->volumes[i] = volumes[i];
    } else {
      if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
        snd_mixer_selem_set_playback_volume_all (alsa_track->element,
            volumes[0]);
        for (i = 0; i < track->num_channels; i++)
          alsa_track->volumes[i] = volumes[0];
      } else {
        for (i = 0; i < track->num_channels; i++) {
          alsa_track->volumes[i] = volumes[i];
          snd_mixer_selem_set_playback_volume (alsa_track->element, i,
              volumes[i]);
        }
      }
    }

  } else if (track->flags & GST_MIXER_TRACK_INPUT) {

    /* Is emulated record flag activated? */
    if (track->flags & GST_MIXER_TRACK_RECORD ||
        alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) {
      if (check_if_volumes_are_the_same (track->num_channels, volumes)) {
        snd_mixer_selem_set_capture_volume_all (alsa_track->element,
            volumes[0]);
        for (i = 0; i < track->num_channels; i++)
          alsa_track->volumes[i] = volumes[0];
      } else {
        for (i = 0; i < track->num_channels; i++) {
          alsa_track->volumes[i] = volumes[i];
          snd_mixer_selem_set_capture_volume (alsa_track->element, i,
              volumes[i]);
        }
      }
    } else {
      for (i = 0; i < track->num_channels; i++)
        alsa_track->volumes[i] = volumes[i];
    }
  }
  g_static_rec_mutex_unlock (mixer->rec_mutex);
}
Ejemplo n.º 16
0
static int alsa_mixer_set_volume(int l, int r)
{
	if (mixer_elem == NULL) {
		return -1;
	}
	l += mixer_vol_min;
	r += mixer_vol_min;
	if (l > mixer_vol_max)
		d_print("error: left volume too high (%d > %ld)\n",
				l, mixer_vol_max);
	if (r > mixer_vol_max)
		d_print("error: right volume too high (%d > %ld)\n",
				r, mixer_vol_max);
	snd_mixer_selem_set_playback_volume(mixer_elem, SND_MIXER_SCHN_FRONT_LEFT, l);
	snd_mixer_selem_set_playback_volume(mixer_elem, SND_MIXER_SCHN_FRONT_RIGHT, r);
	return 0;
}
Ejemplo n.º 17
0
/**
 * Sets the volume of the audio device.
 *
 * @param   count   [in]    volume in percent
 *
 * @note If count is less than 0 or more than 100
 * it will be set correctly to 0 or 100.
 */
void MMSAudioCtrl::setVolume(int count) {
    /* calculate the new value */
    this->xval = -1;
    this->volume = count;
    if (this->volume < 0) this->volume = 0;
    if (this->volume > 100) this->volume = 100;
    if (this->volume == 0)
        this->xval = this->pmin;
    else
    if (this->volume == 100)
        this->xval = this->pmax;
    else
        this->xval = this->pmin + ((this->pmax - this->pmin) * (long)this->volume) / 100;

    /* set the new value */
    snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, this->xval);
    snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, this->xval);

    /* set mute to off */
    this->muteFlag = false;
}
Ejemplo n.º 18
0
bool AlsaMixer::SetVolumePercent( const char* channel, int value )
{
	LOG( Logger::LOG_DEBUG, "AlsaMixer::SetVolume( %s, %d )", channel, value);
	bool success = false;
	snd_mixer_elem_t *elem;
	snd_mixer_selem_id_t *sid;
	snd_mixer_selem_id_alloca(&sid);

	snd_mixer_selem_id_set_index( sid, 0);
	snd_mixer_selem_id_set_name( sid, channel);
	elem = snd_mixer_find_selem(_handle, sid);
	if (!elem) {
		LOG( Logger::LOG_ERROR, "Unable to find simple control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
		goto end;
	}
	if( snd_mixer_selem_has_playback_volume(elem) )
	{
		long min, max;
		if( snd_mixer_selem_get_playback_volume_range(elem, &min, &max) < 0 )
		{
			LOG( Logger::LOG_ERROR, "Unable to get playback volume range for control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
			goto end;
		}
		int volume = ((max - min) * value) / 100 + min;
		for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
			if (snd_mixer_selem_set_playback_volume(elem, (snd_mixer_selem_channel_id_t)chn, volume ) >= 0)
			{
				success = true;
			}
		}
	}else if( snd_mixer_selem_has_capture_volume(elem) )
	{
		long min, max;
		if( snd_mixer_selem_get_capture_volume_range(elem, &min, &max) < 0 )
		{
			LOG( Logger::LOG_ERROR, "Unable to get capture volume range for control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
			goto end;
		}
		int volume = ((max - min) * value) / 100 + min;
		for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
			if (snd_mixer_selem_set_capture_volume(elem, (snd_mixer_selem_channel_id_t)chn, volume ) >= 0)
			{
				success = true;
			}
		}
	}
	if( !success )
	{
		LOG( Logger::LOG_ERROR, "Error setting control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
	}
 end:
	return success;
}
Ejemplo n.º 19
0
void
gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track,
    gboolean mute)
{
  GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track);

  g_return_if_fail (mixer->handle != NULL);

  g_static_rec_mutex_lock (mixer->rec_mutex);

  gst_alsa_mixer_track_update (alsa_track);

  if (!!(mute) == !!(track->flags & GST_MIXER_TRACK_MUTE)) {
    g_static_rec_mutex_unlock (mixer->rec_mutex);
    return;
  }
  if (mute) {
    track->flags |= GST_MIXER_TRACK_MUTE;

    if (alsa_track->shared_mute)
      ((GstMixerTrack *) (alsa_track->shared_mute))->flags |=
          GST_MIXER_TRACK_MUTE;
  } else {
    track->flags &= ~GST_MIXER_TRACK_MUTE;

    if (alsa_track->shared_mute)
      ((GstMixerTrack *) (alsa_track->shared_mute))->flags &=
          ~GST_MIXER_TRACK_MUTE;
  }

  if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH) {
    snd_mixer_selem_set_playback_switch_all (alsa_track->element, mute ? 0 : 1);
  } else {
    gint i;
    GstAlsaMixerTrack *ctrl_track;

    if ((track->flags & GST_MIXER_TRACK_INPUT)
        && alsa_track->shared_mute != NULL)
      ctrl_track = alsa_track->shared_mute;
    else
      ctrl_track = alsa_track;

    for (i = 0; i < ((GstMixerTrack *) ctrl_track)->num_channels; i++) {
      long vol =
          mute ? ((GstMixerTrack *) ctrl_track)->
          min_volume : ctrl_track->volumes[i];
      snd_mixer_selem_set_playback_volume (ctrl_track->element, i, vol);
    }
  }
  g_static_rec_mutex_unlock (mixer->rec_mutex);
}
Ejemplo n.º 20
0
/**
 * Mutes/unmutes the sound.
 */
void MMSAudioCtrl::mute() {
    if (isMute()) {
        /* switch to on */
        if(isSwitchable) {
            snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, 1);
            snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, 1);
        } else {
            setVolume(this->volume);
        }
    } else {
        /* set mute */
        if(isSwitchable) {
            snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, 0);
            snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, 0);
        } else {
            snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, 0);
            snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, 0);

            /* set mute to on */
            this->muteFlag = true;
        }
    }
}
Ejemplo n.º 21
0
void KplAudioSetMasterVolume(long left, long right)
{
	long min, max;
	snd_mixer_t *handle;
	snd_mixer_selem_id_t *sid;
	const char *card = "default";
	const char *selem_name = "Master";

	snd_mixer_open(&handle, 0);
	snd_mixer_attach(handle, card);
	snd_mixer_selem_register(handle, NULL, NULL);
	snd_mixer_load(handle);

	snd_mixer_selem_id_alloca(&sid);
	snd_mixer_selem_id_set_index(sid, 0);
	snd_mixer_selem_id_set_name(sid, selem_name);
	snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid);

	snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
	snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, min + (left * (max - min)) / 256);
	snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, min + (right * (max - min)) / 256);

	snd_mixer_close(handle);
}
void setRealVolume(PortControl* portControl,
                   snd_mixer_selem_channel_id_t channel, float value) {
    long lValue = 0;
    long min = 0;
    long max = 0;

    if (isPlaybackFunction(portControl->portType)) {
        snd_mixer_selem_get_playback_volume_range(portControl->elem,
                                                  &min, &max);
        lValue = scaleVolumeValueToHardware(value, min, max);
        snd_mixer_selem_set_playback_volume(portControl->elem,
                                            channel, lValue);
    } else {
        snd_mixer_selem_get_capture_volume_range(portControl->elem,
                                                 &min, &max);
        lValue = scaleVolumeValueToHardware(value, min, max);
        snd_mixer_selem_set_capture_volume(portControl->elem,
                                           channel, lValue);
    }
}
Ejemplo n.º 23
0
/*
 * Class:     org_tritonus_lowlevel_alsa_AlsaMixerElement
 * Method:    setPlaybackVolume
 * Signature: (II)V
 */
JNIEXPORT void JNICALL
Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_setPlaybackVolume
(JNIEnv* env, jobject obj, jint nChannelType, jint nValue)
{
    snd_mixer_elem_t*	handle;
    int			nReturn;

    if (debug_flag) {
        (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_setPlaybackVolume(): begin\n");
    }
    handle = getHandle(env, obj);
    nReturn = snd_mixer_selem_set_playback_volume(handle, (snd_mixer_selem_channel_id_t) nChannelType, nValue);
    if (nReturn < 0)
    {
        throwRuntimeException(env, snd_strerror(nReturn));
    }
    if (debug_flag) {
        (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_setPlaybackVolume(): end\n");
    }
}
Ejemplo n.º 24
0
static void set_volume_indexed(PxDev *dev, int i, PxVolume volume, int playback)
{
   snd_mixer_elem_t *elem;
   long vol, min, max;
   int j;

   if (!dev->handle) {
      return;
   }

   if (i < 0 || i > dev->numselems) {
      return;
   }

   elem = dev->selems[i].elem;
   if (playback) {
      snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
      for (j = 0; j < SND_MIXER_SCHN_LAST; j++) {
         if (snd_mixer_selem_has_playback_channel(elem, j)) {
            vol = (long) (volume * (max - min) + 0.5);
            snd_mixer_selem_set_playback_volume(elem, j, vol);
         }
      }
   }
   else {
      snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
      for (j = 0; j < SND_MIXER_SCHN_LAST; j++) {
         if (snd_mixer_selem_has_capture_channel(elem, j)) {
            vol = (long) (volume * (max - min) + 0.5);
            snd_mixer_selem_set_capture_volume(elem, j, vol);
         }
      }
   }

   return;
}
Ejemplo n.º 25
0
static void
alsa_configure (struct sound_device *sd)
{
  int val, err, dir;
  unsigned uval;
  struct alsa_params *p = (struct alsa_params *) sd->data;
  snd_pcm_uframes_t buffer_size;

  xassert (p->handle != 0);

  err = snd_pcm_hw_params_malloc (&p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate hardware parameter structure", err);

  err = snd_pcm_sw_params_malloc (&p->swparams);
  if (err < 0)
    alsa_sound_perror ("Could not allocate software parameter structure", err);

  err = snd_pcm_hw_params_any (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not initialize hardware parameter structure", err);

  err = snd_pcm_hw_params_set_access (p->handle, p->hwparams,
                                      SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0)
    alsa_sound_perror ("Could not set access type", err);

  val = sd->format;
  err = snd_pcm_hw_params_set_format (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set sound format", err);

  uval = sd->sample_rate;
  err = snd_pcm_hw_params_set_rate_near (p->handle, p->hwparams, &uval, 0);
  if (err < 0)
    alsa_sound_perror ("Could not set sample rate", err);

  val = sd->channels;
  err = snd_pcm_hw_params_set_channels (p->handle, p->hwparams, val);
  if (err < 0)
    alsa_sound_perror ("Could not set channel count", err);

  err = snd_pcm_hw_params (p->handle, p->hwparams);
  if (err < 0)
    alsa_sound_perror ("Could not set parameters", err);


  err = snd_pcm_hw_params_get_period_size (p->hwparams, &p->period_size, &dir);
  if (err < 0)
    alsa_sound_perror ("Unable to get period size for playback", err);

  err = snd_pcm_hw_params_get_buffer_size (p->hwparams, &buffer_size);
  if (err < 0)
    alsa_sound_perror("Unable to get buffer size for playback", err);

  err = snd_pcm_sw_params_current (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to determine current swparams for playback",
                       err);

  /* Start the transfer when the buffer is almost full */
  err = snd_pcm_sw_params_set_start_threshold (p->handle, p->swparams,
                                               (buffer_size / p->period_size)
                                               * p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set start threshold mode for playback", err);

  /* Allow the transfer when at least period_size samples can be processed */
  err = snd_pcm_sw_params_set_avail_min (p->handle, p->swparams, p->period_size);
  if (err < 0)
    alsa_sound_perror ("Unable to set avail min for playback", err);

  err = snd_pcm_sw_params (p->handle, p->swparams);
  if (err < 0)
    alsa_sound_perror ("Unable to set sw params for playback\n", err);

  snd_pcm_hw_params_free (p->hwparams);
  p->hwparams = NULL;
  snd_pcm_sw_params_free (p->swparams);
  p->swparams = NULL;

  err = snd_pcm_prepare (p->handle);
  if (err < 0)
    alsa_sound_perror ("Could not prepare audio interface for use", err);

  if (sd->volume > 0)
    {
      int chn;
      snd_mixer_t *handle;
      snd_mixer_elem_t *e;
      const char *file = sd->file ? sd->file : DEFAULT_ALSA_SOUND_DEVICE;

      if (snd_mixer_open (&handle, 0) >= 0)
        {
          if (snd_mixer_attach (handle, file) >= 0
              && snd_mixer_load (handle) >= 0
              && snd_mixer_selem_register (handle, NULL, NULL) >= 0)
            for (e = snd_mixer_first_elem (handle);
                 e;
                 e = snd_mixer_elem_next (e))
              {
                if (snd_mixer_selem_has_playback_volume (e))
                  {
                    long pmin, pmax, vol;
                    snd_mixer_selem_get_playback_volume_range (e, &pmin, &pmax);
                    vol = pmin + (sd->volume * (pmax - pmin)) / 100;

                    for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++)
                      snd_mixer_selem_set_playback_volume (e, chn, vol);
                  }
              }
          snd_mixer_close(handle);
        }
    }
}
Ejemplo n.º 26
0
/* to set/get/query special features/parameters */
static int control(int cmd, void *arg)
{
  switch(cmd) {
  case AOCONTROL_QUERY_FORMAT:
    return CONTROL_TRUE;
  case AOCONTROL_GET_VOLUME:
  case AOCONTROL_SET_VOLUME:
    {
      ao_control_vol_t *vol = (ao_control_vol_t *)arg;

      int err;
      snd_mixer_t *handle;
      snd_mixer_elem_t *elem;
      snd_mixer_selem_id_t *sid;

      char *mix_name = "PCM";
      char *card = "default";
      int mix_index = 0;

      long pmin, pmax;
      long get_vol, set_vol;
      float f_multi;

      if(AF_FORMAT_IS_IEC61937(ao_data.format))
	return CONTROL_TRUE;

      if(mixer_channel) {
	 char *test_mix_index;

	 mix_name = strdup(mixer_channel);
	 if ((test_mix_index = strchr(mix_name, ','))){
		*test_mix_index = 0;
		test_mix_index++;
		mix_index = strtol(test_mix_index, &test_mix_index, 0);

		if (*test_mix_index){
		  mp_msg(MSGT_AO,MSGL_ERR,
		    MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero);
		  mix_index = 0 ;
		}
	 }
      }
      if(mixer_device) card = mixer_device;

      //allocate simple id
      snd_mixer_selem_id_alloca(&sid);

      //sets simple-mixer index and name
      snd_mixer_selem_id_set_index(sid, mix_index);
      snd_mixer_selem_id_set_name(sid, mix_name);

      if (mixer_channel) {
	free(mix_name);
	mix_name = NULL;
      }

      if ((err = snd_mixer_open(&handle, 0)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerOpenError, snd_strerror(err));
	return CONTROL_ERROR;
      }

      if ((err = snd_mixer_attach(handle, card)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerAttachError,
	       card, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }

      if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerRegisterError, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }
      err = snd_mixer_load(handle);
      if (err < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerLoadError, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }

      elem = snd_mixer_find_selem(handle, sid);
      if (!elem) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl,
	       snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
	}

      snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax);
      f_multi = (100 / (float)(pmax - pmin));

      if (cmd == AOCONTROL_SET_VOLUME) {

	set_vol = vol->left / f_multi + pmin + 0.5;

	//setting channels
	if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol)) < 0) {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingLeftChannel,
		 snd_strerror(err));
	  snd_mixer_close(handle);
	  return CONTROL_ERROR;
	}
	mp_msg(MSGT_AO,MSGL_DBG2,"left=%li, ", set_vol);

	set_vol = vol->right / f_multi + pmin + 0.5;

	if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol)) < 0) {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingRightChannel,
		 snd_strerror(err));
	  snd_mixer_close(handle);
	  return CONTROL_ERROR;
	}
	mp_msg(MSGT_AO,MSGL_DBG2,"right=%li, pmin=%li, pmax=%li, mult=%f\n",
	       set_vol, pmin, pmax, f_multi);

	if (snd_mixer_selem_has_playback_switch(elem)) {
	  int lmute = (vol->left == 0.0);
	  int rmute = (vol->right == 0.0);
	  if (snd_mixer_selem_has_playback_switch_joined(elem)) {
	    lmute = rmute = lmute && rmute;
	  } else {
	    snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !rmute);
	  }
	  snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !lmute);
	}
      }
      else {
	snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol);
	vol->left = (get_vol - pmin) * f_multi;
	snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol);
	vol->right = (get_vol - pmin) * f_multi;

	mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right);
      }
      snd_mixer_close(handle);
      return CONTROL_OK;
    }

  } //end switch
  return CONTROL_UNKNOWN;
}
Ejemplo n.º 27
0
/*
  Drawbacks. Sets volume on both channels but gets volume on one. Can be easily adapted.
 */
int audio_volume(audio_volume_action action, long* outvol) {
	int ret = 0;
	snd_mixer_t* handle;
	snd_mixer_elem_t* elem;
	snd_mixer_selem_id_t* sid;

	static const char* mix_name = "Master";
	static const char* card = "default";
	static int mix_index = 0;

	long pmin, pmax;
	long get_vol, set_vol;
	float f_multi;

	snd_mixer_selem_id_alloca(&sid);

	//sets simple-mixer index and name
	snd_mixer_selem_id_set_index(sid, mix_index);
	snd_mixer_selem_id_set_name(sid, mix_name);

	if ((snd_mixer_open(&handle, 0)) < 0)
		return -1;
	if ((snd_mixer_attach(handle, card)) < 0) {
		snd_mixer_close(handle);
		return -2;
	}
	if ((snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
		snd_mixer_close(handle);
		return -3;
	}
	ret = snd_mixer_load(handle);
	if (ret < 0) {
		snd_mixer_close(handle);
		return -4;
	}
	elem = snd_mixer_find_selem(handle, sid);
	if (!elem) {
		snd_mixer_close(handle);
		return -5;
	}

	long minv, maxv;

	snd_mixer_selem_get_playback_volume_range (elem, &minv, &maxv);
	fprintf(stderr, "Volume range <%li,%li>\n", minv, maxv);

	if(action == AUDIO_VOLUME_GET) {
		if(snd_mixer_selem_get_playback_volume(elem, 0, outvol) < 0) {
			snd_mixer_close(handle);
			return -6;
		}

		fprintf(stderr, "Get volume %li with status %i\n", *outvol, ret);
		/* make the value bound to 100 */
		*outvol -= minv;
		maxv -= minv;
		minv = 0;
		*outvol = 100 * (*outvol) / maxv; // make the value bound from 0 to 100
	}
	else if(action == AUDIO_VOLUME_SET) {
		if(*outvol < 0 || *outvol > VOLUME_BOUND) // out of bounds
			return -7;
		*outvol = (*outvol * (maxv - minv) / (100-1)) + minv;

		if(snd_mixer_selem_set_playback_volume(elem, 0, *outvol) < 0) {
			snd_mixer_close(handle);
			return -8;
		}
		if(snd_mixer_selem_set_playback_volume(elem, 1, *outvol) < 0) {
			snd_mixer_close(handle);
			return -9;
		}
		fprintf(stderr, "Set volume %li with status %i\n", *outvol, ret);
	}

	snd_mixer_close(handle);
	return 0;
	}
Ejemplo n.º 28
0
/*
 * Set/get current PCM mixer gain.
 * Return value: 0 success, 1 failure
 * Returns the current mixer setting in ret_value
 * Sets the mixer to new_value is set, does nothing when NULL
 */
static int alsa_gain(struct audio_info_struct *ai, long *ret_value, long *new_value, char *error)
{
    int              sts;
    snd_mixer_elem_t *mixerelem;
    long             value;
    long             left;
    long             right;

    mixerelem = ai->vh;
    if (!mixerelem) {
        if (error) {
            sprintf(error, "Mixer Device is not initialized\n");
        }
        return 1;
    }

    if (ret_value) {
        sts = snd_mixer_selem_get_playback_volume(mixerelem,
                SND_MIXER_SCHN_FRONT_LEFT, &value);
        if (sts) {
            if (error) {
                sprintf(error, "snd_mixer_selem_get_playback_volume(LEFT): "
                        "failed; %d\n", sts);
            }
            return 1;
        }
        left = value;

        sts = snd_mixer_selem_get_playback_volume(mixerelem,
                SND_MIXER_SCHN_FRONT_LEFT, &value);
        if (sts) {
            if (error) {
                sprintf(error, "snd_mixer_selem_get_playback_volume(RIGHT): "
                        "failed; %d\n", sts);
            }
            return 1;
        }
        right = value;

        *ret_value = (left + right) / 2;
    }

    if (new_value) {
        sts = snd_mixer_selem_set_playback_volume(mixerelem,
                SND_MIXER_SCHN_FRONT_LEFT, *new_value);
        if (sts) {
            if (error) {
                sprintf(error, "snd_mixer_selem_set_playback_volume(LEFT): "
                        "failed; %d\n", sts);
            }
            return 1;
        }
        sts = snd_mixer_selem_set_playback_volume(mixerelem,
                SND_MIXER_SCHN_FRONT_RIGHT, *new_value);
        if (sts) {
            if (error) {
                sprintf(error, "snd_mixer_selem_set_playback_volume(RIGHT): "
                        "failed; %d\n", sts);
            }
            return 1;
        }
    }

    return 0;
}
Ejemplo n.º 29
0
void VolumeControl::setVolume(int volume)
{
	//clamp to 0-100 range
	if (volume < 0)
	{
		volume = 0;
	}
	if (volume > 100)
	{
		volume = 100;
	}
	//store values in internal variables
	internalVolume = volume;
#if defined (__APPLE__)
    #warning TODO: Not implemented for MacOS yet!!!
#elif defined(__linux__)
	if (mixerElem != nullptr)
	{
		//get volume range
		long minVolume;
		long maxVolume;
		if (snd_mixer_selem_get_playback_volume_range(mixerElem, &minVolume, &maxVolume) == 0)
		{
			//ok. bring into minVolume-maxVolume range and set
			long rawVolume = (volume * (maxVolume - minVolume) / 100) + minVolume;
			if (snd_mixer_selem_set_playback_volume(mixerElem, SND_MIXER_SCHN_FRONT_LEFT, rawVolume) < 0
				|| snd_mixer_selem_set_playback_volume(mixerElem, SND_MIXER_SCHN_FRONT_RIGHT, rawVolume) < 0)
			{
				LOG(LogError) << "VolumeControl::getVolume() - Failed to set mixer volume!";
			}
		}
		else
		{
			LOG(LogError) << "VolumeControl::getVolume() - Failed to get volume range!";
		}
	}
#elif defined(WIN32) || defined(_WIN32)
	if (mixerHandle != nullptr)
	{
		//Windows older than Vista. use mixer API. get volume from line control
		MIXERCONTROLDETAILS_UNSIGNED value;
		value.dwValue = (volume * 65535) / 100;
		MIXERCONTROLDETAILS mixerControlDetails;
		mixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
		mixerControlDetails.dwControlID = mixerControl.dwControlID;
		mixerControlDetails.cChannels = 1; //always 1 for a MIXERCONTROL_CONTROLF_UNIFORM control
		mixerControlDetails.cMultipleItems = 0; //always 0 except for a MIXERCONTROL_CONTROLF_MULTIPLE control
		mixerControlDetails.paDetails = &value;
		mixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
		if (mixerSetControlDetails((HMIXEROBJ)mixerHandle, &mixerControlDetails, MIXER_SETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR)
		{
			LOG(LogError) << "VolumeControl::setVolume() - Failed to set mixer volume!";
		}
	}
	else if (endpointVolume != nullptr)
	{
		//Windows Vista or above. use EndpointVolume API
		float floatVolume = 0.0f; //0-1
		if (volume > 0) {
			floatVolume = (float)volume / 100.0f;
		}
		if (endpointVolume->SetMasterVolumeLevelScalar(floatVolume, nullptr) != S_OK)
		{
			LOG(LogError) << "VolumeControl::setVolume() - Failed to set master volume!";
		}
	}
#endif
}
Ejemplo n.º 30
0
static int control(struct ao *ao, enum aocontrol cmd, void *arg)
{
    struct priv *p = ao->priv;
    snd_mixer_t *handle = NULL;
    switch (cmd) {
    case AOCONTROL_GET_MUTE:
    case AOCONTROL_SET_MUTE:
    case AOCONTROL_GET_VOLUME:
    case AOCONTROL_SET_VOLUME:
    {
        int err;
        snd_mixer_elem_t *elem;
        snd_mixer_selem_id_t *sid;

        long pmin, pmax;
        long get_vol, set_vol;
        float f_multi;

        if (!af_fmt_is_pcm(ao->format))
            return CONTROL_FALSE;

        snd_mixer_selem_id_alloca(&sid);

        snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index);
        snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name);

        err = snd_mixer_open(&handle, 0);
        CHECK_ALSA_ERROR("Mixer open error");

        err = snd_mixer_attach(handle, p->cfg_mixer_device);
        CHECK_ALSA_ERROR("Mixer attach error");

        err = snd_mixer_selem_register(handle, NULL, NULL);
        CHECK_ALSA_ERROR("Mixer register error");

        err = snd_mixer_load(handle);
        CHECK_ALSA_ERROR("Mixer load error");

        elem = snd_mixer_find_selem(handle, sid);
        if (!elem) {
            MP_VERBOSE(ao, "Unable to find simple control '%s',%i.\n",
                       snd_mixer_selem_id_get_name(sid),
                       snd_mixer_selem_id_get_index(sid));
            goto alsa_error;
        }

        snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax);
        f_multi = (100 / (float)(pmax - pmin));

        switch (cmd) {
        case AOCONTROL_SET_VOLUME: {
            ao_control_vol_t *vol = arg;
            set_vol = vol->left / f_multi + pmin + 0.5;

            err = snd_mixer_selem_set_playback_volume
                    (elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol);
            CHECK_ALSA_ERROR("Error setting left channel");
            MP_DBG(ao, "left=%li, ", set_vol);

            set_vol = vol->right / f_multi + pmin + 0.5;

            err = snd_mixer_selem_set_playback_volume
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol);
            CHECK_ALSA_ERROR("Error setting right channel");
            MP_DBG(ao, "right=%li, pmin=%li, pmax=%li, mult=%f\n",
                   set_vol, pmin, pmax, f_multi);
            break;
        }
        case AOCONTROL_GET_VOLUME: {
            ao_control_vol_t *vol = arg;
            snd_mixer_selem_get_playback_volume
                (elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol);
            vol->left = (get_vol - pmin) * f_multi;
            snd_mixer_selem_get_playback_volume
                (elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol);
            vol->right = (get_vol - pmin) * f_multi;
            MP_DBG(ao, "left=%f, right=%f\n", vol->left, vol->right);
            break;
        }
        case AOCONTROL_SET_MUTE: {
            bool *mute = arg;
            if (!snd_mixer_selem_has_playback_switch(elem))
                goto alsa_error;
            if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
                snd_mixer_selem_set_playback_switch
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, !*mute);
            }
            snd_mixer_selem_set_playback_switch
                (elem, SND_MIXER_SCHN_FRONT_LEFT, !*mute);
            break;
        }
        case AOCONTROL_GET_MUTE: {
            bool *mute = arg;
            if (!snd_mixer_selem_has_playback_switch(elem))
                goto alsa_error;
            int tmp = 1;
            snd_mixer_selem_get_playback_switch
                (elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp);
            *mute = !tmp;
            if (!snd_mixer_selem_has_playback_switch_joined(elem)) {
                snd_mixer_selem_get_playback_switch
                    (elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp);
                *mute &= !tmp;
            }
            break;
        }
        }
        snd_mixer_close(handle);
        return CONTROL_OK;
    }

    } //end switch
    return CONTROL_UNKNOWN;

alsa_error:
    if (handle)
        snd_mixer_close(handle);
    return CONTROL_ERROR;
}