From 1e76b09595fc9ba46d725debcb08c3f5d0dd6275 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sun, 3 Jul 2016 20:34:26 +0300 Subject: initial --- Makefile | 12 +++++ main.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 Makefile create mode 100644 main.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2edca13 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +CC=gcc +CFLAGS=-std=gnu99 -Wall -pedantic -Wextra `pkg-config --cflags ${LIBS}` +LIBS=alsa dbus-1 +LDFLAGS=`pkg-config --libs ${LIBS}` + +all: main + +main: main.o + ${CC} ${LDFLAGS} main.o -o alsa-volume-monitor + +main.o: + ${CC} ${CFLAGS} -c main.c diff --git a/main.c b/main.c new file mode 100644 index 0000000..9ef961b --- /dev/null +++ b/main.c @@ -0,0 +1,150 @@ +/** + * Based on alsactl/monitor.c (by Takashi Iwai ) from alsa-utils + * http://git.alsa-project.org/?p=alsa-utils.git;a=blob_plain;f=alsactl/monitor.c;hb=HEAD + * + * Inspired by kbdd + */ + +#include +#include +#include + +int notify(DBusConnection *conn) +{ + DBusMessage *msg; + dbus_uint32_t serial = 0; + + msg = dbus_message_new_signal("/com/ch1p/Object", "com.ch1p.avm", "valueChanged"); + if (NULL == msg) { + fprintf(stderr, "DBus: Message Null\n"); + return 1; + } + + if (!dbus_connection_send(conn, msg, &serial)) { + fprintf(stderr, "DBus send: Out Of Memory!\n"); + return 1; + } + dbus_connection_flush(conn); + + dbus_message_unref(msg); + return 0; +} + +int open_ctl(const char *name, snd_ctl_t **ctlp) +{ + snd_ctl_t *ctl; + int err; + + err = snd_ctl_open(&ctl, name, SND_CTL_READONLY); + if (err < 0) { + fprintf(stderr, "Cannot open ctl %s\n", name); + return err; + } + err = snd_ctl_subscribe_events(ctl, 1); + if (err < 0) { + fprintf(stderr, "Cannot open subscribe events to ctl %s\n", name); + snd_ctl_close(ctl); + return err; + } + *ctlp = ctl; + return 0; +} + +int check_event(snd_ctl_t *ctl, DBusConnection *conn) +{ + snd_ctl_event_t *event; + unsigned int mask; + int err; + + snd_ctl_event_alloca(&event); + err = snd_ctl_read(ctl, event); + if (err < 0) + return err; + + if (snd_ctl_event_get_type(event) != SND_CTL_EVENT_ELEM) + return 0; + + mask = snd_ctl_event_elem_get_mask(event); + if (!(mask & SND_CTL_EVENT_MASK_VALUE)) + return 0; + + notify(conn); + + return 0; +} + +#define MAX_CARDS 256 + +int monitor(const char *name, DBusConnection *conn) { + snd_ctl_t *ctl; + int err = 0; + + err = open_ctl(name, &ctl); + if (err < 0) + goto error; + + while (1) { + struct pollfd fd; + + snd_ctl_poll_descriptors(ctl, &fd, 1); + + err = poll(&fd, 1, -1); + if (err <= 0) { + err = 0; + break; + } + + unsigned short revents; + snd_ctl_poll_descriptors_revents(ctl, &fd, 1, + &revents); + if (revents & POLLIN) + check_event(ctl, conn); + } + +error: + snd_ctl_close(ctl); + return err; +} + +void usage() +{ + fprintf(stderr, + "Usage:\n" + " alsa-volume-monitor \n\n" + "Example:\n" + " alsa-volume-monitor hw:0\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + if (argc < 2) + usage(); + + DBusConnection *connection; + DBusError err; + int ret; + + dbus_error_init(&err); + connection = dbus_bus_get(DBUS_BUS_SESSION, &err); + + if (dbus_error_is_set(&err)) { + fprintf(stderr, "DBus Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + + if (!connection) { + return 1; + } + + ret = dbus_bus_request_name(connection, "com.ch1p.avm", + DBUS_NAME_FLAG_REPLACE_EXISTING , &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "DBus Name Error (%s)\n", err.message); + dbus_error_free(&err); + } + + monitor(argv[1], connection); + + return 0; +} -- cgit v1.2.3