Example #1
0
void asound_set_channel(const gchar * channel)
{
    if(m_mixer == NULL || channel == NULL) {
        return;
    }
    if(g_strcmp0(channel, m_channel) == 0)
        return;

    // Clean up any previously set channels
    g_free(m_channel);
    m_channel = g_strdup(channel);
    if(m_elem)
    {
        snd_mixer_elem_set_callback(m_elem, NULL);
        m_elem = NULL;
    }

    // Setup m_elem using the provided channelname
    snd_mixer_selem_id_t * sid;
    snd_mixer_selem_id_malloc(&sid);
    snd_mixer_selem_id_set_name(sid, channel);
    m_elem = snd_mixer_find_selem(m_mixer, sid);
    if(m_elem != NULL)
    {
        snd_mixer_elem_set_callback(m_elem, asound_elem_event);
        snd_mixer_selem_id_free(sid);
    }
}
Example #2
0
void lamixer_mixerelem_show(MixerElem *mixer_elem)
{
	if(mixer_elem->playback != NULL)
		lamixer_volbox_show(mixer_elem->playback, mixer_elem->elem, mixerbox);
	
	if(mixer_elem->capture != NULL)
		lamixer_volbox_show(mixer_elem->capture, mixer_elem->elem, capturebox);
	
	if(mixer_elem->pswitch != NULL)
		lamixer_switchbox_show(mixer_elem->pswitch, switchvbox);
	
	if(mixer_elem->cswitch != NULL)
		lamixer_switchbox_show(mixer_elem->cswitch, switchcapturevbox);
	
	if(mixer_elem->penum != NULL)
		lamixer_enumbox_show(mixer_elem->penum, enumvbox);
	
	if(mixer_elem->cenum != NULL)
		lamixer_enumbox_show(mixer_elem->cenum, enumcapturevbox);
	
	if(mixer_elem->playback != NULL || mixer_elem->capture != NULL) {
		snd_mixer_elem_set_callback(mixer_elem->elem, lamixer_volbox_change);
		snd_mixer_elem_set_callback_private(mixer_elem->elem, mixer_elem);
	}
}
static int mixer_callback(snd_mixer_t *mixer, unsigned int mask, snd_mixer_elem_t *elem)
{
	if (mask & SND_CTL_EVENT_MASK_ADD) {
		snd_mixer_elem_set_callback(elem, elem_callback);
		controls_changed = TRUE;
	}
	return 0;
}
Example #4
0
void lamixer_enumbox_show(EnumBox *enumbox, GtkWidget *enumvbox)
{
	guint evalue;
	snd_mixer_selem_get_enum_item(enumbox->volelem, SND_MIXER_SCHN_FRONT_LEFT, &evalue);
	gtk_combo_box_set_active(GTK_COMBO_BOX(enumbox->enumswitch), evalue);
	gtk_box_pack_start(GTK_BOX(enumvbox), enumbox->enumhbox, TRUE, FALSE, 0);
	g_signal_connect(G_OBJECT(enumbox->enumswitch), "changed", G_CALLBACK(lamixer_enumbox_changed), enumbox->volelem);
	
	snd_mixer_elem_set_callback(enumbox->volelem, lamixer_enumbox_change);
	snd_mixer_elem_set_callback_private(enumbox->volelem, enumbox);
}
Example #5
0
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;
}
Example #6
0
void
gam_toggle_set_elem (GamToggle *gam_toggle, snd_mixer_elem_t *elem)
{
    GamTogglePrivate *priv;

    g_return_if_fail (GAM_IS_TOGGLE (gam_toggle));

    priv = GAM_TOGGLE_GET_PRIVATE (gam_toggle);

    if (priv->elem)
        snd_mixer_elem_set_callback (priv->elem, NULL);

    if (elem) {
        snd_mixer_elem_set_callback_private (elem, gam_toggle);
        snd_mixer_elem_set_callback (elem, gam_toggle_refresh);
    }

    priv->elem = elem;

    g_object_notify (G_OBJECT (gam_toggle), "elem");
}
Example #7
0
void lamixer_switchbox_show(SwitchBox *swbox, GtkWidget *swvbox)
{
	int swstat;

	snd_mixer_selem_get_playback_switch (swbox->volelem, SND_MIXER_SCHN_FRONT_LEFT, &swstat);

	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(swbox->volswitch), swstat);
	swbox->hswsignalid = g_signal_connect(G_OBJECT(swbox->volswitch), "toggled", G_CALLBACK(lamixer_volswitch_changed), swbox->volelem);
	gtk_box_pack_start(GTK_BOX(swvbox), swbox->volswitch, TRUE, TRUE, 0);

	snd_mixer_elem_set_callback(swbox->volelem, lamixer_switchbox_change);
	snd_mixer_elem_set_callback_private(swbox->volelem, swbox);
}
Example #8
0
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);
	}
}
Example #9
0
static gint
_j4status_alsa_section_mixer_callback(snd_mixer_t *mixer, guint mask, snd_mixer_elem_t *elem)
{
    J4statusAlsaSection *section = snd_mixer_get_callback_private(mixer);
    if ( mask & SND_CTL_EVENT_MASK_ADD )
    {
        if ( ( snd_mixer_selem_get_index(elem) == 0 )
             && ( g_strcmp0(snd_mixer_selem_get_name(elem), "Master") == 0 )
             && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)
             && ( snd_mixer_elem_get_callback_private(elem) == NULL )
            )
        {
            snd_mixer_elem_set_callback(elem, _j4status_alsa_section_elem_callback);
            snd_mixer_elem_set_callback_private(elem, section);
        }
    }
    return 0;
}
Example #10
0
static void
gam_toggle_finalize (GObject *object)
{
    GamToggle *gam_toggle;
    GamTogglePrivate *priv;

    g_return_if_fail (GAM_IS_TOGGLE (object));

    gam_toggle = GAM_TOGGLE (object);

    priv = GAM_TOGGLE_GET_PRIVATE (gam_toggle);

    snd_mixer_elem_set_callback (priv->elem, NULL);

    g_free (priv->name_config);

    priv->name_config = NULL;
    priv->elem = NULL;
    priv->mixer = NULL;
    priv->app = NULL;

    G_OBJECT_CLASS (parent_class)->finalize (object);
}
Example #11
0
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);
}
Example #12
0
/**
 * 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;
}
Example #13
0
void asound_setup(const gchar * card, const gchar * channel,
                  void (*volume_changed)(int,gboolean))
{
    gchar * card_override = NULL; // used to hold a string like hw:0 if a nice
    // device name was given as 'card'

    // Clean up resources from previous calls to setup
    g_free(m_channel);
    m_channel = NULL;
    if(m_elem) {
        snd_mixer_elem_set_callback(m_elem, NULL);
        m_elem = NULL;
    }
    if(m_mixer) {
        snd_mixer_close(m_mixer);
        m_mixer = NULL;
    }
    g_list_free_full(m_channel_names, g_free);
    m_channel_names = NULL;
    g_list_free_full(m_device_names, g_free);
    m_device_names = NULL;

    // Save card, volume_changed
    g_free(m_device);
    m_device = g_strdup(card);
    m_volume_changed = volume_changed;

    // Populate list of device names
    int card_number = -1;
    int ret = snd_card_next(&card_number);
    snd_ctl_card_info_t * info = NULL;
    snd_ctl_card_info_alloca(&info);
    m_device_names = g_list_append(m_device_names, (gpointer)g_strdup("default"));
    while(ret == 0 && card_number != -1) {
        char buf[16];
        sprintf(buf, "hw:%d", card_number);
        snd_ctl_t * ctl = NULL;
        if(snd_ctl_open(&ctl, buf, 0) < 0) {
            continue;
        }
        if(snd_ctl_card_info(ctl, info) < 0) {
            snd_ctl_close(ctl);
            continue;
        }
        snd_ctl_close(ctl);

        gchar * nice_name = g_strdup(snd_ctl_card_info_get_name(info));
        m_device_names = g_list_append(m_device_names, (gpointer)nice_name);

        if(g_strcmp0(nice_name, m_device) == 0) {
            g_free(card_override);
            card_override = g_strdup_printf("hw:%d", card_number);
        }
        ret = snd_card_next(&card_number);
    }

    // Load the mixer for the provided cardname
    snd_mixer_open(&m_mixer, 0);
    if(snd_mixer_attach(m_mixer, (card_override != NULL ? card_override : m_device)) < 0) {
        fprintf(stderr, "Failed to open sound device with name: %s\n",
                (card_override != NULL ? card_override : m_device));
        snd_mixer_close(m_mixer);
        m_mixer = NULL;
        g_free(card_override);
        return;
    } else {
        g_free(card_override);
    }
    snd_mixer_selem_register(m_mixer, NULL, NULL);
    snd_mixer_load(m_mixer);

    // Setup g_io_watch for the mixer
    int count = snd_mixer_poll_descriptors_count(m_mixer);
    if(count >= 1)
    {
        struct pollfd pfd;

        count = snd_mixer_poll_descriptors(m_mixer, &pfd, 1);
        if(count == 1)
        {
            GIOChannel * giochannel = g_io_channel_unix_new(pfd.fd);
            g_io_add_watch_full(giochannel, G_PRIORITY_DEFAULT,
                                G_IO_IN | G_IO_ERR , asound_poll_cb, NULL, NULL);
        }
    }

    // Iterate over the elements in the mixer and store them in m_channel_names
    int elemcount = snd_mixer_get_count(m_mixer);
    snd_mixer_elem_t * elem = snd_mixer_first_elem(m_mixer);
    int loop;
    for(loop = 0; loop < elemcount; loop++)
    {
        const char * elemname = snd_mixer_selem_get_name(elem);
        if(snd_mixer_selem_has_playback_volume(elem))
        {
            m_channel_names = g_list_append(m_channel_names,
                                            (gpointer)g_strdup(elemname));
        }
        elem = snd_mixer_elem_next(elem);
    }

    // Setup m_elem using the provided channelname
    if(channel != NULL && asound_channel_exists(channel))
        asound_set_channel(channel);
    else if(m_channel_names != NULL)
        asound_set_channel((const gchar*)m_channel_names->data);
}