At Mon, 3 Aug 2009 12:43:21 +0200,Łukasz Stelmach wrote:> > > The patch introduces D-Bus support in amixer. With --dbus option given amixer> works continiously (like with the --stdin) waiting for> org.freedesktop.Hal.Device.Condition with the first argument "ButtonPressed"> and the second being one of: "volume-up", "volume-down" and "mute". These> are emmited by the HAL input helper. A single amixer process can controll> one mixer item. There are options to choose a specific item to controll,> an input device to listen and a single adjustment step size.> > Signed-off-by: Łukasz Stelmach <stlman@xxxxxxxxx> Thanks for the patch. The approach is interesting, but I'm not sure whether we should putall into amixer in this way since we don't want extra librarydependency. (Note: amixer could be used in initrd.)I think it's better to split the code and make it as an individualdaemon instead of additional options of amixer. Just my $0.02. thanks, Takashi > ---> amixer/Makefile.am | 3 +-> amixer/amixer.1 | 18 ++++++> amixer/amixer.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++> configure.in | 12 ++++> 4 files changed, 203 insertions(+), 1 deletions(-)> > diff --git a/amixer/Makefile.am b/amixer/Makefile.am> index fcd0e81..fa951a6 100644> --- a/amixer/Makefile.am> +++ b/amixer/Makefile.am> @@ -1,5 +1,6 @@> INCLUDES = -I$(top_srcdir)/include> -LDADD = -lm> +LDADD = -lm @DBUS_LIBS@> +CFLAGS += @DBUS_CFLAGS@> # LDFLAGS = -static> # CFLAGS += -g -Wall> > diff --git a/amixer/amixer.1 b/amixer/amixer.1> index b1ac323..bc160be 100644> --- a/amixer/amixer.1> +++ b/amixer/amixer.1> @@ -88,6 +88,24 @@ Select the card number to control. The device name created from this> parameter has syntax 'hw:N' where N is specified card number.> > .TP> +\fI\-\-dbus[=\fISCONTROL\fP]> +> +Connect to system D-Bus and wait for \fIorg.freedesktop.Hal.Device.Condition\fP> +signals with ButtonPressed as the first argument and one of: \fIvolume-up\fP,> +\fIvolume-down\fP or \fImute\fP as the second one. Control the selected> +\fISCONTROL\fP item. The default item is 'Master,0'.> +> +.TP> +\fI\-\-dbus-path=<\fIUDI\fP>> +> +Choose a particular input device that emits control events.> +> +.TP> +\fI\-\-dbus-step=<\fIN\fP>> +> +Set an amount by wich to increase or decrease volume upon event.> +> +.TP> \fI\-D\fP device> > Select the device name to control. The default control name is 'default'.> diff --git a/amixer/amixer.c b/amixer/amixer.c> index 9620721..31de674 100644> --- a/amixer/amixer.c> +++ b/amixer/amixer.c> @@ -18,6 +18,8 @@> *> */> > +#include "aconfig.h"> +> #include <stdio.h>> #include <stdlib.h>> #include <string.h>> @@ -31,6 +33,10 @@> #include <sys/poll.h>> #include "amixer.h"> > +#ifdef HAVE_DBUS> +#include <dbus/dbus.h>> +#endif /* HAVE_DBUS */> +> #define LEVEL_BASIC (1<<0)> #define LEVEL_INACTIVE (1<<1)> #define LEVEL_ID (1<<2)> @@ -43,6 +49,12 @@ static int ignore_error = 0;> static struct snd_mixer_selem_regopt smixer_options;> static char card[64] = "default";> > +#ifdef HAVE_DBUS> +static char dbus_sctl[64] = "Master,0";> +static char *dbus_path = NULL;> +static char dbus_step[8] = "1";> +#endif /* HAVE_DBUS */> +> static void error(const char *fmt,...)> {> va_list va;> @@ -60,6 +72,11 @@ static int help(void)> printf("\nAvailable options:\n");> printf(" -h,--help this help\n");> printf(" -c,--card N select the card\n");> +#ifdef HAVE_DBUS> + printf(" --dbus[=sID] Connect to the system D-Bus and wait for volume messages\n");> + printf(" --dbus-path UDI Choose a particular input device (udi)\n");> + printf(" --dbus-step N Set the step size (default: 1)\n");> +#endif /* HAVE_DBUS */> printf(" -D,--device N select the device, default '%s'\n", card);> printf(" -d,--debug debug mode\n");> printf(" -n,--nocheck do not perform range checking\n");> @@ -1887,15 +1904,147 @@ static int exec_stdin(void)> return 0;> }> > +#ifdef HAVE_DBUS> +> +#define OPT_DBUS 0x81> +#define OPT_DBUS_PATH 0x82> +#define OPT_DBUS_STEP 0x83> +> +void* get_dbus_arg(DBusMessageIter* args, int type, void** out) {> + if (type != dbus_message_iter_get_arg_type(args))> + return NULL;> + dbus_message_iter_get_basic(args, out);> + dbus_message_iter_next(args);> + return *out;> +}> +> +int exec_dbus(void)> +{> + char *sargv[MAX_ARGS];> + int sargc;> + const char* s;> + int stepl;> + DBusError error;> + DBusMessage* msg;> + DBusConnection *conn;> + DBusMessageIter args;> +> + stepl = strlen(dbus_step);> + dbus_step[stepl+1] = '\0';> +> + dbus_error_init (&error);> + conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);> +> + if(!conn) {> + fprintf(stderr, "dbus:%s: %s\n",> + error.name, error.message);> + return 1;> + }> +> + dbus_bus_add_match(conn,> + "type='signal',"> + "interface='org.freedesktop.Hal.Device',"> + "member='Condition'",> + &error);> + /* The first message is a NameOwnerChanged signal, ignore it. */> + msg = dbus_connection_pop_message(conn);> + dbus_message_unref(msg);> +> + if(dbus_error_is_set(&error)) {> + fprintf(stderr, "dbus:match error:%s\n",> + error.message);> + return 1;> + }> +> + while (1) {> + sargv[0] = dbus_sctl; sargc = 1;> +> + if (!(msg = dbus_connection_pop_message(conn))) {> + dbus_connection_read_write(conn, -1);> + continue;> + }> +> + s = dbus_message_get_interface(msg);> + if(strncmp("org.freedesktop.Hal.Device", s, 26)) {> + if(debugflag)> + fprintf(stderr, "dbus:unsupported interface:%s\n", s);> + goto badmessage;> + }> +> + if(dbus_path &&> + (s=dbus_message_get_path(msg)) &&> + strncmp(dbus_path, s, strlen(s))) {> + if(debugflag)> + fprintf(stderr, "dbus:not the selected udi:%s\n", s);> + goto badmessage;> + }> +> + if(!dbus_message_iter_init(msg, &args)) {> + if(debugflag)> + fprintf(stderr, "dbus:message has no arguments\n");> + goto badmessage;> + }> +> + if (strncmp(get_dbus_arg(&args, DBUS_TYPE_STRING, (void*)&s), "ButtonPressed", 13)) {> + if(debugflag)> + fprintf(stderr, "dbus:not a ButtonPressed event\n");> + goto badmessage;> + }> +> + if (!get_dbus_arg(&args, DBUS_TYPE_STRING, (void*)&s)) {> + if(debugflag)> + fprintf(stderr, "dbus:invalid argument type\n");> + goto badmessage;> + }> +> + /* static int sset(unsigned int argc, char *argv[], int roflag, int keep_handle) */> + if (!strncmp(s, "volume-up", 9)) {> + if(debugflag)> + fprintf(stderr, "dbus:volume-up\n");> + dbus_step[stepl]='+';> + sargv[1] = dbus_step;> + } else if (!strncmp(s, "volume-down", 11)) {> + if(debugflag)> + fprintf(stderr, "dbus:volume-down\n");> + dbus_step[stepl]='-';> + sargv[1] = dbus_step;> + } else if (!strncmp(s, "mute", 4)) {> + if(debugflag)> + fprintf(stderr, "dbus:mute (toggle)\n");> + sargv[1] = "toggle";> + } else {> + if(debugflag)> + fprintf(stderr, "dbus:invalid argument value\n");> + goto badmessage;> + }> + sset(++sargc, sargv, 0, 1);> +badmessage:> + dbus_message_unref(msg);> + }> +> + if(conn)> + dbus_connection_unref(conn);> + return 0;> +}> +#endif /* HAVE_DBUS */> > int main(int argc, char *argv[])> {> int morehelp, level = 0;> int read_stdin = 0;> +#ifdef HAVE_DBUS> + int read_dbus = 0;> + int t;> +#endif /* HAVE_DBUS */> static const struct option long_option[] => {> {"help", 0, NULL, 'h'},> {"card", 1, NULL, 'c'},> +#ifdef HAVE_DBUS> + {"dbus", optional_argument, NULL, OPT_DBUS},> + {"dbus-path", 1, NULL, OPT_DBUS_PATH},> + {"dbus-step", 1, NULL, OPT_DBUS_STEP},> +#endif /* HAVE_DBUS */> {"device", 1, NULL, 'D'},> {"quiet", 0, NULL, 'q'},> {"inactive", 0, NULL, 'i'},> @@ -1964,6 +2113,24 @@ int main(int argc, char *argv[])> case 's':> read_stdin = 1;> break;> +#ifdef HAVE_DBUS> + case OPT_DBUS:> + if(optarg) {> + strncpy(dbus_sctl, optarg, sizeof(dbus_sctl)-1);> + dbus_sctl[sizeof(dbus_sctl)-1] = '\0';> + }> + read_dbus = 1;> + break;> + case OPT_DBUS_PATH:> + dbus_path=optarg;> + break;> + case OPT_DBUS_STEP:> + t=atoi(optarg);> + if(t > 0 && t <= 999999) {> + snprintf(dbus_step, sizeof(dbus_step), "%d", atoi(optarg));> + }> + break;> +#endif /* HAVE_DBUS */> default:> fprintf(stderr, "Invalid switch or option needs an argument.\n");> morehelp++;> @@ -1978,6 +2145,10 @@ int main(int argc, char *argv[])> if (read_stdin)> return exec_stdin();> > +#ifdef HAVE_DBUS> + if(read_dbus)> + return exec_dbus();> +#endif /* HAVE_DBUS */> if (argc - optind <= 0) {> return selems(LEVEL_BASIC | level) ? 1 : 0;> }> diff --git a/configure.in b/configure.in> index 1349ff3..717d6c5 100644> --- a/configure.in> +++ b/configure.in> @@ -7,6 +7,9 @@ AM_INIT_AUTOMAKE(alsa-utils, 1.0.20)> AM_GNU_GETTEXT([external])> AM_GNU_GETTEXT_VERSION([0.15])> > +dnl required versions of other packages> +m4_define([dbus_required_version], [1.2.0])> +> dnl Checks for programs.> > dnl try to gues cross-compiler if not set> @@ -74,6 +77,15 @@ AC_ARG_ENABLE(alsamixer,> no) alsamixer=false ;;> *) AC_MSG_ERROR(bad value ${enableval} for --enable-alsamixer) ;;> esac],[alsamixer=true])> +AC_ARG_WITH(dbus, [ --with-dbus Enable D-Bus support in amixer])> + if test "x$with_dbus" != xno; then> + PKG_CHECK_MODULES(DBUS, dbus-1 >= dbus_required_version,> + have_dbus=yes,> + have_dbus=no)> + fi> + if test "x$have_dbus" = xyes; then> + AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if amixer is to support D-Bus])> + fi> fi> AM_CONDITIONAL(ALSAMIXER, test x$alsamixer = xtrue)> > -- > 1.6.3.3> > > ----------------------------------------------------------------------> Zostan Dziewczyna lub Chlopakiem lata!> Wygraj skuter >> http://link.interia.pl/f22a7 > _______________________________________________Alsa-devel mailing listAlsa-devel@xxxxxxxxxxxxxxxxxxxx://mailman.alsa-project.org/mailman/listinfo/alsa-devel