int OpenMixer_Linux_ALSA(px_mixer *Px, int index) { PxInfo *info; int card; if (!initialize(Px)) { return FALSE; } info = (PxInfo *) Px->info; if (PaAlsa_GetStreamInputCard(Px->pa_stream, &card) == paNoError) { if (!open_mixer(&info->capture, card, FALSE)) { return cleanup(Px); } } if (PaAlsa_GetStreamOutputCard(Px->pa_stream, &card) == paNoError) { if (!open_mixer(&info->playback, card, TRUE)) { return cleanup(Px); } } return TRUE; }
void moko_alsa_volume_control_set_element_from_name (MokoAlsaVolumeControl *control, const gchar *name) { MokoAlsaVolumeControlPrivate *priv = ALSA_VOLUME_CONTROL_PRIVATE (control); if (!priv->device) return; detach_mixer (control); if (!name) { moko_alsa_volume_control_set_element (control, NULL); return; } open_mixer (control); if ((snd_mixer_attach (priv->mixer_handle, priv->device) == 0) && (snd_mixer_selem_register (priv->mixer_handle, NULL, NULL) == 0) && (snd_mixer_load (priv->mixer_handle) == 0)) { snd_mixer_elem_t *elem; elem = snd_mixer_first_elem (priv->mixer_handle); while (elem) { const char *elem_name = snd_mixer_selem_get_name (elem); if (strcmp (elem_name, name) == 0) break; elem = snd_mixer_elem_next (elem); } if (!elem) { snd_mixer_detach (priv->mixer_handle, priv->device); close_mixer (control); g_warning ("Mixer element '%s' not found", name); attach_mixer (control); } else { snd_mixer_selem_id_t *id; if (snd_mixer_selem_id_malloc (&id) != 0) { g_warning ("Unable to allocate element id"); snd_mixer_detach ( priv->mixer_handle, priv->device); close_mixer (control); } else { snd_mixer_selem_get_id (elem, id); snd_mixer_detach ( priv->mixer_handle, priv->device); close_mixer (control); g_debug ("Setting element ID"); moko_alsa_volume_control_set_element ( control, id); snd_mixer_selem_id_free (id); } } } else g_warning ("Unable to open mixer on card '%s'", priv->device); }
static void attach_mixer (MokoAlsaVolumeControl *self) { MokoAlsaVolumeControlPrivate *priv = ALSA_VOLUME_CONTROL_PRIVATE (self); g_debug ("Trying to attach... %p, %s, %p", priv->mixer_handle, priv->device, priv->element); open_mixer (self); if (priv->mixer_handle && priv->device && priv->element && (snd_mixer_attach (priv->mixer_handle, priv->device) == 0) && (snd_mixer_selem_register (priv->mixer_handle, NULL, NULL) == 0) && (snd_mixer_load (priv->mixer_handle) == 0)) { priv->mixer_elem = snd_mixer_find_selem ( priv->mixer_handle, priv->element); if (!priv->mixer_elem) { g_warning ("Unable to find mixer element"); snd_mixer_detach (priv->mixer_handle, priv->device); close_mixer (self); } else { g_debug ("Attached to mixer"); if (snd_mixer_selem_has_playback_volume ( priv->mixer_elem)) { priv->control_type = PLAYBACK; snd_mixer_selem_get_playback_volume_range ( priv->mixer_elem, &priv->min, &priv->max); } else if (snd_mixer_selem_has_capture_volume ( priv->mixer_elem)) { priv->control_type = CAPTURE; snd_mixer_selem_get_capture_volume_range ( priv->mixer_elem, &priv->min, &priv->max); } else priv->control_type = CONTROL; snd_mixer_elem_set_callback ( priv->mixer_elem, mixer_elem_event_cb); snd_mixer_elem_set_callback_private ( priv->mixer_elem, self); start_polling (self); update_volume (self); } } else { close_mixer (self); } }
int main(int argc, char *argv[]) { if (!open_mixer()) return 1; initialize_channels(); atexit(Epplet_cleanup); Epplet_Init("Emix", "0.9", "Audio mixer Epplet", 3, 3, argc, argv, 0); vs_master = Epplet_create_vslider(2, 2, 44, 0, 20, 1, 5, &channels[0].value, set_volume, &channels[0]); vs_pcm = Epplet_create_vslider(10, 2, 44, 0, 20, 1, 5, &channels[1].value, set_volume, &channels[1]); vs_lin = Epplet_create_vslider(18, 2, 44, 0, 20, 1, 5, &channels[2].value, set_volume, &channels[2]); vs_cda = Epplet_create_vslider(26, 2, 44, 0, 20, 1, 5, &channels[3].value, set_volume, &channels[3]); b_close = Epplet_create_button(NULL, NULL, 34, 3, 0, 0, "CLOSE", 0, NULL, cb_close, NULL); b_mute = Epplet_create_togglebutton("M", NULL, 34, 18, 12, 12, &mute_status, toggle_mute, &channels[0]); b_help = Epplet_create_button(NULL, NULL, 34, 33, 0, 0, "HELP", 0, NULL, cb_help, NULL); Epplet_gadget_show(vs_master); Epplet_gadget_show(vs_pcm); Epplet_gadget_show(vs_lin); Epplet_gadget_show(vs_cda); Epplet_gadget_show(b_close); Epplet_gadget_show(b_mute); Epplet_gadget_show(b_help); Epplet_show(); Epplet_timer(update_volumes_callback, NULL, 0.5, "TIMER"); Epplet_Loop(); return 0; }
/** * Get all playable channels for a single alsa card and * return them as a GSList. * * @param card HCTL name of the alsa card * @return the GSList of channels */ static GSList * get_channels(const char *card) { int ccount, i; snd_mixer_t *mixer; snd_mixer_elem_t *telem; GSList *channels = NULL; mixer = open_mixer(card, NULL, 0); if (mixer == NULL) return NULL; ccount = snd_mixer_get_count(mixer); telem = snd_mixer_first_elem(mixer); for (i = 0; i < ccount; i++) { if (snd_mixer_selem_has_playback_volume(telem)) channels = g_slist_append(channels, strdup(snd_mixer_selem_get_name(telem))); telem = snd_mixer_elem_next(telem); } #ifdef DEBUG GSList *tmp = channels; if (tmp) { printf("Card %s: available channels\n", card); while (tmp) { printf("\t%s\n", (char *) tmp->data); tmp = tmp->next; } } else { printf("Card %s: no playable channels\n", card); } #endif close_mixer(mixer, card); return channels; }
/** * Initializes the alsa system by getting the cards * and channels and setting the io watch for external * volume changes. * * @return 0 on success otherwise negative error code */ static int alsaset(void) { char *card_name; char *channel; // update list of available cards DEBUG_PRINT("Getting available cards..."); get_cards(); assert(cards != NULL); // get selected card assert(active_card == NULL); card_name = get_selected_card(); DEBUG_PRINT("Selected card: %s", card_name); if (card_name) { active_card = find_card(card_name); g_free(card_name); } // if not available, use the default card if (!active_card) { DEBUG_PRINT("Using default soundcard"); active_card = cards->data; } // If no playable channels, iterate on card list until a valid card is // found. // In most situations, the first card of the list (which is the // Alsa default card) can be opened. // However, in some situations the default card may be unavailable. // For example, when it's an USB DAC, and it's disconnected. if (!active_card->channels) { GSList *item; DEBUG_PRINT("Card '%s' has no playable channels, iterating on card list", active_card->dev); for (item = cards; item; item = item->next) { active_card = item->data; if (active_card->channels) break; } assert(item != NULL); } // open card DEBUG_PRINT("Opening card '%s'...", active_card->dev); smixer_options.device = active_card->dev; handle = open_mixer(active_card->dev, &smixer_options, smixer_level); assert(handle != NULL); // Set the channel // We have to handle the fact that the channel name defined // in PNMixer configuration is not necessarily valid. // For example, this may happen when the default alsa soundcard // is modified. The channel names of the new default card may // not match the channel names of the previous default card. assert(elem == NULL); channel = get_selected_channel(active_card->name); if (channel) { snd_mixer_selem_id_t *sid; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_name(sid, channel); elem = snd_mixer_find_selem(handle, sid); g_free(channel); } if (elem == NULL) { elem = snd_mixer_first_elem(handle); } assert(elem != NULL); // Set callback DEBUG_PRINT("Using channel '%s'", snd_mixer_selem_get_name(elem)); snd_mixer_elem_set_callback(elem, alsa_cb); // set watch for volume changes set_io_watch(handle); return 0; }