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); } }
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); }
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(); }
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; }
/* 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; }
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); }
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); }
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); } }
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); }
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; }
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); }
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); }
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; }
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); }
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; }
/** * 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; }
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; }
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); }
/** * 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; } } }
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); } }
/* * 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"); } }
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; }
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); } } }
/* 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; }
/* 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; }
/* * 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; }
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 }
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; }