Re: [PATCH - amixer] listen to D-Bus for volume-up, volume-down and mute signals.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux