static void on_capture_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->mic) { DEBUG("microphone mixer value changed\n"); snd_mixer_selem_get_capture_volume_range(mixer->mic, &min, &max); val = ((newval/100) * (max-min)+0.5); snd_mixer_selem_set_capture_volume(mixer->mic, 0, val); snd_mixer_selem_set_capture_volume(mixer->mic, 1, val); } DEBUG("mixer->mic_muted = %d\n", mixer->mic_muted); if(g_mixer_ui_updated) g_mixer_ui_updated = !g_mixer_ui_updated; }
static void am_create_capture_mixer(GtkWidget *hbox, alsa_mixer_t *mixer) { GtkWidget *switch_btn = NULL, *vbox = NULL, *adv_btn = NULL, *img = NULL; GtkObject *adj = NULL; char *icon = NULL; gdouble dval = 0; long cmin, cmax, Rvol, Lvol; gboolean muted = TRUE, need_reset; char path[1024] = {0}; if(mixer->mic) muted = alsa_mixer_is_muted(mixer->mic, &need_reset); mixer->mic_muted = muted; g_snprintf(path, 1024, DVM_CONFIG_PATH"/%s", g_capture_iconset[muted ? 3: 0]); switch_btn = gtk_event_box_new(); img = gtk_image_new_from_file(path); gtk_container_add(GTK_CONTAINER(switch_btn), img); g_object_set_data(G_OBJECT(switch_btn), "iconset", g_capture_iconset); g_signal_connect(switch_btn, "enter-notify-event", G_CALLBACK(on_enter_switch_widget), mixer); g_signal_connect(switch_btn, "leave-notify-event", G_CALLBACK(on_leave_switch_widget), mixer); g_signal_connect(switch_btn, "button-press-event", G_CALLBACK(on_press_switch_widget), mixer); g_signal_connect(switch_btn, "button-release-event", G_CALLBACK(on_release_switch_widget), mixer); if(mixer->mic) { snd_mixer_selem_get_capture_volume_range(mixer->mic, &cmin, &cmax); snd_mixer_selem_get_capture_volume(mixer->mic, 0, &Rvol); snd_mixer_selem_get_capture_volume(mixer->mic, 1, &Lvol); dval = ((gdouble)(Rvol + Lvol)*50)/(cmax-cmin); adj = gtk_adjustment_new(dval, 0, 100, 1, 6, 0); snd_mixer_elem_set_callback_private(mixer->mic, adj); } else { adj = gtk_adjustment_new(0, 0, 100, 1, 6, 0); } g_object_set_data(G_OBJECT(adj), "image-obj", img); g_object_set_data(G_OBJECT(adj), "mixer-obj", mixer); DEBUG("capture set object data, img = %x, mixer = %x\n", img, mixer); //g_signal_connect(adj, "value-changed", G_CALLBACK(on_capture_mixer_changed), mixer); adv_btn = gtk_button_new_with_label("Advanced"); vbox = am_create_mixer_ui(switch_btn, "Microphone", GTK_ADJUSTMENT(adj), adv_btn); gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); }
/* * Class: org_tritonus_lowlevel_alsa_AlsaMixerElement * Method: getCaptureVolumeRange * Signature: ([I)V */ JNIEXPORT void JNICALL Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_getCaptureVolumeRange (JNIEnv* env, jobject obj, jintArray anValues) { snd_mixer_elem_t* handle; jint values[2]; if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_getCaptureVolumeRange(): begin\n"); } handle = getHandle(env, obj); snd_mixer_selem_get_capture_volume_range(handle, (long*) values, (long*) values + 1); checkArrayLength(env, anValues, 2); (*env)->SetIntArrayRegion(env, anValues, 0, 2, values); if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_getCaptureVolumeRange(): end\n"); } }
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); } }
/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB", the values are logarithmic. */ static void* createVolumeControl(PortControlCreator* creator, PortControl* portControl, snd_mixer_elem_t* elem, int isPlayback) { void* control; float precision; long min, max; if (isPlayback) { snd_mixer_selem_get_playback_volume_range(elem, &min, &max); } else { snd_mixer_selem_get_capture_volume_range(elem, &min, &max); } /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic. So the following calculation is wrong. However, there is no correct calculation, since for equal-distant logarithmic steps, the precision expressed in linear varies over the scale. */ precision = 1.0F / getRange(min, max); control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, ""); return control; }
float getRealVolume(PortControl* portControl, snd_mixer_selem_channel_id_t channel) { float fValue; long lValue = 0; long min = 0; long max = 0; if (isPlaybackFunction(portControl->portType)) { snd_mixer_selem_get_playback_volume_range(portControl->elem, &min, &max); snd_mixer_selem_get_playback_volume(portControl->elem, channel, &lValue); } else { snd_mixer_selem_get_capture_volume_range(portControl->elem, &min, &max); snd_mixer_selem_get_capture_volume(portControl->elem, channel, &lValue); } fValue = scaleVolumeValueToNormalized(lValue, min, max); return fValue; }
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; }
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; }
GstMixerTrack * gst_alsa_mixer_track_new (snd_mixer_elem_t * element, gint num, gint track_num, gint flags, gboolean sw, GstAlsaMixerTrack * shared_mute_track, gboolean append_capture) { GstAlsaMixerTrack *alsa_track; GstMixerTrack *track; const gchar *name; const gchar *label; gint i; long min = 0, max = 0; const struct { const gchar orig[12]; const gchar trans[12]; } alsa_track_labels[] = { { "Master", N_("Master")}, { "Bass", N_("Bass")}, { "Treble", N_("Treble")}, { "PCM", N_("PCM")}, { "Synth", N_("Synth")}, { "Line", N_("Line-in")}, { "CD", N_("CD")}, { "Mic", N_("Microphone")}, { "PC Speaker", N_("PC Speaker")}, { "Playback", N_("Playback")}, { "Capture", N_("Capture")} }; name = snd_mixer_selem_get_name (element); GST_LOG ("[%s] num=%d,track_num=%d,flags=0x%08x,sw=%s,shared_mute_track=%p", name, num, track_num, flags, (sw) ? "true" : "false", shared_mute_track); track = (GstMixerTrack *) g_object_new (GST_ALSA_MIXER_TRACK_TYPE, "untranslated-label", name, NULL); alsa_track = (GstAlsaMixerTrack *) track; GST_LOG ("[%s] created new mixer track %p", name, track); /* This reflects the assumptions used for GstAlsaMixerTrack */ if (!(!!(flags & GST_MIXER_TRACK_OUTPUT) ^ !!(flags & GST_MIXER_TRACK_INPUT))) { GST_ERROR ("Mixer track must be either output or input!"); g_return_val_if_reached (NULL); } track->flags = flags; alsa_track->element = element; alsa_track->shared_mute = shared_mute_track; alsa_track->track_num = track_num; alsa_track->alsa_channels = 0; gst_alsa_mixer_track_update_alsa_capabilities (alsa_track); if (flags & GST_MIXER_TRACK_OUTPUT) { while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && snd_mixer_selem_has_playback_channel (element, alsa_track->alsa_channels)) { alsa_track->alsa_channels++; } GST_LOG ("[%s] %d output channels", name, alsa_track->alsa_channels); } else if (flags & GST_MIXER_TRACK_INPUT) { while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && snd_mixer_selem_has_capture_channel (element, alsa_track->alsa_channels)) { alsa_track->alsa_channels++; } GST_LOG ("[%s] %d input channels", name, alsa_track->alsa_channels); } else { g_assert_not_reached (); } if (sw) track->num_channels = 0; else track->num_channels = alsa_track->alsa_channels; /* translate the name if we can */ label = name; for (i = 0; i < G_N_ELEMENTS (alsa_track_labels); ++i) { if (g_utf8_collate (label, alsa_track_labels[i].orig) == 0) { label = _(alsa_track_labels[i].trans); break; } } if (num == 0) { track->label = g_strdup_printf ("%s%s%s", label, append_capture ? " " : "", append_capture ? _("Capture") : ""); } else { track->label = g_strdup_printf ("%s%s%s %d", label, append_capture ? " " : "", append_capture ? _("Capture") : "", num); } /* set volume information */ if (track->num_channels > 0) { if ((flags & GST_MIXER_TRACK_OUTPUT)) snd_mixer_selem_get_playback_volume_range (element, &min, &max); else snd_mixer_selem_get_capture_volume_range (element, &min, &max); } track->min_volume = (gint) min; track->max_volume = (gint) max; for (i = 0; i < track->num_channels; i++) { long tmp = 0; if (flags & GST_MIXER_TRACK_OUTPUT) snd_mixer_selem_get_playback_volume (element, i, &tmp); else snd_mixer_selem_get_capture_volume (element, i, &tmp); alsa_track->volumes[i] = (gint) tmp; } gst_alsa_mixer_track_update (alsa_track); return track; }
bool AlsaMixer::StepVolume( const char* channel, int step ) { LOG( Logger::LOG_DEBUG, "AlsaMixer::StepVolume( %s, %d )", channel, step); 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; } for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { long volume; if (snd_mixer_selem_get_playback_volume(elem, (snd_mixer_selem_channel_id_t)chn, &volume ) >= 0) { volume += step; if( volume > max )volume = max; if( volume < min )volume = min; 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; } for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { long volume; if (snd_mixer_selem_get_capture_volume(elem, (snd_mixer_selem_channel_id_t)chn, &volume ) >= 0) { volume += step; if( volume > max )volume = max; if( volume < min )volume = min; 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; }