From eb5b6d233740a155b50f9b998af2e02f2afd004b Mon Sep 17 00:00:00 2001 From: Saturnino Luz Date: Mon, 26 Apr 2021 23:59:06 +0100 Subject: [PATCH] Added mic mute/unmute show feature --- README.md | 9 +++ res/Makefile.am | 3 +- res/mic_muted.svg | 125 ++++++++++++++++++++++++++++++++++++++++ res/mic_on.svg | 81 ++++++++++++++++++++++++++ src/client.c | 13 +++-- src/common.h | 3 + src/daemon.c | 47 +++++++++++---- src/specs.xml | 2 +- src/value-client-stub.h | 26 +++------ src/value-daemon-stub.h | 71 +++++++++++------------ 10 files changed, 307 insertions(+), 73 deletions(-) create mode 100644 res/mic_muted.svg create mode 100644 res/mic_on.svg diff --git a/README.md b/README.md index cc86677..9918c26 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,16 @@ to show a notification for volume level 25%. To show a notification for muted sound, call: $ volnoti-show -m + +To show a notification for muted microphone, call: + + $ volnoti-show -c + +To show a notification for un-muted microphone, call: + $ volnoti-show -u + + The best way to do this is to create simple script and attach it to the hot-keys on your keyboard. But this depends on your window manager and system configuration. diff --git a/res/Makefile.am b/res/Makefile.am index 10394d1..9f594d2 100644 --- a/res/Makefile.am +++ b/res/Makefile.am @@ -1,7 +1,8 @@ datadir = $(datarootdir)/pixmaps/@PACKAGE@/ ICONS = progressbar_empty.png progressbar_full.png \ volume_high.svg volume_medium.svg \ - volume_low.svg volume_off.svg volume_muted.svg + volume_low.svg volume_off.svg volume_muted.svg \ + mic_muted.svg mic_on.svg data_DATA = $(ICONS) EXTRA_DIST = $(ICONS) diff --git a/res/mic_muted.svg b/res/mic_muted.svg new file mode 100644 index 0000000..135c331 --- /dev/null +++ b/res/mic_muted.svg @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/res/mic_on.svg b/res/mic_on.svg new file mode 100644 index 0000000..9680026 --- /dev/null +++ b/res/mic_on.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + diff --git a/src/client.c b/src/client.c index a073fb8..be2370e 100644 --- a/src/client.c +++ b/src/client.c @@ -31,7 +31,9 @@ static void print_usage(const char* filename, int failure) { g_print("Usage: %s [-v] [-m] \n" " -h\t--help\t\thelp\n" " -v\t--verbose\tverbose\n" - " -m\t--mute\t\tmuted\n" + " -m\t--mute\tvolume muted\n" + " -c\t--micmute\tmicrophone muted\n" + " -u\t--micunmute\tmicrophone unmuted\n" " \t\tint 0-100\n", filename); if (failure) exit(EXIT_FAILURE); @@ -43,17 +45,20 @@ int main(int argc, const char* argv[]) { void *options = gopt_sort(&argc, argv, gopt_start( gopt_option('h', 0, gopt_shorts('h', '?'), gopt_longs("help", "HELP")), gopt_option('m', 0, gopt_shorts('m'), gopt_longs("mute")), + gopt_option('c', 0, gopt_shorts('c'), gopt_longs("micmute")), + gopt_option('u', 0, gopt_shorts('u'), gopt_longs("micunmute")), gopt_option('v', GOPT_REPEAT, gopt_shorts('v'), gopt_longs("verbose")))); int help = gopt(options, 'h'); int debug = gopt(options, 'v'); - int muted = gopt(options, 'm'); + int muted = gopt(options, 'm')? 1 : gopt(options, 'c') ? 2 : gopt(options, 'u') ? 3 : 0; + gopt_free(options); if (help) print_usage(argv[0], FALSE); gint volume; - if (muted) { + if (muted ) { if (argc > 2) { print_usage(argv[0], TRUE); } else if (argc == 2) { @@ -105,7 +110,7 @@ int main(int argc, const char* argv[]) { print_debug_ok(debug); print_debug("Sending volume...", debug); - uk_ac_cam_db538_VolumeNotification_notify(proxy, volume, muted, &error); + uk_ac_cam_db538_VolumeNotification_notify(proxy, volume, muted , &error); if (error != NULL) { handle_error("Failed to send notification", error->message, FALSE); g_clear_error(&error); diff --git a/src/common.h b/src/common.h index 933f714..7cdc0e8 100644 --- a/src/common.h +++ b/src/common.h @@ -24,6 +24,9 @@ /* And we're interested in using it through this interface. This must match the entry in the interface definition XML. */ #define VALUE_SERVICE_INTERFACE "uk.ac.cam.db538.VolumeNotification" +#define VOL_MUTED 1 +#define MIC_MUTED 2 +#define MIC_UNMUTED 3 void handle_error(const char* msg, const char* reason, gboolean fatal); void print_debug(const gchar *msg, int debug); diff --git a/src/daemon.c b/src/daemon.c index b530fa4..b9be677 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -32,6 +32,8 @@ typedef struct { gint volume; gboolean muted; + gboolean micmuted; + gboolean micunmuted; GtkWindow *notification; @@ -40,6 +42,8 @@ typedef struct { GdkPixbuf *icon_low; GdkPixbuf *icon_off; GdkPixbuf *icon_muted; + GdkPixbuf *icon_micon; + GdkPixbuf *icon_micmuted; GdkPixbuf *image_progressbar_empty; GdkPixbuf *image_progressbar_full; @@ -60,7 +64,7 @@ typedef struct { GType volume_object_get_type(void); gboolean volume_object_notify(VolumeObject* obj, gint value_in, - gboolean muted, + int muted, GError** error); #define VOLUME_TYPE_OBJECT \ @@ -117,15 +121,28 @@ time_handler(VolumeObject *obj) gboolean volume_object_notify(VolumeObject* obj, gint value, - gboolean muted, + int muted, GError** error) { g_assert(obj != NULL); - if (muted) { - obj->muted = TRUE; + if (muted == VOL_MUTED) { + obj->muted = TRUE; + obj->micmuted = FALSE; + obj->micunmuted = FALSE; + } else if ( muted == MIC_MUTED ) { + obj->muted = FALSE; + obj->micunmuted = FALSE; + obj->micmuted = TRUE; + } else if ( muted == MIC_UNMUTED ) { + obj->muted = FALSE; + obj->micunmuted = TRUE; + obj->micmuted = FALSE; } else { - obj->muted = FALSE; + obj->muted = FALSE; + obj->micmuted = FALSE; + obj->micunmuted = FALSE; } + obj->volume = (value > 100) ? 100 : value; if (obj->notification == NULL) { @@ -139,14 +156,18 @@ gboolean volume_object_notify(VolumeObject* obj, // choose icon if (obj->muted) set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_muted); + else if (obj->micmuted) + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_micmuted); + else if (obj->micunmuted) + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_micon); else if (obj->volume >= 75) - set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_high); + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_high); else if (obj->volume >= 50) - set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_medium); + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_medium); else if (obj->volume >= 25) - set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_low); + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_low); else - set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_off); + set_notification_icon(GTK_WINDOW(obj->notification), obj->icon_off); // prepare and set progress bar gint width_full = obj->width_progressbar * obj->volume / 100; @@ -304,7 +325,13 @@ int main(int argc, char* argv[]) { status->icon_muted = gdk_pixbuf_new_from_file(IMAGE_PATH "volume_muted.svg", &error); if (error != NULL) handle_error("Couldn't load volume_muted.svg.", error->message, TRUE); - + status->icon_micmuted = gdk_pixbuf_new_from_file(IMAGE_PATH "mic_muted.svg", &error); + if (error != NULL) + handle_error("Couldn't load mic_muted.svg.", error->message, TRUE); + status->icon_micon = gdk_pixbuf_new_from_file(IMAGE_PATH "mic_on.svg", &error); + if (error != NULL) + handle_error("Couldn't load mic_on.svg.", error->message, TRUE); + // progress bar status->image_progressbar_empty = gdk_pixbuf_new_from_file(IMAGE_PATH "progressbar_empty.png", &error); if (error != NULL) diff --git a/src/specs.xml b/src/specs.xml index cf061fc..53a81e2 100644 --- a/src/specs.xml +++ b/src/specs.xml @@ -4,7 +4,7 @@ - + diff --git a/src/value-client-stub.h b/src/value-client-stub.h index 3c820b9..77a17d1 100644 --- a/src/value-client-stub.h +++ b/src/value-client-stub.h @@ -7,11 +7,7 @@ G_BEGIN_DECLS #ifndef _DBUS_GLIB_ASYNC_DATA_FREE #define _DBUS_GLIB_ASYNC_DATA_FREE -static -#ifdef G_HAVE_INLINE -inline -#endif -void +static inline void _dbus_glib_async_data_free (gpointer stuff) { g_slice_free (DBusGAsyncData, stuff); @@ -21,15 +17,11 @@ _dbus_glib_async_data_free (gpointer stuff) #ifndef DBUS_GLIB_CLIENT_WRAPPERS_uk_ac_cam_db538_VolumeNotification #define DBUS_GLIB_CLIENT_WRAPPERS_uk_ac_cam_db538_VolumeNotification -static -#ifdef G_HAVE_INLINE -inline -#endif -gboolean -uk_ac_cam_db538_VolumeNotification_notify (DBusGProxy *proxy, const gint IN_volume, GError **error) +static inline gboolean +uk_ac_cam_db538_VolumeNotification_notify (DBusGProxy *proxy, const gint IN_volume, const gint IN_muted, GError **error) { - return dbus_g_proxy_call (proxy, "notify", error, G_TYPE_INT, IN_volume, G_TYPE_INVALID, G_TYPE_INVALID); + return dbus_g_proxy_call (proxy, "notify", error, G_TYPE_INT, IN_volume, G_TYPE_INT, IN_muted, G_TYPE_INVALID, G_TYPE_INVALID); } typedef void (*uk_ac_cam_db538_VolumeNotification_notify_reply) (DBusGProxy *proxy, GError *error, gpointer userdata); @@ -44,19 +36,15 @@ uk_ac_cam_db538_VolumeNotification_notify_async_callback (DBusGProxy *proxy, DBu return; } -static -#ifdef G_HAVE_INLINE -inline -#endif -DBusGProxyCall* -uk_ac_cam_db538_VolumeNotification_notify_async (DBusGProxy *proxy, const gint IN_volume, uk_ac_cam_db538_VolumeNotification_notify_reply callback, gpointer userdata) +static inline DBusGProxyCall* +uk_ac_cam_db538_VolumeNotification_notify_async (DBusGProxy *proxy, const gint IN_volume, const gint IN_muted, uk_ac_cam_db538_VolumeNotification_notify_reply callback, gpointer userdata) { DBusGAsyncData *stuff; stuff = g_slice_new (DBusGAsyncData); stuff->cb = G_CALLBACK (callback); stuff->userdata = userdata; - return dbus_g_proxy_begin_call (proxy, "notify", uk_ac_cam_db538_VolumeNotification_notify_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_INT, IN_volume, G_TYPE_INVALID); + return dbus_g_proxy_begin_call (proxy, "notify", uk_ac_cam_db538_VolumeNotification_notify_async_callback, stuff, _dbus_glib_async_data_free, G_TYPE_INT, IN_volume, G_TYPE_INT, IN_muted, G_TYPE_INVALID); } #endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_uk_ac_cam_db538_VolumeNotification */ diff --git a/src/value-daemon-stub.h b/src/value-daemon-stub.h index 39efb57..56a3020 100644 --- a/src/value-daemon-stub.h +++ b/src/value-daemon-stub.h @@ -1,16 +1,11 @@ /* Generated by dbus-binding-tool; do not edit! */ - -#ifndef __dbus_glib_marshal_volume_object_MARSHAL_H__ -#define __dbus_glib_marshal_volume_object_MARSHAL_H__ - -#include - -G_BEGIN_DECLS +/* This file is generated by glib-genmarshal, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */ +#include #ifdef G_ENABLE_DEBUG #define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) +#define g_marshal_value_peek_char(v) g_value_get_schar (v) #define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) #define g_marshal_value_peek_int(v) g_value_get_int (v) #define g_marshal_value_peek_uint(v) g_value_get_uint (v) @@ -54,33 +49,36 @@ G_BEGIN_DECLS #define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer #endif /* !G_ENABLE_DEBUG */ - -/* BOOLEAN:INT,POINTER */ -extern void dbus_glib_marshal_volume_object_BOOLEAN__INT_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); +/* Prototype for -Wmissing-prototypes */ +G_BEGIN_DECLS +extern +void dbus_glib_marshal_volume_object_BOOLEAN__INT_INT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +G_END_DECLS void -dbus_glib_marshal_volume_object_BOOLEAN__INT_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) +dbus_glib_marshal_volume_object_BOOLEAN__INT_INT_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) { - typedef gboolean (*GMarshalFunc_BOOLEAN__INT_POINTER) (gpointer data1, - gint arg_1, - gpointer arg_2, - gpointer data2); - register GMarshalFunc_BOOLEAN__INT_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; + typedef gboolean (*GMarshalFunc_BOOLEAN__INT_INT_POINTER) (gpointer data1, + gint arg1, + gint arg2, + gpointer arg3, + gpointer data2); + GCClosure *cc = (GCClosure *) closure; + gpointer data1, data2; + GMarshalFunc_BOOLEAN__INT_INT_POINTER callback; gboolean v_return; g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 3); + g_return_if_fail (n_param_values == 4); if (G_CCLOSURE_SWAP_DATA (closure)) { @@ -92,29 +90,26 @@ dbus_glib_marshal_volume_object_BOOLEAN__INT_POINTER (GClosure *closure, data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } - callback = (GMarshalFunc_BOOLEAN__INT_POINTER) (marshal_data ? marshal_data : cc->callback); + callback = (GMarshalFunc_BOOLEAN__INT_INT_POINTER) (marshal_data ? marshal_data : cc->callback); v_return = callback (data1, g_marshal_value_peek_int (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), + g_marshal_value_peek_int (param_values + 2), + g_marshal_value_peek_pointer (param_values + 3), data2); g_value_set_boolean (return_value, v_return); } -G_END_DECLS - -#endif /* __dbus_glib_marshal_volume_object_MARSHAL_H__ */ - #include static const DBusGMethodInfo dbus_glib_volume_object_methods[] = { - { (GCallback) volume_object_notify, dbus_glib_marshal_volume_object_BOOLEAN__INT_POINTER, 0 }, + { (GCallback) volume_object_notify, dbus_glib_marshal_volume_object_BOOLEAN__INT_INT_POINTER, 0 }, }; const DBusGObjectInfo dbus_glib_volume_object_object_info = { 1, dbus_glib_volume_object_methods, 1, -"uk.ac.cam.db538.VolumeNotification\0notify\0S\0volume\0I\0i\0\0\0", +"uk.ac.cam.db538.VolumeNotification\0notify\0S\0volume\0I\0i\0muted\0I\0i\0\0\0", "\0", "\0" };