From 7678aaab7a6db95c86d2104b363db2c3ffb91ab0 Mon Sep 17 00:00:00 2001
From: c4pp4
Date: Sat, 2 Nov 2024 23:49:47 +0100
Subject: [PATCH 1/1] Unity shortcuts plugin

Signed-off-by: c4pp4
---
 configure.ac                         |   8 +
 extra.mk.in                          |   2 +
 meson.build                          |   5 +
 meson_options.txt                    |   2 +
 src/meson.build                      |   4 +
 src/unityshortcuts/Makefile          |  13 ++
 src/unityshortcuts/meson.build       |   7 +
 src/unityshortcuts/unityshortcuts.cc | 295 +++++++++++++++++++++++++++
 8 files changed, 336 insertions(+)
 create mode 100644 src/unityshortcuts/Makefile
 create mode 100644 src/unityshortcuts/meson.build
 create mode 100644 src/unityshortcuts/unityshortcuts.cc

diff --git a/configure.ac b/configure.ac
index 8309684..b43938e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -441,6 +441,13 @@ ENABLE_PLUGIN_WITH_DEP(mms,
     MMS,
     libmms >= 0.3)
 
+ENABLE_PLUGIN_WITH_DEP(unityshortcuts,
+    Unity shortcuts,
+    auto,
+    GENERAL,
+    DBUS,
+    dbus-1 >= 0.60 dbus-glib-1 >= 0.60)
+
 ENABLE_PLUGIN_WITH_DEP(notify,
     libnotify OSD,
     auto,
@@ -853,6 +860,7 @@ echo "  General"
 echo "  -------"
 echo "  Ampache browser (requires Qt):          $have_ampache"
 echo "  Delete Files:                           $USE_GTK_OR_QT"
+echo "  Unity Shortcuts:                        $have_unityshortcuts"
 echo "  libnotify OSD:                          $have_notify"
 echo "  Linux Infrared Remote Control (LIRC):   $have_lirc"
 echo "  Lyrics Viewer:                          yes"
diff --git a/extra.mk.in b/extra.mk.in
index c702945..ff536b3 100644
--- a/extra.mk.in
+++ b/extra.mk.in
@@ -33,6 +33,8 @@ CUE_CFLAGS ?= @CUE_CFLAGS@
 CUE_LIBS ?= @CUE_LIBS@
 CURL_CFLAGS ?= @CURL_CFLAGS@
 CURL_LIBS ?= @CURL_LIBS@
+DBUS_CFLAGS ?= @DBUS_CFLAGS@
+DBUS_LIBS ?= @DBUS_LIBS@
 FFMPEG_CFLAGS ?= @FFMPEG_CFLAGS@
 FFMPEG_LIBS ?= @FFMPEG_LIBS@
 FILEWRITER_CFLAGS ?= @FILEWRITER_CFLAGS@
diff --git a/meson.build b/meson.build
index 0450b0b..093239f 100644
--- a/meson.build
+++ b/meson.build
@@ -54,6 +54,10 @@ audgui_dep = declare_dependency(link_args: [
 
 glib_req = '>= 2.32'
 glib_dep = dependency('glib-2.0', version: glib_req, required: true)
+dbus_req = '>= 0.60'
+dbus_dep = dependency('dbus-1', version: dbus_req, required: true)
+dbus_glib_req = '>= 0.60'
+dbus_glib_dep = dependency('dbus-glib-1', version: dbus_glib_req, required: true)
 gmodule_dep = dependency('gmodule-2.0', version: glib_req, required: true)
 zlib_dep = dependency('zlib', required: true)
 
@@ -299,6 +303,7 @@ if meson.version().version_compare('>= 0.53')
     'MPRIS 2 Server': get_variable('have_mpris2', false),
     'Scrobbler 2.0': get_variable('have_scrobbler2', false),
     'Song Change': get_option('songchange'),
+    'Unity Shortcuts': get_variable('have_unityshortcuts', true),
   }, section: 'General')
 
   if conf.has('USE_QT')
diff --git a/meson_options.txt b/meson_options.txt
index fbef006..84f4094 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -106,6 +106,8 @@ option('songchange', type: 'boolean', value: true,
        description: 'Whether the Song Change plugin is enabled')
 option('streamtuner', type: 'boolean', value: false,
        description: 'Whether the Stream Tuner plugin is enabled')
+option('unityshortcuts', type: 'boolean', value: true,
+       description: 'Whether the Unity Shortcuts plugin is enabled')
 
 
 # effect plugins
diff --git a/src/meson.build b/src/meson.build
index 50b7662..cff7db5 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -183,6 +183,10 @@ if get_option('songchange')
   subdir('songchange')
 endif
 
+if get_option('unityshortcuts')
+  subdir('unityshortcuts')
+endif
+
 
 # input plugins
 if get_option('aac')
diff --git a/src/unityshortcuts/Makefile b/src/unityshortcuts/Makefile
new file mode 100644
index 0000000..e67244e
--- /dev/null
+++ b/src/unityshortcuts/Makefile
@@ -0,0 +1,13 @@
+PLUGIN = unityshortcuts${PLUGIN_SUFFIX}
+
+SRCS = unityshortcuts.cc
+
+include ../../buildsys.mk
+include ../../extra.mk
+
+plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR}
+
+LD = ${CXX}
+CFLAGS += ${PLUGIN_CFLAGS}
+CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GLIB_CFLAGS} ${DBUS_CFLAGS} -I../.. -I..
+LIBS += ${GLIB_LIBS} ${DBUS_LIBS} ${GTK_LIBS}
diff --git a/src/unityshortcuts/meson.build b/src/unityshortcuts/meson.build
new file mode 100644
index 0000000..a700ac1
--- /dev/null
+++ b/src/unityshortcuts/meson.build
@@ -0,0 +1,7 @@
+shared_module('unityshortcuts',
+  'unityshortcuts.cc',
+  dependencies: [audacious_dep, gtk_dep, dbus_dep, dbus_glib_dep],
+  name_prefix: '',
+  install: true,
+  install_dir: general_plugin_dir
+)
diff --git a/src/unityshortcuts/unityshortcuts.cc b/src/unityshortcuts/unityshortcuts.cc
new file mode 100644
index 0000000..dc359f0
--- /dev/null
+++ b/src/unityshortcuts/unityshortcuts.cc
@@ -0,0 +1,295 @@
+/*
+ *  This file is part of audacious-unity-shortcut plugin for audacious
+ *
+ *  Copyright (c) 2007-2008    Sascha Hlusiak <contact@saschahlusiak.de>
+ *  Name: plugin.c
+ *  Description: plugin.c
+ *
+ *  audacious-unity-shortcut is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  audacious-unity-shortcut is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with audacious-unity-shortcut; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-bindings.h>
+#include <glib-object.h>
+
+#include <libaudcore/drct.h>
+#include <libaudcore/plugin.h>
+#include <libaudcore/i18n.h>
+
+class UnityShortcuts : public GeneralPlugin
+{
+public:
+    static const char about[];
+
+    static constexpr PluginInfo info = {
+        N_("Unity Shortcuts"),
+        PACKAGE,
+        about
+    };
+
+    constexpr UnityShortcuts () : GeneralPlugin (info, true) {}
+
+    bool init ();
+    void cleanup ();
+};
+
+EXPORT UnityShortcuts aud_plugin_instance;
+
+static DBusGProxy *media_player_keys_proxy = nullptr;
+
+const char UnityShortcuts::about[] =
+ N_("Unity Shortcuts Plugin\n"
+    "(former GNOME Shortcuts Plugin)\n"
+    "Lets you control the player with Unity's shortcuts.\n\n"
+    "Copyright (C) 2007-2008 Sascha Hlusiak <contact@saschahlusiak.de>");
+
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+
+
+static void
+hotkey_marshal_VOID__STRING_STRING (GClosure     *closure,
+                                    GValue       *return_value,
+                                    unsigned         n_param_values,
+                                    const GValue *param_values,
+                                    void *      invocation_hint,
+                                    void *      marshal_data)
+{
+    typedef void (*GMarshalFunc_VOID__STRING_STRING) (void * data1,
+                                                      void * arg_1,
+                                                      void * arg_2);
+    GMarshalFunc_VOID__STRING_STRING callback;
+    GCClosure *cc = (GCClosure*) closure;
+    void * data1;
+
+    g_return_if_fail (n_param_values == 3);
+
+    if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+        data1 = closure->data;
+    } else {
+        data1 = g_value_peek_pointer (param_values + 0);
+    }
+    callback = (GMarshalFunc_VOID__STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+    callback (data1,
+     g_marshal_value_peek_string (param_values + 1),
+     g_marshal_value_peek_string (param_values + 2));
+}
+
+static void
+on_media_player_key_pressed (DBusGProxy *proxy, const char *application, const char *key)
+{
+    if (strcmp ("Audacious", application) == 0) {
+        int current_volume /* , old_volume */ ;
+        static int volume_static = 0;
+        bool mute;
+
+        /* get current volume */
+        current_volume = aud_drct_get_volume_main ();
+        /* old_volume = current_volume; */
+        if (current_volume)
+        {
+            /* volume is not mute */
+            mute = false;
+        } else {
+            /* volume is mute */
+            mute = true;
+        }
+
+        /* mute the playback */
+        if (strcmp ("Mute", key) == 0)
+        {
+            if (!mute)
+            {
+                volume_static = current_volume;
+                aud_drct_set_volume_main (0);
+                mute = true;
+            } else {
+                aud_drct_set_volume_main (volume_static);
+                mute = false;
+            }
+            return;
+        }
+
+        /* decreace volume */
+/*      if ((keycode == plugin_cfg.vol_down) && (state == plugin_cfg.vol_down_mask))
+        {
+            if (mute)
+            {
+                current_volume = old_volume;
+                old_volume = 0;
+                mute = false;
+            }
+
+            if ((current_volume -= plugin_cfg.vol_decrement) < 0)
+            {
+                current_volume = 0;
+            }
+
+            if (current_volume != old_volume)
+            {
+                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
+                 current_volume);
+            }
+
+            old_volume = current_volume;
+            return true;
+        }*/
+
+        /* increase volume */
+/*      if ((keycode == plugin_cfg.vol_up) && (state == plugin_cfg.vol_up_mask))
+        {
+            if (mute)
+            {
+                current_volume = old_volume;
+                old_volume = 0;
+                mute = false;
+            }
+
+            if ((current_volume += plugin_cfg.vol_increment) > 100)
+            {
+                current_volume = 100;
+            }
+
+            if (current_volume != old_volume)
+            {
+                xmms_remote_set_main_volume (audacioushotkey.xmms_session,
+                 current_volume);
+            }
+
+            old_volume = current_volume;
+            return true;
+        }*/
+
+        /* play or pause */
+        if (strcmp ("Play", key) == 0 || strcmp ("Pause", key) == 0)
+        {
+            aud_drct_play_pause ();
+            return;
+        }
+
+        /* stop */
+        if (strcmp ("Stop", key) == 0)
+        {
+            aud_drct_stop ();
+            return;
+        }
+
+        /* prev track */
+        if (strcmp ("Previous", key) == 0)
+        {
+            aud_drct_pl_prev ();
+            return;
+        }
+
+        /* next track */
+        if (strcmp ("Next", key) == 0)
+        {
+            aud_drct_pl_next ();
+            return;
+        }
+    }
+}
+
+void UnityShortcuts::cleanup ()
+{
+    GError *error = nullptr;
+    if (media_player_keys_proxy == nullptr) return;
+
+    dbus_g_proxy_disconnect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+     G_CALLBACK (on_media_player_key_pressed), nullptr);
+
+    dbus_g_proxy_call (media_player_keys_proxy,
+     "ReleaseMediaPlayerKeys", &error,
+     G_TYPE_STRING, "Audacious",
+     G_TYPE_INVALID, G_TYPE_INVALID);
+    if (error != nullptr) {
+        g_warning ("Could not release media player keys: %s", error->message);
+        g_error_free (error);
+    }
+    g_object_unref(media_player_keys_proxy);
+    media_player_keys_proxy = nullptr;
+}
+
+bool UnityShortcuts::init ()
+{
+    DBusGConnection *bus;
+    GError *error = nullptr;
+    dbus_g_thread_init();
+
+    bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    if ((bus == nullptr) && error) {
+        g_warning ("Error connecting to DBus: %s", error->message);
+        g_error_free (error);
+        return false;
+    } else {
+        media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
+         "org.gnome.SettingsDaemon",
+         "/org/gnome/SettingsDaemon/MediaKeys",
+         "org.gnome.SettingsDaemon.MediaKeys");
+        if (media_player_keys_proxy == nullptr) {
+            media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
+             "org.gnome.SettingsDaemon.MediaKeys",
+             "/org/gnome/SettingsDaemon/MediaKeys",
+             "org.gnome.SettingsDaemon.MediaKeys");
+            if (media_player_keys_proxy == nullptr)
+                return false;
+        }
+
+        dbus_g_proxy_call (media_player_keys_proxy,
+         "GrabMediaPlayerKeys", &error,
+         G_TYPE_STRING, "Audacious",
+         G_TYPE_UINT, 0,
+         G_TYPE_INVALID,
+         G_TYPE_INVALID);
+        if (error != nullptr) {
+            g_error_free (error);
+            error = nullptr;
+            g_object_unref(media_player_keys_proxy);
+            media_player_keys_proxy = dbus_g_proxy_new_for_name (bus,
+             "org.gnome.SettingsDaemon",
+             "/org/gnome/SettingsDaemon",
+             "org.gnome.SettingsDaemon");
+            if (media_player_keys_proxy == nullptr)
+                return false;
+
+            dbus_g_proxy_call (media_player_keys_proxy,
+             "GrabMediaPlayerKeys", &error,
+             G_TYPE_STRING, "Audacious",
+             G_TYPE_UINT, 0,
+             G_TYPE_INVALID,
+             G_TYPE_INVALID);
+            if (error != nullptr) {
+                g_warning ("Could not grab media player keys: %s", error->message);
+                g_error_free (error);
+                g_object_unref(media_player_keys_proxy);
+                media_player_keys_proxy = nullptr;
+                return false;
+            }
+        }
+
+        dbus_g_object_register_marshaller (hotkey_marshal_VOID__STRING_STRING,
+         G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+        dbus_g_proxy_add_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+        dbus_g_proxy_connect_signal (media_player_keys_proxy, "MediaPlayerKeyPressed",
+         G_CALLBACK (on_media_player_key_pressed), nullptr, nullptr);
+
+        return true;
+    }
+}
-- 
2.45.2

