static int elem_get_vol_percent(snd_mixer_elem_t *elem) { int i, percent; long pmin, pmax, volume; for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { /* playback volume */ 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); if (snd_mixer_selem_has_playback_volume(elem)) snd_mixer_selem_get_playback_volume(elem, i, &volume); } /* capture volume */ else if (snd_mixer_selem_has_capture_channel(elem, i) && !snd_mixer_selem_has_common_volume(elem)) { snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax); if (snd_mixer_selem_has_capture_volume(elem)) snd_mixer_selem_get_capture_volume(elem, i, &volume); } else { /* Misc. ex: Boost */ snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); snd_mixer_selem_get_playback_volume(elem, i, &volume); } } percent = (int) ((double)(volume - pmin) / (double)(pmax - pmin) * 100); return percent; }
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 gst_alsa_mixer_track_update_alsa_capabilities (GstAlsaMixerTrack * alsa_track) { alsa_track->alsa_flags = 0; alsa_track->capture_group = -1; if (snd_mixer_selem_has_common_volume (alsa_track->element)) alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_VOLUME; if (snd_mixer_selem_has_playback_volume (alsa_track->element)) alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PVOLUME; if (snd_mixer_selem_has_capture_volume (alsa_track->element)) alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CVOLUME; if (snd_mixer_selem_has_common_switch (alsa_track->element)) alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_SWITCH; if (snd_mixer_selem_has_playback_switch (alsa_track->element)) alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PSWITCH; if (snd_mixer_selem_has_capture_switch (alsa_track->element)) { alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH; if (snd_mixer_selem_has_capture_switch_exclusive (alsa_track->element)) { alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH_EXCL; alsa_track->capture_group = snd_mixer_selem_get_capture_group (alsa_track->element); } } GST_LOG ("[%s] alsa_flags=0x%08x, capture_group=%d", snd_mixer_selem_get_name (alsa_track->element), alsa_track->alsa_flags, alsa_track->capture_group); }
/* * Class: org_tritonus_lowlevel_alsa_AlsaMixerElement * Method: hasCommonVolume * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCommonVolume (JNIEnv* env, jobject obj) { snd_mixer_elem_t* handle; int nReturn; if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCommonVolume(): begin\n"); } handle = getHandle(env, obj); nReturn = snd_mixer_selem_has_common_volume(handle); if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCommonVolume(): end\n"); } return (jboolean) nReturn; }
static void gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer) { gint i, count; snd_mixer_elem_t *element, *master; GList *item; g_return_if_fail (mixer->handle != NULL); if (mixer->tracklist) return; g_static_rec_mutex_lock (mixer->rec_mutex); master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle); count = snd_mixer_get_count (mixer->handle); element = snd_mixer_first_elem (mixer->handle); /* build track list * * Some ALSA tracks may have playback and capture capabilities. * Here we model them as two separate GStreamer tracks. */ for (i = 0; i < count; i++) { GstMixerTrack *play_track = NULL; GstMixerTrack *cap_track = NULL; const gchar *name; GList *item; gint samename = 0; name = snd_mixer_selem_get_name (element); /* prevent dup names */ for (item = mixer->tracklist; item != NULL; item = item->next) { snd_mixer_elem_t *temp; if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) temp = GST_ALSA_MIXER_OPTIONS (item->data)->element; else temp = GST_ALSA_MIXER_TRACK (item->data)->element; if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0) samename++; } GST_LOG ("[%s] probing element #%u, mixer->dir=%u", name, i, mixer->dir); if (mixer->dir & GST_ALSA_MIXER_PLAYBACK) { gboolean has_playback_switch, has_playback_volume; has_playback_switch = snd_mixer_selem_has_playback_switch (element); has_playback_volume = snd_mixer_selem_has_playback_volume (element); GST_LOG ("[%s] PLAYBACK: has_playback_volume=%d, has_playback_switch=%d" "%s", name, has_playback_volume, has_playback_switch, (element == master) ? " MASTER" : ""); if (has_playback_volume) { gint flags = GST_MIXER_TRACK_OUTPUT; if (element == master) flags |= GST_MIXER_TRACK_MASTER; play_track = gst_alsa_mixer_track_new (element, samename, i, flags, FALSE, NULL, FALSE); } else if (has_playback_switch) { /* simple mute switch */ play_track = gst_alsa_mixer_track_new (element, samename, i, GST_MIXER_TRACK_OUTPUT, TRUE, NULL, FALSE); } if (snd_mixer_selem_is_enumerated (element)) { GstMixerOptions *opts = gst_alsa_mixer_options_new (element, i); GST_LOG ("[%s] is enumerated (%d)", name, i); mixer->tracklist = g_list_append (mixer->tracklist, opts); } } if (mixer->dir & GST_ALSA_MIXER_CAPTURE) { gboolean has_capture_switch, has_common_switch; gboolean has_capture_volume, has_common_volume; has_capture_switch = snd_mixer_selem_has_capture_switch (element); has_common_switch = snd_mixer_selem_has_common_switch (element); has_capture_volume = snd_mixer_selem_has_capture_volume (element); has_common_volume = snd_mixer_selem_has_common_volume (element); GST_LOG ("[%s] CAPTURE: has_capture_volume=%d, has_common_volume=%d, " "has_capture_switch=%d, has_common_switch=%d, play_track=%p", name, has_capture_volume, has_common_volume, has_capture_switch, has_common_switch, play_track); if (has_capture_volume && !(play_track && has_common_volume)) { cap_track = gst_alsa_mixer_track_new (element, samename, i, GST_MIXER_TRACK_INPUT, FALSE, NULL, play_track != NULL); } else if (has_capture_switch && !(play_track && has_common_switch)) { cap_track = gst_alsa_mixer_track_new (element, samename, i, GST_MIXER_TRACK_INPUT, TRUE, NULL, play_track != NULL); } } if (play_track && cap_track) { GST_ALSA_MIXER_TRACK (play_track)->shared_mute = GST_ALSA_MIXER_TRACK (cap_track); GST_ALSA_MIXER_TRACK (cap_track)->shared_mute = GST_ALSA_MIXER_TRACK (play_track); } if (play_track) mixer->tracklist = g_list_append (mixer->tracklist, play_track); if (cap_track) mixer->tracklist = g_list_append (mixer->tracklist, cap_track); element = snd_mixer_elem_next (element); } for (item = mixer->tracklist; item != NULL; item = item->next) { snd_mixer_elem_t *temp; if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) temp = GST_ALSA_MIXER_OPTIONS (item->data)->element; else temp = GST_ALSA_MIXER_TRACK (item->data)->element; snd_mixer_elem_set_callback (temp, gst_alsa_mixer_elem_handle_callback); snd_mixer_elem_set_callback_private (temp, mixer); } g_static_rec_mutex_unlock (mixer->rec_mutex); }
static int open_mixer(PxDev *dev, int card, int playback) { snd_mixer_elem_t *elem; char name[256]; int err; int i; sprintf(name, "hw:%d", card); dev->card = card; dev->handle = NULL; do { err = snd_mixer_open(&dev->handle, 0); if (err < 0) { break; } err = snd_mixer_attach(dev->handle, name); if (err < 0) { break; } err = snd_mixer_selem_register(dev->handle, NULL, NULL); if (err < 0) { break; } err = snd_mixer_load(dev->handle); if (err < 0) { break; } for (elem = snd_mixer_first_elem(dev->handle); elem != NULL; elem = snd_mixer_elem_next(elem)) { if (!playback) { if (!snd_mixer_selem_has_capture_volume(elem) && !snd_mixer_selem_has_capture_switch(elem) && !snd_mixer_selem_has_common_volume(elem)) { continue; } } else { if (!snd_mixer_selem_has_playback_volume(elem) && !snd_mixer_selem_has_playback_switch(elem) && !snd_mixer_selem_has_common_volume(elem)) { continue; } } dev->numselems++; } dev->selems = calloc(dev->numselems, sizeof(PxSelem)); if (dev->selems == NULL) { break; } i = 0; for (elem = snd_mixer_first_elem(dev->handle); elem != NULL; elem = snd_mixer_elem_next(elem)) { if (!playback) { if (!snd_mixer_selem_has_capture_volume(elem) && !snd_mixer_selem_has_capture_switch(elem) && !snd_mixer_selem_has_common_volume(elem)) { continue; } } else { if (!snd_mixer_selem_has_playback_volume(elem) && !snd_mixer_selem_has_playback_switch(elem) && !snd_mixer_selem_has_common_volume(elem)) { continue; } } if (snd_mixer_selem_id_malloc(&dev->selems[i].sid) < 0) { break; } snd_mixer_selem_get_id(elem, dev->selems[i].sid); dev->selems[i].elem = elem; snprintf(name, sizeof(name), "%s:%d", snd_mixer_selem_id_get_name(dev->selems[i].sid), snd_mixer_selem_id_get_index(dev->selems[i].sid)); dev->selems[i].name = strdup(name); if (!dev->selems[i].name) { break; } i++; } if (i == dev->numselems) { return TRUE; } } while (FALSE); if (dev->selems) { for (i = 0; i < dev->numselems; i++) { if (dev->selems[i].sid) { snd_mixer_selem_id_free(dev->selems[i].sid); } if (dev->selems[i].name) { free(dev->selems[i].name); } } free(dev->selems); dev->selems = NULL; } if (dev->handle) { snd_mixer_close(dev->handle); dev->handle = NULL; } return FALSE; }