PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
PA_MODULE_AUTHOR("Lennart Poettering");
PA_MODULE_DESCRIPTION("Multimedia keyboard support via Linux evdev");
PA_MODULE_VERSION(PACKAGE_VERSION);
-PA_MODULE_LOAD_ONCE(FALSE);
-PA_MODULE_USAGE("device=<evdev device> sink=<sink name>");
+PA_MODULE_LOAD_ONCE(false);
+PA_MODULE_USAGE("device=<evdev device> sink=<sink name> volume_limit=<volume limit> volume_step=<volume change step>");
#define DEFAULT_DEVICE "/dev/input/event0"
-/*
- * This isn't defined in older kernel headers and there is no way of
- * detecting it.
- */
-struct _input_id {
- __u16 bustype;
- __u16 vendor;
- __u16 product;
- __u16 version;
-};
-
static const char* const valid_modargs[] = {
"device",
"sink",
+ "volume_limit",
+ "volume_step",
NULL,
};
pa_io_event *io;
char *sink_name;
pa_module *module;
+ pa_volume_t volume_limit;
+ pa_volume_t volume_step;
};
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) {
}
if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) {
- enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID;
+ enum {
+ INVALID,
+ UP,
+ DOWN,
+ MUTE_TOGGLE
+ } volchange = INVALID;
pa_log_debug("Key code=%u, value=%u", ev.code, ev.value);
switch (ev.code) {
- case KEY_VOLUMEDOWN: volchange = DOWN; break;
- case KEY_VOLUMEUP: volchange = UP; break;
- case KEY_MUTE: volchange = MUTE_TOGGLE; break;
+ case KEY_VOLUMEDOWN:
+ volchange = DOWN;
+ break;
+
+ case KEY_VOLUMEUP:
+ volchange = UP;
+ break;
+
+ case KEY_MUTE:
+ volchange = MUTE_TOGGLE;
+ break;
}
if (volchange != INVALID) {
pa_sink *s;
- if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
+ if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK)))
pa_log("Failed to get sink '%s'", u->sink_name);
else {
- int i;
- pa_cvolume cv = *pa_sink_get_volume(s, FALSE);
-
-#define DELTA (PA_VOLUME_NORM/20)
+ pa_cvolume cv = *pa_sink_get_volume(s, false);
switch (volchange) {
case UP:
- for (i = 0; i < cv.channels; i++) {
- cv.values[i] += DELTA;
-
- if (cv.values[i] > PA_VOLUME_NORM)
- cv.values[i] = PA_VOLUME_NORM;
- }
-
- pa_sink_set_volume(s, &cv);
+ pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit);
+ pa_sink_set_volume(s, &cv, true, true);
break;
case DOWN:
- for (i = 0; i < cv.channels; i++) {
- if (cv.values[i] >= DELTA)
- cv.values[i] -= DELTA;
- else
- cv.values[i] = PA_VOLUME_MUTED;
- }
-
- pa_sink_set_volume(s, &cv);
+ pa_cvolume_dec(&cv, u->volume_step);
+ pa_sink_set_volume(s, &cv, true, true);
break;
case MUTE_TOGGLE:
-
- pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE));
+ pa_sink_set_mute(s, !pa_sink_get_mute(s, false), true);
break;
case INVALID:
- ;
+ pa_assert_not_reached();
}
}
}
u->module->core->mainloop->io_free(u->io);
u->io = NULL;
- pa_module_unload_request(u->module, TRUE);
+ pa_module_unload_request(u->module, true);
}
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
pa_modargs *ma = NULL;
struct userdata *u;
int version;
- struct _input_id input_id;
+ struct input_id input_id;
char name[256];
uint8_t evtype_bitmask[EV_MAX/8 + 1];
+ pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
+ pa_volume_t volume_step = PA_VOLUME_NORM/20;
pa_assert(m);
goto fail;
}
- m->userdata = u = pa_xnew(struct userdata,1);
+ if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
+ pa_log("Failed to parse volume limit");
+ goto fail;
+ }
+
+ if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
+ pa_log("Failed to parse volume step");
+ goto fail;
+ }
+
+ m->userdata = u = pa_xnew(struct userdata, 1);
u->module = m;
u->io = NULL;
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
u->fd = -1;
u->fd_type = 0;
+ u->volume_limit = PA_CLAMP_VOLUME(volume_limit);
+ u->volume_step = PA_CLAMP_VOLUME(volume_step);
- if ((u->fd = open(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY)) < 0) {
- pa_log("failed to open evdev device: %s", pa_cstrerror(errno));
+ if ((u->fd = pa_open_cloexec(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY, 0)) < 0) {
+ pa_log("Failed to open evdev device: %s", pa_cstrerror(errno));
goto fail;
}
pa_log_info("evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff);
- if(ioctl(u->fd, EVIOCGID, &input_id)) {
+ if (ioctl(u->fd, EVIOCGID, &input_id)) {
pa_log("EVIOCGID failed: %s", pa_cstrerror(errno));
goto fail;
}
input_id.vendor, input_id.product, input_id.version, input_id.bustype);
memset(name, 0, sizeof(name));
- if(ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
+ if (ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
pa_log("EVIOCGNAME failed: %s", pa_cstrerror(errno));
goto fail;
}