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); } }
static gint gam_slider_pan_get_volume (GamSliderPan *gam_slider_pan) { glong left_chn, right_chn, pmin, pmax; 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); if (snd_mixer_selem_has_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) snd_mixer_selem_get_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_LEFT, &left_chn); else snd_mixer_selem_get_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)))) { return rint (100 - (left_chn * (100 / (gfloat)pmax))); } else { if (snd_mixer_selem_has_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) snd_mixer_selem_get_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, &right_chn); else snd_mixer_selem_get_capture_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, &right_chn); return rint (100 - (MAX(left_chn, right_chn) * (100 / (gfloat)pmax))); } }
static GObject * gam_slider_pan_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params) { GObject *object; GamSliderPan *gam_slider_pan; GamSliderPanPrivate *priv; object = (* G_OBJECT_CLASS (parent_class)->constructor) (type, n_construct_properties, construct_params); gam_slider_pan = GAM_SLIDER_PAN (object); priv = GAM_SLIDER_PAN_GET_PRIVATE (gam_slider_pan); if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) { priv->pan_adjustment = gtk_adjustment_new (gam_slider_pan_get_pan (gam_slider_pan), -100, 101, 1, 5, 1); g_signal_connect (G_OBJECT (priv->pan_adjustment), "value-changed", G_CALLBACK (gam_slider_pan_pan_value_changed_cb), gam_slider_pan); priv->pan_slider = gtk_hscale_new (GTK_ADJUSTMENT (priv->pan_adjustment)); gtk_scale_set_draw_value (GTK_SCALE (priv->pan_slider), FALSE); g_signal_connect (G_OBJECT (priv->pan_slider), "event", G_CALLBACK (gam_slider_pan_pan_event_cb), gam_slider_pan); } else priv->pan_slider = gtk_label_new (NULL); gtk_widget_show (priv->pan_slider); gam_slider_add_pan_widget (GAM_SLIDER (gam_slider_pan), priv->pan_slider); priv->vol_adjustment = gtk_adjustment_new (gam_slider_pan_get_volume (gam_slider_pan), 0, 101, 1, 5, 1); g_signal_connect (G_OBJECT (priv->vol_adjustment), "value-changed", G_CALLBACK (gam_slider_pan_volume_value_changed_cb), gam_slider_pan); priv->vol_slider = gtk_vscale_new (GTK_ADJUSTMENT (priv->vol_adjustment)); gtk_widget_show (priv->vol_slider); gtk_scale_set_draw_value (GTK_SCALE (priv->vol_slider), FALSE); gam_slider_add_volume_widget (GAM_SLIDER (gam_slider_pan), priv->vol_slider); gtk_label_set_mnemonic_widget (gam_slider_get_label_widget (GAM_SLIDER (gam_slider_pan)), priv->vol_slider); return object; }
static void gam_slider_pan_refresh (GamSlider *gam_slider) { GamSliderPan * const gam_slider_pan = GAM_SLIDER_PAN (snd_mixer_elem_get_callback_private (gam_slider_get_elem (gam_slider))); GamSliderPanPrivate *priv; priv = GAM_SLIDER_PAN_GET_PRIVATE (gam_slider_pan); gtk_adjustment_set_value (GTK_ADJUSTMENT (priv->vol_adjustment), (gdouble) gam_slider_pan_get_volume (gam_slider_pan)); if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (gam_slider))) { gtk_adjustment_set_value (GTK_ADJUSTMENT (priv->pan_adjustment), (gdouble) gam_slider_pan_get_pan (gam_slider_pan)); } }
/* * Class: org_tritonus_lowlevel_alsa_AlsaMixerElement * Method: isPlaybackMono * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_isPlaybackMono (JNIEnv* env, jobject obj) { snd_mixer_elem_t* handle; int nReturn; if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_isPlaybackMono(): begin\n"); } handle = getHandle(env, obj); nReturn = snd_mixer_selem_is_playback_mono(handle); if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_isPlaybackMono(): end\n"); } return (jboolean) nReturn; }
long SIDInfo::getRealVolume() { if (!hasVolume || !_sid) return min; snd_mixer_elem_t* elem = snd_mixer_find_selem(_handle, _sid); if (!elem) return min; long vleft, vright; snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &vleft); vright = vleft; if (!snd_mixer_selem_is_playback_mono(elem)) snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &vright); return (vleft + vright)/2; }
static gint gam_slider_pan_get_pan (GamSliderPan *gam_slider_pan) { glong left_chn, right_chn; if (!snd_mixer_selem_is_playback_mono (gam_slider_get_elem (GAM_SLIDER (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 (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_LEFT, &left_chn); else snd_mixer_selem_get_capture_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_LEFT, &left_chn); if (snd_mixer_selem_has_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)))) snd_mixer_selem_get_playback_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, &right_chn); else snd_mixer_selem_get_capture_volume (gam_slider_get_elem (GAM_SLIDER (gam_slider_pan)), SND_MIXER_SCHN_FRONT_RIGHT, &right_chn); if ((gam_slider_pan_get_volume (gam_slider_pan) != 0) && (left_chn != right_chn)) return rint (((gfloat)(right_chn - left_chn) / (gfloat)MAX(left_chn, right_chn)) * 100); } return 0; }
MixerElem *lamixer_volelem_new(snd_mixer_elem_t *elem) { MixerElem *mixer_elem; guint voltype=0, elemidx=0, mono; long minrange=0,maxrange=0,rangevalue_left=0,rangevalue_right=0; const char* selem_name = NULL; char elem_name[64]; mixer_elem = g_malloc(sizeof(MixerElem)); mixer_elem->elem = elem; mixer_elem->playback = NULL; mixer_elem->capture = NULL; mixer_elem->pswitch = NULL; mixer_elem->cswitch = NULL; mixer_elem->penum = NULL; mixer_elem->cenum = NULL; elemidx = snd_mixer_selem_get_index(elem); selem_name = snd_mixer_selem_id_get_name(sid); strcpy(elem_name, selem_name); if(elemidx > 0) { sprintf(elem_name,"%s %i",elem_name, elemidx); } if (!snd_mixer_selem_is_enumerated(elem)) { if (snd_mixer_selem_has_playback_volume(elem)) { voltype = 1; snd_mixer_selem_get_playback_volume_range (elem, &minrange, &maxrange); mono = snd_mixer_selem_is_playback_mono(elem); snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left); if(!mono) snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &rangevalue_right); mixer_elem->playback = lamixer_volbox_new(elem_name,mono, \ (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_playback_switch_joined(elem)), minrange, maxrange, elem, voltype); } else if (snd_mixer_selem_has_playback_switch(elem)) { voltype = 1; mixer_elem->pswitch = lamixer_switchbox_add(elem_name, elem, voltype); } if (snd_mixer_selem_has_capture_volume(elem)) { voltype = 2; snd_mixer_selem_get_capture_volume_range (elem, &minrange, &maxrange); mono = snd_mixer_selem_is_capture_mono(elem); snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left); if(!mono) snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &rangevalue_right); mixer_elem->capture = lamixer_volbox_new(elem_name,mono, \ (snd_mixer_selem_has_capture_switch(elem) || snd_mixer_selem_has_capture_switch_joined(elem)), minrange, maxrange, elem, voltype); } else if (snd_mixer_selem_has_capture_switch(elem)) { voltype = 2; mixer_elem->cswitch = lamixer_switchbox_add(elem_name, elem, voltype); } } else { if (snd_mixer_selem_is_enum_playback(elem)) { voltype = 1; mixer_elem->penum = lamixer_enumbox_add(elem_name, elem, voltype); } else if (snd_mixer_selem_is_enum_capture(elem)) { voltype = 2; mixer_elem->cenum = lamixer_enumbox_add(elem_name, elem, voltype); } } return mixer_elem; }
static snd_mixer_elem_t * gst_alsa_mixer_find_master_mixer (GstAlsaMixer * mixer, snd_mixer_t * handle) { snd_mixer_elem_t *element; gint i, count; count = snd_mixer_get_count (handle); g_static_rec_mutex_lock (mixer->rec_mutex); /* Check if we have a playback mixer labelled as 'Master' */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && strcmp (snd_mixer_selem_get_name (element), "Master") == 0) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, check if we have a playback mixer labelled as 'Front' */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && strcmp (snd_mixer_selem_get_name (element), "Front") == 0) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, check if we have a playback mixer labelled as 'PCM' */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && strcmp (snd_mixer_selem_get_name (element), "PCM") == 0) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, check if we have a playback mixer labelled as 'Speaker' */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && strcmp (snd_mixer_selem_get_name (element), "Speaker") == 0) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, check if we have a playback mixer with both volume and switch that * is not mono */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && snd_mixer_selem_has_playback_switch (element) && !snd_mixer_selem_is_playback_mono (element)) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, check if we have any playback mixer with both volume and switch */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element) && snd_mixer_selem_has_playback_switch (element)) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } /* If not, take any playback mixer with a volume control */ element = snd_mixer_first_elem (handle); for (i = 0; i < count; i++) { if (snd_mixer_selem_has_playback_volume (element)) { g_static_rec_mutex_unlock (mixer->rec_mutex); return element; } element = snd_mixer_elem_next (element); } g_static_rec_mutex_unlock (mixer->rec_mutex); /* Looks like we're out of luck ... */ return NULL; }
void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { PortMixer* portMixer; snd_mixer_elem_t* elem; void* control; PortControl* portControl; void* controls[10]; int numControls; char* portName; int isPlayback = 0; int isMono; int isStereo; char* type; snd_mixer_selem_channel_id_t channel; TRACE0("> PORT_GetControls\n"); if (id == NULL) { ERROR0("Invalid handle!"); // $$mp: an error code should be returned. return; } portMixer = (PortMixer*) id; if (portIndex < 0 || portIndex >= portMixer->numElems) { ERROR0("Port index out of range!"); // $$mp: an error code should be returned. return; } numControls = 0; elem = portMixer->elems[portIndex]; if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) { /* Since we've split/duplicated elements with both playback and capture on the recovery of elements, we now can assume that we handle only to deal with either playback or capture. */ isPlayback = isPlaybackFunction(portMixer->types[portIndex]); isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) || (!isPlayback && snd_mixer_selem_is_capture_mono(elem)); isStereo = (isPlayback && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) || (!isPlayback && snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) && snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)); // single volume control if (isMono || isStereo) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_VOLUME; if (isMono) { portControl->channel = CHANNELS_MONO; } else { portControl->channel = CHANNELS_STEREO; } control = createVolumeControl(creator, portControl, elem, isPlayback); if (control != NULL) { controls[numControls++] = control; } } } else { // more than two channels, each channels has its own control. for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) { if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) || (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_VOLUME; portControl->channel = channel; control = createVolumeControl(creator, portControl, elem, isPlayback); // We wrap in a compound control to provide the channel name. if (control != NULL) { /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the declaration of PORT_NewCompoundControlPtr in Ports.h should be changed to take a const char* parameter. */ control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1); } if (control != NULL) { controls[numControls++] = control; } } } } } // BALANCE control if (isStereo) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_BALANCE; portControl->channel = CHANNELS_STEREO; /* $$mp: The value for precision is chosen more or less arbitrarily. */ control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, ""); if (control != NULL) { controls[numControls++] = control; } } } } if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) { if (getControlSlot(portMixer, &portControl)) { type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT; portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = type; control = (creator->newBooleanControl)(creator, portControl, type); if (control != NULL) { controls[numControls++] = control; } } } /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the declaration of PORT_NewCompoundControlPtr in Ports.h should be changed to take a const char* parameter. */ portName = (char*) snd_mixer_selem_get_name(elem); control = (creator->newCompoundControl)(creator, portName, controls, numControls); if (control != NULL) { (creator->addControl)(creator, control); } TRACE0("< PORT_GetControls\n"); }