void fill_card_combo(GtkWidget *combo, GtkWidget *channels_combo) { struct acard* c; GSList *cur_card; gchar* selected_card; int fs=0,idx,sidx=0; GtkTreeIter iter; GtkListStore* store = GTK_LIST_STORE(gtk_combo_box_get_model (GTK_COMBO_BOX(combo))); cur_card = cards; selected_card = get_selected_card(); idx = 0; while (cur_card) { c = cur_card->data; if (!c->channels) { cur_card = cur_card->next; continue; } if (selected_card && !strcmp(c->name,selected_card)) { gchar *sel_chan = get_selected_channel(c->name); sidx = idx; fill_channel_combo(c->channels,channels_combo,sel_chan); fs = 1; if (sel_chan) g_free(sel_chan); } gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, 0, c->name, -1); cur_card = cur_card->next; idx++; } if (!fs) { gchar *sel_chan; c = cards->data; sel_chan = get_selected_channel(c->name); fill_channel_combo(c->channels,channels_combo,sel_chan); if (sel_chan) g_free(sel_chan); } gtk_combo_box_set_active (GTK_COMBO_BOX (combo),sidx); if (selected_card) g_free(selected_card); }
/** * 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; }