bool AlsaMixer::GetVolumePercent( const char* channel, int* value ) { LOG( Logger::LOG_DEBUG, "AlsaMixer::GetVolume( %s )", channel); 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; } long volume; for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { if (snd_mixer_selem_get_playback_volume(elem, (snd_mixer_selem_channel_id_t)chn, &volume ) >= 0) { *value = (volume - min) * 100 / ( max - min ); success = true; break; } } }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; } long volume; for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { if (snd_mixer_selem_get_capture_volume(elem, (snd_mixer_selem_channel_id_t)chn, &volume ) >= 0) { *value = (volume - min) * 100 / ( max - min ); success = true; break; } } } if( !success ) { LOG( Logger::LOG_ERROR, "Error getting control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); } end: return success; }
static snd_mixer_elem_t *find_mixer_elem_by_name(const char *goal_name) { snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid = NULL; snd_mixer_selem_id_malloc(&sid); for (elem = snd_mixer_first_elem(alsa_mixer_handle); elem; elem = snd_mixer_elem_next(elem)) { const char *name; snd_mixer_selem_get_id(elem, sid); name = snd_mixer_selem_id_get_name(sid); d_print("name = %s\n", name); d_print("has playback volume = %d\n", snd_mixer_selem_has_playback_volume(elem)); d_print("has playback switch = %d\n", snd_mixer_selem_has_playback_switch(elem)); if (strcasecmp(name, goal_name) == 0) { if (!snd_mixer_selem_has_playback_volume(elem)) { d_print("mixer element `%s' does not have playback volume\n", name); elem = NULL; } break; } } snd_mixer_selem_id_free(sid); return elem; }
static int alsa_mixer_open(int *volume_max) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; int count; int rc; snd_mixer_selem_id_alloca(&sid); rc = snd_mixer_open(&alsa_mixer_handle, 0); if (rc < 0) goto error; rc = snd_mixer_attach(alsa_mixer_handle, alsa_mixer_device); if (rc < 0) goto error; rc = snd_mixer_selem_register(alsa_mixer_handle, NULL, NULL); if (rc < 0) goto error; rc = snd_mixer_load(alsa_mixer_handle); if (rc < 0) goto error; count = snd_mixer_get_count(alsa_mixer_handle); if (count == 0) { d_print("error: mixer does not have elements\n"); return -2; } elem = snd_mixer_first_elem(alsa_mixer_handle); while (elem) { const char *name; int has_vol, has_switch; snd_mixer_selem_get_id(elem, sid); name = snd_mixer_selem_id_get_name(sid); d_print("name = %s\n", name); d_print("has playback volume = %d\n", snd_mixer_selem_has_playback_volume(elem)); d_print("has playback switch = %d\n", snd_mixer_selem_has_playback_switch(elem)); if (strcasecmp(name, alsa_mixer_element)) { elem = snd_mixer_elem_next(elem); continue; } has_vol = snd_mixer_selem_has_playback_volume(elem); if (!has_vol) { d_print("mixer element `%s' does not have playback volume\n", name); return -2; } snd_mixer_selem_get_playback_volume_range(elem, &mixer_vol_min, &mixer_vol_max); has_switch = snd_mixer_selem_has_playback_switch(elem); /* FIXME: get number of channels */ mixer_elem = elem; *volume_max = mixer_vol_max - mixer_vol_min; return 0; } d_print("error: mixer element `%s' not found\n", alsa_mixer_element); return -2; error: d_print("error: %s\n", snd_strerror(rc)); return -1; }
bool AlsaMixer::GetChannelSwitch( const char* channel, bool* on ) { 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_switch(elem) ) { for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { int value; if (snd_mixer_selem_get_playback_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value) >= 0) { *on = value != 0; success = true; break; } } }else if( snd_mixer_selem_has_capture_switch(elem) ) { for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) { int value; if (snd_mixer_selem_get_capture_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value ) >= 0) { *on = value != 0; success = true; break; } } } if( !success ) { LOG( Logger::LOG_ERROR, "Error getting control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); } end: return success; }
static int on_mixer_event(snd_mixer_t *handle, unsigned int mask, snd_mixer_elem_t *elem) { snd_mixer_selem_id_t *sid; if(mask & SND_CTL_EVENT_MASK_ADD) { snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_get_id(elem, sid); DEBUG("set callback for mixer control = %s\n", snd_mixer_selem_id_get_name(sid)); snd_mixer_elem_set_callback(elem, on_mixer_elem_event); } return 0; }
static int on_mixer_elem_event(snd_mixer_elem_t *elem, unsigned int mask) { snd_mixer_selem_id_t *sid; void *data = NULL; if(elem) data = snd_mixer_elem_get_callback_private(elem); if(data) { long min, max, Rvol, Lvol; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_get_id(elem, sid); DEBUG("mixer elem control = %s, mask = %x, data = %x\n", snd_mixer_selem_id_get_name(sid), mask, data); if(mask & SND_CTL_EVENT_MASK_VALUE) { char path[1024] = {0}; alsa_mixer_t *mixer = (alsa_mixer_t *)g_object_get_data(G_OBJECT(data), "mixer-obj"); GtkWidget *img = (GtkWidget *)g_object_get_data(G_OBJECT(data), "image-obj"); DEBUG("mixer = %x, img = %x\n", mixer, img); if(snd_mixer_selem_has_playback_volume(elem)) { if(mixer->pcm_muted != alsa_mixer_is_muted(elem, NULL)) { mixer->pcm_muted = !mixer->pcm_muted; g_snprintf(path, 1024, DVM_CONFIG_PATH"/%s", g_playback_iconset[mixer->pcm_muted ? 3: 0]); DEBUG("playback switch detected, image path = %s\n", path); gtk_image_set_from_file(GTK_IMAGE(img), path); } snd_mixer_selem_get_playback_volume(elem, 0, &Rvol); snd_mixer_selem_get_playback_volume(elem, 1, &Lvol); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); DEBUG("new val = %d, %d, min = %d, max = %d\n", Rvol, Lvol, min, max); } else if(snd_mixer_selem_has_capture_volume(elem)) { if(mixer->mic_muted != alsa_mixer_is_muted(elem, NULL)) { mixer->mic_muted = !mixer->mic_muted; g_snprintf(path, 1024, DVM_CONFIG_PATH"/%s", g_capture_iconset[mixer->mic_muted ? 3: 0]); DEBUG("capture switch detected, image path = %s\n", path); gtk_image_set_from_file(GTK_IMAGE(img), path); } snd_mixer_selem_get_capture_volume_range(elem, &min, &max); snd_mixer_selem_get_capture_volume(elem, 0, &Rvol); snd_mixer_selem_get_capture_volume(elem, 1, &Lvol); DEBUG("new val = %d, %d, min = %d, max = %d\n", Rvol, Lvol, min, max); } g_mixer_ui_updated = TRUE; gtk_adjustment_set_value(GTK_ADJUSTMENT(data), ((gdouble)(Rvol+Lvol)*50)/(max-min)); } } return 0; }
/* * The purpose of this function is to let the user to select * the input where he plugged his signals. * Now if user select "default", as device, we have to select the input * on the mixer of the card used by "default". * What is the card used by device "default" ? */ static void as_setup_input_combo (GtkWidget *combo, SoundParams *sparams) { snd_mixer_t *handle; int i ; snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; snd_mixer_selem_id_alloca(&sid); char *devname; char name[32]; devname = sparams->device_name; if ( *sparams->indexstr == '-' ) { sprintf(name, "hw:%d", sparams->firstcard); devname = name; } handle = sound_open_mixer(devname); if ( handle == NULL ){ return ; } for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem, sid); if (! snd_mixer_selem_is_active(elem)) { continue; } const char *control_name = snd_mixer_selem_id_get_name(sid); // printf("Simple mixer control '%s',%i\n", control_name, snd_mixer_selem_id_get_index(sid)); if (snd_mixer_selem_is_enum_capture(elem)) { int items; char itemname[40]; app_free(sparams->control_name); sparams->control_name = app_strdup(control_name); items = snd_mixer_selem_get_enum_items(elem); // printf(" Items:"); for (i = 0; i < items; i++) { snd_mixer_selem_get_enum_item_name(elem, i, sizeof(itemname) - 1, itemname); // printf(" '%s'", itemname); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), itemname ); if ( i == sparams->input ) { gtk_combo_box_set_active (GTK_COMBO_BOX (combo), i); } } // printf("\n"); } } snd_mixer_close(handle); return ; }
void list_mixers(const char *output_device) { int err; snd_mixer_t *handle; snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; char *ctl = ctl4device(output_device); snd_mixer_selem_id_alloca(&sid); LOG_INFO("listing mixers for: %s", output_device); if ((err = snd_mixer_open(&handle, 0)) < 0) { LOG_ERROR("open error: %s", snd_strerror(err)); return; } if ((err = snd_mixer_attach(handle, ctl)) < 0) { LOG_ERROR("attach error: %s", snd_strerror(err)); snd_mixer_close(handle); free(ctl); return; } free(ctl); if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { LOG_ERROR("register error: %s", snd_strerror(err)); snd_mixer_close(handle); return; } if ((err = snd_mixer_load(handle)) < 0) { LOG_ERROR("load error: %s", snd_strerror(err)); snd_mixer_close(handle); return; } printf("Volume controls for %s\n", output_device); for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) { if (snd_mixer_selem_has_playback_volume(elem)) { snd_mixer_selem_get_id(elem, sid); printf(" %s", snd_mixer_selem_id_get_name(sid)); if (snd_mixer_selem_id_get_index(sid)) { printf(",%d", snd_mixer_selem_id_get_index(sid)); } printf("\n"); } } printf("\n"); snd_mixer_close(handle); }
void SoundPref::getMixerDevices(int mode) { snd_mixer_t *mixer; QComboBox *cmb; if (mode == modePlayback) cmb = ui.playbackMixerDeviceCmb; else { // TODO : capture mixer devices } cmb->clear(); int err; if ((err = snd->getMixer(&mixer, mixerCard)) < 0) { return; } snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); int indx = 0; int current = -1; cmb->addItem(""); for (elem = snd_mixer_first_elem(mixer); elem; elem = snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem, sid); if (!snd_mixer_selem_is_active(elem)) continue; QString device = snd_mixer_selem_id_get_name(sid); if (mode == modePlayback) { if (snd_mixer_selem_has_playback_volume(elem)) cmb->addItem(device); } else if (mode == modeCapture) { // TODO: } else continue; if (device == mixerDevice) { current = indx; } indx ++; } if (current >= 0) cmb->setCurrentIndex(current+1); snd_mixer_close(mixer); }
static PxVolume get_volume(PxDev *dev, const char *name, int playback) { const char *sname; int i; if (!dev->handle) { return 0.0; } for (i = 0; i < dev->numselems; i++) { sname = snd_mixer_selem_id_get_name(dev->selems[i].sid); if (strcmp(sname, name) == 0) { return get_volume_indexed(dev, i, playback); } } return 0.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 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; }
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; }
static int mixer_open(void) { snd_mixer_elem_t *elem; snd_mixer_elem_t *master; snd_mixer_elem_t *pcm; snd_mixer_elem_t *custom; snd_mixer_selem_id_t *sid; int ret; ret = snd_mixer_open(&mixer_hdl, 0); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to open mixer: %s\n", snd_strerror(ret)); mixer_hdl = NULL; return -1; } ret = snd_mixer_attach(mixer_hdl, card_name); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to attach mixer: %s\n", snd_strerror(ret)); goto out_close; } ret = snd_mixer_selem_register(mixer_hdl, NULL, NULL); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to register mixer: %s\n", snd_strerror(ret)); goto out_detach; } ret = snd_mixer_load(mixer_hdl); if (ret < 0) { DPRINTF(E_LOG, L_LAUDIO, "Failed to load mixer: %s\n", snd_strerror(ret)); goto out_detach; } /* Grab interesting elements */ snd_mixer_selem_id_alloca(&sid); pcm = NULL; master = NULL; custom = NULL; for (elem = snd_mixer_first_elem(mixer_hdl); elem; elem = snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem, sid); if (mixer_name && (strcmp(snd_mixer_selem_id_get_name(sid), mixer_name) == 0)) { custom = elem; break; } else if (strcmp(snd_mixer_selem_id_get_name(sid), "PCM") == 0) pcm = elem; else if (strcmp(snd_mixer_selem_id_get_name(sid), "Master") == 0) master = elem; } if (mixer_name) { if (custom) vol_elem = custom; else { DPRINTF(E_LOG, L_LAUDIO, "Failed to open configured mixer element '%s'\n", mixer_name); goto out_detach; } } else if (pcm) vol_elem = pcm; else if (master) vol_elem = master; else { DPRINTF(E_LOG, L_LAUDIO, "Failed to open PCM or Master mixer element\n"); goto out_detach; } /* Get min & max volume */ snd_mixer_selem_get_playback_volume_range(vol_elem, &vol_min, &vol_max); return 0; out_detach: snd_mixer_detach(mixer_hdl, card_name); out_close: snd_mixer_close(mixer_hdl); mixer_hdl = NULL; vol_elem = NULL; return -1; }
/* 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; }
static int alsa_mixer_init(alsa_mixer_t *mixer, char *card) { snd_mixer_selem_id_t *sid; snd_mixer_elem_t *elem; snd_mixer_selem_id_alloca(&sid); int err; if ((err = snd_mixer_open(&mixer->handle, 0)) < 0) { DEBUG("Mixer %s open error: %s", card, snd_strerror(err)); mixer->handle = NULL; return err; } if ((err = snd_mixer_attach(mixer->handle, card)) < 0) { DEBUG("Mixer %s local error: %s\n", card, snd_strerror(err)); snd_mixer_close(mixer->handle); mixer->handle = NULL; return err; } if ((err = snd_mixer_selem_register(mixer->handle, NULL, NULL)) < 0) { DEBUG("Mixer register error: %s", snd_strerror(err)); snd_mixer_close(mixer->handle); return err; } snd_mixer_set_callback(mixer->handle, on_mixer_event); err = snd_mixer_load(mixer->handle); if (err < 0) { DEBUG("Mixer %s load error: %s", card, snd_strerror(err)); snd_mixer_close(mixer->handle); return err; } for (elem = snd_mixer_first_elem(mixer->handle); elem; elem = snd_mixer_elem_next(elem)) { const char *name = NULL; snd_mixer_selem_get_id(elem, sid); if (!snd_mixer_selem_is_active(elem)) continue; name = snd_mixer_selem_id_get_name(sid); if(snd_mixer_selem_has_playback_volume(elem)) { if(strcmp(name, "Master") == 0) mixer->master = elem; else if(strcmp(name, "PCM") == 0) mixer->pcm = elem; } else if(snd_mixer_selem_has_capture_volume(elem) || snd_mixer_selem_has_capture_switch(elem)) { DEBUG("capture elem name = %s\n", name); /**make sure have one capture source if capture is available*/ if(NULL == mixer->mic) { mixer->mic = elem; } /**if have Microphone, replace it*/ if(strcmp(name, "Microphone") == 0) mixer->mic = elem; if(strcmp(name, "Capture") == 0) mixer->mic = elem; } } DEBUG("master = %x, pcm = %x, microphone = %x\n", mixer->master, mixer->pcm, mixer->mic); return 0; }
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; }
bool LapsusAlsaMixer::init() { int err; snd_ctl_t *ctl_handle; snd_ctl_card_info_t *hw_info; snd_ctl_card_info_alloca(&hw_info); if ((err = snd_ctl_open (&ctl_handle, "default", 0)) < 0) return false; if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) return false; snd_ctl_close (ctl_handle); if ((err = snd_mixer_open (&_handle, 0)) < 0) return false; if ((err = snd_mixer_attach (_handle, "default")) < 0) return false; if ((err = snd_mixer_selem_register (_handle, 0, 0)) < 0) return false; if ((err = snd_mixer_load (_handle)) < 0) return false; // printf("Card name: '%s'\n", snd_ctl_card_info_get_name(hw_info)); // printf("Device name: '%s'\n", snd_ctl_card_info_get_mixername(hw_info)); snd_mixer_elem_t *elem; snd_mixer_selem_id_t *tmp_sid = 0; for (elem = snd_mixer_first_elem(_handle); elem; elem = snd_mixer_elem_next(elem)) { if (snd_mixer_selem_is_active(elem)) { if (!tmp_sid) tmp_sid = (snd_mixer_selem_id_t*) malloc(snd_mixer_selem_id_sizeof()); snd_mixer_selem_get_id(elem, tmp_sid); const char *name = snd_mixer_selem_id_get_name( tmp_sid ); if (!strcasecmp(name, "Headphone")) { if (sids[ID_HP]) delete sids[ID_HP]; sids[ID_HP] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } else if (!strcasecmp(name, "Front")) { if (sids[ID_F]) delete sids[ID_F]; sids[ID_F] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } else if (!strcasecmp(name, "Master")) { if (sids[ID_M]) delete sids[ID_M]; sids[ID_M] = new SIDInfo(_handle, tmp_sid); tmp_sid = 0; } } } if (tmp_sid) free(tmp_sid); bool foundAny = false; for (int i = 0; i < ID_LAST; ++i) { if (sids[i]) { if (sids[i]->hasMute) { foundAny = true; } if (sids[i]->hasVolume) { foundAny = true; long range = sids[i]->max - sids[i]->min; if (range > _globalMax) _globalMax = range; } } } if (_globalMax > INT_MAX) _globalMax = INT_MAX; if (!foundAny) return false; for (int i = 0; i < ID_LAST; ++i) { if (sids[i]) sids[i]->setGlobalMax(_globalMax); } if ((_count = snd_mixer_poll_descriptors_count(_handle)) < 0) return false; _fds = (struct pollfd*) calloc(_count, sizeof(struct pollfd)); if (!_fds) return false; if ((err = snd_mixer_poll_descriptors(_handle, _fds, _count)) < 0) return false; if (err != _count) return 0; _sns = new QSocketNotifier*[_count]; for ( int i = 0; i < _count; ++i ) { _sns[i] = new QSocketNotifier(_fds[i].fd, QSocketNotifier::Read); connect(_sns[i], SIGNAL(activated(int)), this, SLOT(alsaEvent())); } // To read our current parameters. Signals will be emited, but those signals // are not yet connected to anything - this method is called from constructor // only. getVolume(); mixerIsMuted(); return true; }
ALSAMixer::ALSAMixer(const char *sndcard) { int err; LOGI(" Init ALSAMIXER for SNDCARD : %s",sndcard); mixerMasterProp = ALSA_PROP(AudioSystem::DEVICE_OUT_ALL, "master", "PCM", "Capture"); mixerProp = { ALSA_PROP(AudioSystem::DEVICE_OUT_EARPIECE, "earpiece", "Earpiece", "Capture"), ALSA_PROP(AudioSystem::DEVICE_OUT_SPEAKER, "speaker", "Speaker", ""), ALSA_PROP(AudioSystem::DEVICE_OUT_WIRED_HEADSET, "headset", "Headphone", "Capture"), ALSA_PROP(AudioSystem::DEVICE_OUT_BLUETOOTH_SCO, "bluetooth.sco", "Bluetooth", "Bluetooth Capture"), ALSA_PROP(AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP, "bluetooth.a2dp", "Bluetooth A2DP", "Bluetooth A2DP Capture"), ALSA_PROP(static_cast<AudioSystem::audio_devices>(0), "", NULL, NULL) }; initMixer (&mMixer[SND_PCM_STREAM_PLAYBACK], sndcard); initMixer (&mMixer[SND_PCM_STREAM_CAPTURE], sndcard); snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) { mixer_info_t *info = mixerMasterProp[i].mInfo = new mixer_info_t; property_get (mixerMasterProp[i].propName, info->name, mixerMasterProp[i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); info->volume = info->max; setVol[i] (elem, info->volume); if (i == SND_PCM_STREAM_PLAYBACK && snd_mixer_selem_has_playback_switch (elem)) snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } LOGV("Mixer: master '%s' %s.", info->name, info->elem ? "found" : "not found"); for (int j = 0; mixerProp[j][i].device; j++) { mixer_info_t *info = mixerProp[j][i].mInfo = new mixer_info_t; property_get (mixerProp[j][i].propName, info->name, mixerProp[j][i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); info->volume = info->max; setVol[i] (elem, info->volume); if (i == SND_PCM_STREAM_PLAYBACK && snd_mixer_selem_has_playback_switch (elem)) snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } LOGV("Mixer: route '%s' %s.", info->name, info->elem ? "found" : "not found"); } } LOGV("mixer initialized."); }
ALSAMixer::ALSAMixer() { int err; initMixer (&mMixer[SND_PCM_STREAM_PLAYBACK], "AndroidOut"); initMixer (&mMixer[SND_PCM_STREAM_CAPTURE], "AndroidIn"); snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) { mixer_info_t *info = mixerMasterProp[i].mInfo = new mixer_info_t; property_get (mixerMasterProp[i].propName, info->name, mixerMasterProp[i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); info->volume = info->max; setVol[i] (elem, info->volume); if (i == SND_PCM_STREAM_PLAYBACK && snd_mixer_selem_has_playback_switch (elem)) snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } LOGV("Mixer: master '%s' %s.", info->name, info->elem ? "found" : "not found"); for (int j = 0; mixerProp[j][i].device; j++) { mixer_info_t *info = mixerProp[j][i].mInfo = new mixer_info_t; property_get (mixerProp[j][i].propName, info->name, mixerProp[j][i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); info->volume = info->max; setVol[i] (elem, info->volume); if (i == SND_PCM_STREAM_PLAYBACK && snd_mixer_selem_has_playback_switch (elem)) snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } LOGV("Mixer: route '%s' %s.", info->name, info->elem ? "found" : "not found"); } } #ifdef AUDIO_MODEM_TI ALSAControl control("hw:00"); status_t error; #if 0//(WORKAROUND_AVOID_VOICE_VOLUME_SATURATION == 1) //[LG_FW_P970_MERGE] - jungsoo1221.lee LOGV("Workaround: Voice call max volume limited to: %d", WORKAROUND_MAX_VOICE_VOLUME); #endif #if 0//(WORKAROUND_SET_VOICE_VOLUME_MIN == 1) //[LG_FW_P970_MERGE] - jungsoo1221.lee LOGV("Workaround: Voice call min volume limited to: %d", WORKAROUND_MIN_VOICE_VOLUME); #endif for (int i = 0; inCallVolumeProp[i].device; i++) { mixer_incall_vol_info_t *info = inCallVolumeProp[i].mInfo = new mixer_incall_vol_info_t; property_get (inCallVolumeProp[i].propName, info->name, inCallVolumeProp[i].propDefault); error = control.get(info->name, info->volume, 0); error = control.getmin(info->name, info->min); error = control.getmax(info->name, info->max); #if 0//(WORKAROUND_AVOID_VOICE_VOLUME_SATURATION == 1) //[LG_FW_P970_MERGE] - jungsoo1221.lee info->max = WORKAROUND_MAX_VOICE_VOLUME; #endif #if 0//(WORKAROUND_SET_VOICE_VOLUME_MIN == 1) //[LG_FW_P970_MERGE] - jungsoo1221.lee info->min = WORKAROUND_MIN_VOICE_VOLUME; #endif if (error < 0) { LOGV("Mixer: In Call Volume '%s': not found", info->name); } else { LOGV("Mixer: In Call Volume '%s': vol. %d min. %d max. %d", info->name, info->volume, info->min, info->max); } } #endif LOGV("mixer initialized."); }
ALSAMixer::ALSAMixer() { int err; initMixer (&mMixer[SND_PCM_STREAM_PLAYBACK], "AndroidOut"); initMixer (&mMixer[SND_PCM_STREAM_CAPTURE], "AndroidIn"); snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); for (int i = 0; i <= SND_PCM_STREAM_LAST; i++) { if (!mMixer[i]) continue; mixer_info_t *info = mixerMasterProp[i].mInfo = new mixer_info_t; property_get (mixerMasterProp[i].propName, info->name, mixerMasterProp[i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); //info->volume = info->max; //setVol[i] (elem, info->volume); //if (i == SND_PCM_STREAM_PLAYBACK && // snd_mixer_selem_has_playback_switch (elem)) // snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } ALOGV("Mixer: master '%s' %s.", info->name, info->elem ? "found" : "not found"); for (int j = 0; mixerProp[j][i].device; j++) { mixer_info_t *info = mixerProp[j][i].mInfo = new mixer_info_t; property_get (mixerProp[j][i].propName, info->name, mixerProp[j][i].propDefault); for (snd_mixer_elem_t *elem = snd_mixer_first_elem(mMixer[i]); elem; elem = snd_mixer_elem_next(elem)) { if (!snd_mixer_selem_is_active(elem)) continue; snd_mixer_selem_get_id(elem, sid); // Find PCM playback volume control element. const char *elementName = snd_mixer_selem_id_get_name(sid); if (info->elem == NULL && strcmp(elementName, info->name) == 0 && hasVolume[i] (elem)) { info->elem = elem; getVolumeRange[i] (elem, &info->min, &info->max); //info->volume = info->max; //setVol[i] (elem, info->volume); //if (i == SND_PCM_STREAM_PLAYBACK && // snd_mixer_selem_has_playback_switch (elem)) // snd_mixer_selem_set_playback_switch_all (elem, 1); break; } } ALOGV("Mixer: route '%s' %s.", info->name, info->elem ? "found" : "not found"); } } ALOGV("mixer initialized."); }
static void alsa_volume_mixer(double volume) { snd_mixer_t* handle; snd_mixer_elem_t* elem; snd_mixer_selem_id_t* sid; unsigned c; long pmin, pmax; long v; int r; snd_mixer_selem_id_alloca(&sid); log_std(("sound:alsa: soundb_alsa_volume(volume:%g)\n", (double)volume)); snd_mixer_selem_id_set_name(sid, "Master"); r = snd_mixer_open(&handle, 0); if (r < 0) { log_std(("ERROR:sound:alsa: Mixer open error: %s\n", snd_strerror(r))); goto err; } r = snd_mixer_attach(handle, alsa_option.mixer_buffer); if (r < 0) { log_std(("ERROR:sound:alsa: Mixer attach error: %s\n", snd_strerror(r))); goto err_close; } if ((r = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { log_std(("ERROR:sound:alsa: Mixer register error: %s\n", snd_strerror(r))); goto err_close; } r = snd_mixer_load(handle); if (r < 0) { log_std(("ERROR:sound:alsa: Mixer load error: %s\n", snd_strerror(r))); goto err_close; } elem = snd_mixer_find_selem(handle, sid); if (!elem) { log_std(("ERROR:sound:alsa: Unable to find simple control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid))); goto err_close; } if (volume > 0) { if (snd_mixer_selem_has_playback_switch(elem)) { log_std(("sound:alsa: enable playback\n")); for(c=0;c<=SND_MIXER_SCHN_LAST;++c) { snd_mixer_selem_set_playback_switch(elem, c, 1); } } else { log_std(("sound:alsa: skip enable playback\n")); } if (snd_mixer_selem_has_playback_volume(elem)) { log_std(("sound:alsa: set playback volume\n")); snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); v = pmin + (pmax - pmin) * volume + 0.5; if (v < pmin) v = pmin; if (v > pmax) v = pmax; log_std(("sound:alsa: min:%d, max:%d, set:%d\n", (int)pmin, (int)pmax, (int)v)); for(c=0;c<=SND_MIXER_SCHN_LAST;++c) { snd_mixer_selem_set_playback_volume(elem, c, v); } } else { log_std(("sound:alsa: skip set playback volume\n")); } } else { if (snd_mixer_selem_has_playback_switch(elem)) { log_std(("sound:alsa: disable playback\n")); for(c=0;c<=SND_MIXER_SCHN_LAST;++c) { snd_mixer_selem_set_playback_switch(elem, c, 0); } } else { log_std(("sound:alsa: skip disable playback\n")); } } snd_mixer_close(handle); return; err_close: snd_mixer_close(handle); err: return; }