Beispiel #1
0
static int mixer_init(char *name, char *iname)
{
	int n, i;
	struct pollfd *fds;

	if (snd_mixer_open(&mixer, 0) < 0) {
		fprintf(stderr, "can't open mixer\n");
		exit(1);
	}
	snd_mixer_attach(mixer, "default");
	snd_mixer_selem_register(mixer, NULL, NULL);
	snd_mixer_load(mixer);

	get_element(name, 1, &ch[0]);
	get_element(iname, 0, &ch[1]);
	
	n = snd_mixer_poll_descriptors_count(mixer);
	fds = calloc(n, sizeof(struct pollfd));
	snd_mixer_poll_descriptors(mixer, fds, n);

	for (i = 0; i < n; i++) {
		GIOChannel* channel = g_io_channel_unix_new( fds[i].fd );
		g_io_add_watch(channel, G_IO_IN|G_IO_HUP, on_mixer_event, NULL);
		g_io_channel_unref(channel);
	}
	return 0;
}
Beispiel #2
0
void lamixer_mixer_elemets()
{
	gint cnt = 0, i;
	struct pollfd *fds;

	g_list_foreach (VolumeBoxes, (GFunc)lamixer_mixerelem_show, NULL);
	
	gtk_table_resize(GTK_TABLE(mixerbox), mRows, ++pCols);
	gtk_table_attach(GTK_TABLE(mixerbox), switchvbox, pCols-1, pCols, 0, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
	
	gtk_table_resize(GTK_TABLE(capturebox), mRows, ++cCols);
	gtk_table_attach(GTK_TABLE(capturebox), switchcapturevbox, cCols-1, cCols, 0, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0);
	
	cnt = snd_mixer_poll_descriptors_count(mixer_handle);

	fds = g_new0(struct pollfd, cnt);

	snd_mixer_poll_descriptors(mixer_handle, fds, cnt);

	alsa_chans = g_new0(GIOChannel*, cnt);

	for (i=0; i<cnt; i++) {
		alsa_chans[i] = g_io_channel_unix_new(fds[i].fd);
		g_io_add_watch(alsa_chans[i], G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, lamixer_volbox_alsa_io, NULL);
	}
	
	g_free(fds);
	n_alsa_chans = cnt;
}
Beispiel #3
0
static void handle_mixer_events (snd_mixer_t *mixer_handle)
{
	int count;

	if ((count = snd_mixer_poll_descriptors_count(mixer_handle)) < 0)
		logit ("snd_mixer_poll_descriptors_count() failed: %s",
				snd_strerror(count));
	else {
		struct pollfd *fds;
		int err;

		fds = xcalloc (count, sizeof(struct pollfd));

		if ((err = snd_mixer_poll_descriptors(mixer_handle, fds,
						count)) < 0)
			logit ("snd_mixer_poll_descriptors() failed: %s",
					snd_strerror(count));
		else {
			err = poll (fds, count, 0);
			if (err < 0)
				error ("poll() failed: %s", strerror(errno));
			else if (err > 0) {
				debug ("Mixer event");
				if ((err = snd_mixer_handle_events(mixer_handle)
							) < 0)
					logit ("snd_mixer_handle_events() "
							"failed: %s",
							snd_strerror(err));
			}

		}

		free (fds);
	}
}
Beispiel #4
0
static int alsa_mixer_get_fds(int *fds)
{
	struct pollfd pfd[NR_MIXER_FDS];
	int count, i;

	count = snd_mixer_poll_descriptors(alsa_mixer_handle, pfd, NR_MIXER_FDS);
	for (i = 0; i < count; i++)
		fds[i] = pfd[i].fd;
	return count;
}
Beispiel #5
0
void asound_setup(const gchar * card, const gchar * channel,
	void (*volume_changed)(int,gboolean))
{
	// Make sure (for now) that the setup function only gets called once
	static int asound_setup_called = 0;
	assert(asound_setup_called == 0);
	asound_setup_called++;

	// Save card, volume_changed
	strcpy(m_card, card);
	m_volume_changed = volume_changed;

	// Load the mixer for the provided cardname
	snd_mixer_open(&m_mixer, 0);
	snd_mixer_attach(m_mixer, m_card);
	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, 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);
}
Beispiel #6
0
static void alsa_mixer_add_io_watch(alsa_mixer_t *mixer) {
  struct pollfd fdset[16];
  int cnt, err, idx;
  GIOChannel *chan = NULL;

  cnt = snd_mixer_poll_descriptors(mixer->handle, fdset, sizeof(fdset)/sizeof(fdset[0]));
  if(cnt > 0) {
    DEBUG("detected %d fdset in alsa event poll.\n", cnt);
    for(idx = 0; idx < cnt; idx++) {
      chan = g_io_channel_unix_new(fdset[idx].fd);
      g_io_add_watch(chan, fdset[idx].events, (GIOFunc)on_mixer_channel_event, mixer);
    }
  }
}
Beispiel #7
0
int VolumeALSA::setupMixer(QString card, QString device)
{
    char *name;
    int err, index;
    pcm_element = 0;

    qDebug("OutputALSA: setupMixer()");

    if ((err = getMixer(&m_mixer, card)) < 0)
        return err;

    parseMixerName(device.toAscii().data(), &name, &index);

    pcm_element = getMixerElem(m_mixer, name, index);

    free(name);

    if (!pcm_element)
    {
        qWarning("OutputALSA: Failed to find mixer element");
        return -1;
    }

    if((err = snd_mixer_selem_set_playback_volume_range(pcm_element, 0, 100)) < 0)
    {
        qWarning("OutputALSA: Unable to set volume range: %s", snd_strerror(-err));
        pcm_element = NULL;
        return -1;
    }

    // setup socket notifiers to monitor the state changes of the mixer
    int n = snd_mixer_poll_descriptors_count(m_mixer);
    if(n > 0)
    {
        struct pollfd* fds = new struct pollfd[n];
        n = snd_mixer_poll_descriptors(m_mixer, fds, n);
        for(int i = 0; i < n; ++i)
        {
            int sock = fds[i].fd;
            QSocketNotifier* sn = new QSocketNotifier(sock, QSocketNotifier::Read, this);
            connect(sn, SIGNAL(activated(int)), SIGNAL(changed()));
        }
        delete []fds;
    }

    qDebug("OutputALSA: setupMixer() success");
    return 0;
}
Beispiel #8
0
static int
_mixer_callback_add(E_Mixer_System *self,
                    int (*func)(void *data, E_Mixer_System *self),
                    void *data)
{
   struct e_mixer_callback_desc *desc;
   struct pollfd *pfds;
   int len;

   len = snd_mixer_poll_descriptors_count(self);
   if (len <= 0)
     return 0;

   desc = malloc(sizeof(struct e_mixer_callback_desc));
   if (!desc)
     return 0;

   desc->func = func;
   desc->data = data;
   desc->self = self;
   desc->idler = NULL;
   desc->handlers = NULL;

   pfds = alloca(len * sizeof(struct pollfd));
   len = snd_mixer_poll_descriptors(self, pfds, len);
   if (len <= 0)
     {
        free(desc);
        return 0;
     }

   while (len > 0)
     {
        Ecore_Fd_Handler *fd_handler;

        len--;
        fd_handler = ecore_main_fd_handler_add(
            pfds[len].fd, ECORE_FD_READ, _cb_fd_handler, desc, NULL, NULL);
        desc->handlers = eina_list_prepend(desc->handlers, fd_handler);
     }

   snd_mixer_set_callback_private(self, desc);

   return 1;
}
Beispiel #9
0
static void
task_monitor_alsa (gpointer data)
{
  struct pollfd *pfds;
  unsigned int nfds, rnfds;
  unsigned short revents;
  GstAlsaMixer *mixer = (GstAlsaMixer *) data;

  g_static_rec_mutex_lock (mixer->rec_mutex);

  nfds = snd_mixer_poll_descriptors_count (mixer->handle);
  if (nfds <= 0) {
    GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds);
    /* FIXME: sleep ? stop monitoring ? */
    return;
  }

  pfds = g_newa (struct pollfd, nfds + 1);
  rnfds = snd_mixer_poll_descriptors (mixer->handle, pfds, nfds);
  g_assert (rnfds <= nfds);

  pfds[rnfds].fd = mixer->pfd[0];
  pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
  pfds[rnfds].revents = 0;

  g_static_rec_mutex_unlock (mixer->rec_mutex);

  GST_LOG ("task loop");
  poll (pfds, rnfds + 1, -1);

  g_static_rec_mutex_lock (mixer->rec_mutex);

  snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents);
  if (revents & POLLIN || revents & POLLPRI) {
    GST_DEBUG ("Handling events");
    snd_mixer_handle_events (mixer->handle);
  }

  g_static_rec_mutex_unlock (mixer->rec_mutex);
}
Beispiel #10
0
/**
 * Sets the io watch for external volume changes
 * and registers the poll_cb() callback function.
 *
 * @param mixer mixer handle
 */
static void
set_io_watch(snd_mixer_t *mixer)
{
    int i, pcount;
    struct pollfd fds[PCOUNT_MAX];

    pcount = snd_mixer_poll_descriptors_count(mixer);
    assert(pcount <= PCOUNT_MAX);
    pcount = snd_mixer_poll_descriptors(mixer, fds, pcount);

    if (pcount <= 0) {
        report_error("Warning: Couldn't get any poll descriptors. "
                     "Won't respond to external volume changes.");
        return;
    }

    for (i = 0; i < pcount; i++) {
        GIOChannel *gioc = g_io_channel_unix_new(fds[i].fd);
        gio_watch_ids[i] = g_io_add_watch(gioc, G_IO_IN | G_IO_ERR,
                                          poll_cb, NULL);
        g_io_channel_unref(gioc);
    }
}
Beispiel #11
0
static void
start_polling (MokoAlsaVolumeControl *self)
{
	struct pollfd *fds;
	gint i, nfds;

	MokoAlsaVolumeControlPrivate *priv = ALSA_VOLUME_CONTROL_PRIVATE (self);
	
	if ((nfds = snd_mixer_poll_descriptors_count (priv->mixer_handle))<=0) {
		g_warning ("No poll descriptors on mixer?");
		return;
	}
	
	fds = g_new0 (struct pollfd, nfds);
	if (snd_mixer_poll_descriptors (priv->mixer_handle, fds, nfds) < 0) {
		g_warning ("Error getting polling descriptors for sound mixer");
		g_free (fds);
		return;
	}
	
	for (i = 0; i < nfds; i++) {
		GIOChannel *channel = g_io_channel_unix_new (fds[i].fd);
		g_debug ("Adding IO watch (IN: %d, OUT: %d)",
			fds[i].events & POLLIN, fds[i].events & POLLOUT);
		g_io_add_watch (channel,
			((fds[i].events & POLLIN) ? G_IO_IN : 0) |
			((fds[i].events & POLLOUT) ? G_IO_OUT : 0) |
			((fds[i].events & POLLPRI) ? G_IO_PRI : 0) |
			((fds[i].events & POLLERR) ? G_IO_ERR : 0) |
			((fds[i].events & POLLHUP) ? G_IO_HUP : 0) |
			((fds[i].events & POLLNVAL) ? G_IO_NVAL : 0),
			(GIOFunc)io_func, self);
	}
	g_free (fds);
	
	g_debug ("Polling for events...");
}
Beispiel #12
0
static void
task_monitor_alsa (gpointer data)
{
  struct pollfd *pfds;
  unsigned int nfds, rnfds;
  unsigned short revents;
  GstAlsaMixer *mixer = (GstAlsaMixer *) data;
  gint ret;

  g_static_rec_mutex_lock (mixer->rec_mutex);

  nfds = snd_mixer_poll_descriptors_count (mixer->handle);
  if (nfds <= 0) {
    GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds);
    /* FIXME: sleep ? stop monitoring ? */
    g_static_rec_mutex_unlock (mixer->rec_mutex);
    return;
  }

  pfds = g_newa (struct pollfd, nfds + 1);
  rnfds = snd_mixer_poll_descriptors (mixer->handle, pfds, nfds);
  g_assert (rnfds <= nfds);

  if (rnfds < 0) {
    GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), ("alsa error: %s",
            snd_strerror (rnfds)));
    gst_task_pause (mixer->task);
    g_static_rec_mutex_unlock (mixer->rec_mutex);
    return;
  }

  pfds[rnfds].fd = mixer->pfd[0];
  pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR;
  pfds[rnfds].revents = 0;

  g_static_rec_mutex_unlock (mixer->rec_mutex);

  GST_LOG ("task loop");
  ret = poll (pfds, rnfds + 1, -1);

  if (ret < 0) {
    GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
    gst_task_pause (mixer->task);
    return;
  }

  g_static_rec_mutex_lock (mixer->rec_mutex);

  ret =
      snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents);
  if (ret < 0) {
    GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), ("alsa error: %s",
            snd_strerror (ret)));
    gst_task_pause (mixer->task);
  } else if (revents & (POLLIN | POLLPRI)) {
    GST_DEBUG ("Handling events");
    snd_mixer_handle_events (mixer->handle);
  } else if (revents & (POLLERR | POLLNVAL | POLLHUP)) {
    GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), (NULL));
    gst_task_pause (mixer->task);
  }

  g_static_rec_mutex_unlock (mixer->rec_mutex);
}
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;
}
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);
}