diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/mixer/AlsaMixerPlugin.cxx | 171 | ||||
-rw-r--r-- | test/read_mixer.cxx | 8 | ||||
-rw-r--r-- | test/run_output.cxx | 8 |
4 files changed, 55 insertions, 134 deletions
diff --git a/Makefile.am b/Makefile.am index 38d31b26b..a17346844 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1276,6 +1276,7 @@ test_run_output_LDADD = $(MPD_LIBS) \ $(ENCODER_LIBS) \ libmixer_plugins.a \ $(FILTER_LIBS) \ + libevent.a \ libutil.a \ $(GLIB_LIBS) test_run_output_SOURCES = test/run_output.cxx \ @@ -1307,6 +1308,7 @@ test_read_mixer_LDADD = \ libpcm.a \ libmixer_plugins.a \ $(OUTPUT_LIBS) \ + libevent.a \ $(GLIB_LIBS) test_read_mixer_SOURCES = test/read_mixer.c \ src/ConfigFile.cxx src/tokenizer.c src/utils.c src/string_util.c \ diff --git a/src/mixer/AlsaMixerPlugin.cxx b/src/mixer/AlsaMixerPlugin.cxx index 9808c6dcc..17f8b9a6f 100644 --- a/src/mixer/AlsaMixerPlugin.cxx +++ b/src/mixer/AlsaMixerPlugin.cxx @@ -21,6 +21,10 @@ #include "mixer_api.h" #include "output_api.h" #include "GlobalEvents.hxx" +#include "Main.hxx" +#include "event/MultiSocketMonitor.hxx" + +#include <algorithm> #include <glib.h> #include <alsa/asoundlib.h> @@ -29,13 +33,16 @@ #define VOLUME_MIXER_ALSA_CONTROL_DEFAULT "PCM" #define VOLUME_MIXER_ALSA_INDEX_DEFAULT 0 -struct alsa_mixer_source { - GSource source; +class AlsaMixerMonitor final : private MultiSocketMonitor { + snd_mixer_t *const mixer; - snd_mixer_t *mixer; +public: + AlsaMixerMonitor(EventLoop &_loop, snd_mixer_t *_mixer) + :MultiSocketMonitor(_loop), mixer(_mixer) {} - /** a linked list of all registered GPollFD objects */ - GSList *fds; +private: + virtual void PrepareSockets(gcc_unused gint *timeout_r) override; + virtual void DispatchSockets() override; }; struct alsa_mixer { @@ -52,7 +59,7 @@ struct alsa_mixer { long volume_max; int volume_set; - struct alsa_mixer_source *source; + AlsaMixerMonitor *monitor; }; /** @@ -64,144 +71,45 @@ alsa_mixer_quark(void) return g_quark_from_static_string("alsa_mixer"); } -/* - * GSource helper functions - * - */ - -static GSList ** -find_fd(GSList **list_r, int fd) -{ - while (true) { - GSList *list = *list_r; - if (list == NULL) - return NULL; - - GPollFD *p = (GPollFD *)list->data; - if (p->fd == fd) - return list_r; - - list_r = &list->next; - } -} - -static void -alsa_mixer_update_fd(struct alsa_mixer_source *source, const struct pollfd *p, - GSList **old_r) -{ - GSList **found_r = find_fd(old_r, p->fd); - if (found_r == NULL) { - /* new fd */ - GPollFD *q = g_new(GPollFD, 1); - q->fd = p->fd; - q->events = p->events; - g_source_add_poll(&source->source, q); - source->fds = g_slist_prepend(source->fds, q); - return; - } - - GSList *found = *found_r; - *found_r = found->next; - - GPollFD *q = (GPollFD *)found->data; - if (q->events != p->events) { - /* refresh events */ - g_source_remove_poll(&source->source, q); - q->events = p->events; - g_source_add_poll(&source->source, q); - } - - found->next = source->fds; - source->fds = found; -} - -static void -alsa_mixer_update_fds(struct alsa_mixer_source *source) +void +AlsaMixerMonitor::PrepareSockets(gcc_unused gint *timeout_r) { - int count = snd_mixer_poll_descriptors_count(source->mixer); + int count = snd_mixer_poll_descriptors_count(mixer); if (count < 0) count = 0; struct pollfd *pfds = g_new(struct pollfd, count); - count = snd_mixer_poll_descriptors(source->mixer, pfds, count); + count = snd_mixer_poll_descriptors(mixer, pfds, count); if (count < 0) count = 0; - GSList *old = source->fds; - source->fds = NULL; + struct pollfd *end = pfds + count; - for (int i = 0; i < count; ++i) - alsa_mixer_update_fd(source, &pfds[i], &old); - g_free(pfds); + UpdateSocketList([pfds, end](int fd) -> unsigned { + auto i = std::find_if(pfds, end, [fd](const struct pollfd &pfd){ + return pfd.fd == fd; + }); + if (i == end) + return 0; - for (; old != NULL; old = old->next) { - GPollFD *q = (GPollFD *)old->data; - g_source_remove_poll(&source->source, q); - g_free(q); - } + auto events = i->events; + i->events = 0; + return events; + }); - g_slist_free(old); -} + for (auto i = pfds; i != end; ++i) + if (i->events != 0) + AddSocket(i->fd, i->events); -/* - * GSource methods - * - */ - -static gboolean -alsa_mixer_source_prepare(GSource *_source, G_GNUC_UNUSED gint *timeout_r) -{ - struct alsa_mixer_source *source = (struct alsa_mixer_source *)_source; - alsa_mixer_update_fds(source); - - return false; -} - -static gboolean -alsa_mixer_source_check(GSource *_source) -{ - struct alsa_mixer_source *source = (struct alsa_mixer_source *)_source; - - for (const GSList *i = source->fds; i != NULL; i = i->next) { - const GPollFD *poll_fd = (GPollFD *)i->data; - if (poll_fd->revents != 0) - return true; - } - - return false; + g_free(pfds); } -static gboolean -alsa_mixer_source_dispatch(GSource *_source, - G_GNUC_UNUSED GSourceFunc callback, - G_GNUC_UNUSED gpointer user_data) +void +AlsaMixerMonitor::DispatchSockets() { - struct alsa_mixer_source *source = (struct alsa_mixer_source *)_source; - - snd_mixer_handle_events(source->mixer); - return true; + snd_mixer_handle_events(mixer); } -static void -alsa_mixer_source_finalize(GSource *_source) -{ - struct alsa_mixer_source *source = (struct alsa_mixer_source *)_source; - - for (GSList *i = source->fds; i != NULL; i = i->next) - g_free(i->data); - - g_slist_free(source->fds); -} - -static GSourceFuncs alsa_mixer_source_funcs = { - alsa_mixer_source_prepare, - alsa_mixer_source_check, - alsa_mixer_source_dispatch, - alsa_mixer_source_finalize, - nullptr, - nullptr, -}; - /* * libasound callbacks * @@ -306,11 +214,7 @@ alsa_mixer_setup(struct alsa_mixer *am, GError **error_r) snd_mixer_elem_set_callback(am->elem, alsa_mixer_elem_callback); - am->source = (struct alsa_mixer_source *) - g_source_new(&alsa_mixer_source_funcs, sizeof(*am->source)); - am->source->mixer = am->handle; - am->source->fds = NULL; - g_source_attach(&am->source->source, g_main_context_default()); + am->monitor = new AlsaMixerMonitor(*main_loop, am->handle); return true; } @@ -345,8 +249,7 @@ alsa_mixer_close(struct mixer *data) assert(am->handle != NULL); - g_source_destroy(&am->source->source); - g_source_unref(&am->source->source); + delete am->monitor; snd_mixer_elem_set_callback(am->elem, NULL); snd_mixer_close(am->handle); diff --git a/test/read_mixer.cxx b/test/read_mixer.cxx index 0b6c16359..c7a5a3e03 100644 --- a/test/read_mixer.cxx +++ b/test/read_mixer.cxx @@ -27,6 +27,8 @@ extern "C" { #include "pcm_volume.h" #include "GlobalEvents.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" #include <glib.h> @@ -34,6 +36,8 @@ extern "C" { #include <string.h> #include <unistd.h> +EventLoop *main_loop; + #ifdef HAVE_PULSE #include "output/pulse_output_plugin.h" @@ -122,6 +126,8 @@ int main(int argc, G_GNUC_UNUSED char **argv) g_thread_init(NULL); + main_loop = new EventLoop(EventLoop::Default()); + mixer = mixer_new(&alsa_mixer_plugin, NULL, NULL, &error); if (mixer == NULL) { g_printerr("mixer_new() failed: %s\n", error->message); @@ -141,6 +147,8 @@ int main(int argc, G_GNUC_UNUSED char **argv) mixer_close(mixer); mixer_free(mixer); + delete main_loop; + assert(volume >= -1 && volume <= 100); if (volume < 0) { diff --git a/test/run_output.cxx b/test/run_output.cxx index 29fb6462c..505423479 100644 --- a/test/run_output.cxx +++ b/test/run_output.cxx @@ -21,6 +21,8 @@ #include "OutputControl.hxx" #include "conf.h" #include "Idle.hxx" +#include "Main.hxx" +#include "event/Loop.hxx" #include "GlobalEvents.hxx" #include "IOThread.hxx" @@ -42,6 +44,8 @@ extern "C" { #include <unistd.h> #include <stdlib.h> +EventLoop *main_loop; + void GlobalEvents::Emit(gcc_unused Event event) { @@ -211,6 +215,8 @@ int main(int argc, char **argv) return 1; } + main_loop = new EventLoop(EventLoop::Default()); + io_thread_init(); if (!io_thread_start(&error)) { g_warning("%s", error->message); @@ -247,6 +253,8 @@ int main(int argc, char **argv) io_thread_deinit(); + delete main_loop; + config_global_finish(); return success ? EXIT_SUCCESS : EXIT_FAILURE; |