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; }
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; }
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); } }
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); }
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; }
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; }
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); }
/** * 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); } }
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..."); }
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); }