![](https://secure.gravatar.com/avatar/5b19e9d0e834ea10ef75803718ad564b.jpg?s=120&d=mm&r=g)
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@poczta.fm
Thanks for the patch.
The approach is interesting, but I'm not sure whether we should put all into amixer in this way since we don't want extra library dependency. (Note: amixer could be used in initrd.) I think it's better to split the code and make it as an individual daemon 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