Implement GNOME Settings Daemon MediaKeys handling.

Clean up some warnings.
This commit is contained in:
Joshua Strobl 2021-04-06 15:35:01 +03:00
parent 43ebe6d041
commit e18b8ca100
5 changed files with 210 additions and 10 deletions

174
src/playback/media-keys.c Normal file
View file

@ -0,0 +1,174 @@
/* media-keys.c
*
* Copyright 2021 Joshua Strobl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <glib-2.0/glib.h>
#include <glib-2.0/gio/gio.h>
#include <gtk-4.0/gtk/gtk.h>
#include "engine.h"
#include "media-keys.h"
extern GtkWindow *main_window;
extern KotoPlaybackEngine *playback_engine;
GDBusConnection *media_keys_dbus_conn = NULL;
GDBusProxy *media_keys_proxy = NULL;
GDBusNodeInfo *media_keys_introspection_data = NULL;
static const gchar introspection_xml[] =
"<node name='/org/gnome/SettingsDaemon/MediaKeys'>"
" <interface name='org.gnome.SettingsDaemon.MediaKeys'>"
" <annotation name='org.freedesktop.DBus.GLib.CSymbol' value='gsd_media_keys_manager'/>"
" <method name='GrabMediaPlayerKeys'>"
" <arg name='application' direction='in' type='s'/>"
" <arg name='time' direction='in' type='u'/>"
" </method>"
" <method name='ReleaseMediaPlayerKeys'>"
" <arg name='application' direction='in' type='s'/>"
" </method>"
" <signal name='MediaPlayerKeyPressed'>"
" <arg name='application' type='s'/>"
" <arg name='key' type='s'/>"
" </signal>"
" </interface>"
"</node>";
void grab_media_keys() {
if (media_keys_proxy == NULL) { // No connection
return;
}
g_dbus_proxy_call(
media_keys_proxy,
"GrabMediaPlayerKeys",
g_variant_new("(su)", "com.github.joshstrobl.koto", 0),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
handle_media_keys_async_done,
NULL
);
}
void handle_media_keys_async_done(GObject *source_object, GAsyncResult *res, gpointer user_data) {
(void) user_data;
g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, NULL); // Ensure we finish our call
}
void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) {
(void) proxy; (void) sender_name; (void) user_data;
if (g_strcmp0(signal_name, "MediaPlayerKeyPressed") != 0) { // Not MediaPlayerKeyPressed
return;
}
gchar *application_name = NULL;
gchar *key = NULL;
g_variant_get(parameters, "(ss)", &application_name, &key);
if (g_strcmp0(application_name, "com.github.joshstrobl.koto") != 0) { // Not for Koto
return;
}
if (g_strcmp0(key, "Play") == 0) {
koto_playback_engine_play(playback_engine);
} else if (g_strcmp0(key, "Pause") == 0) {
koto_playback_engine_pause(playback_engine);
} else if (g_strcmp0(key, "Stop") == 0) {
koto_playback_engine_stop(playback_engine);
} else if (g_strcmp0(key, "Previous") == 0) {
koto_playback_engine_backwards(playback_engine);
} else if (g_strcmp0(key, "Next") == 0) {
koto_playback_engine_forwards(playback_engine);
} else if (g_strcmp0(key, "Repeat") == 0) {
koto_playback_engine_toggle_track_repeat(playback_engine);
} else if (g_strcmp0(key, "Shuffle") == 0) {
koto_playback_engine_toggle_track_shuffle(playback_engine);
}
}
void handle_window_enter(GtkEventControllerFocus *controller, gpointer user_data) {
grab_media_keys(); // Grab our media keys
}
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data) {
release_media_keys(); // Release our media keys
}
void release_media_keys() {
if (media_keys_dbus_conn == NULL) { // No connection
return;
}
GVariant *params = g_variant_new_string(g_strdup("com.github.joshstrobl.koto"));
g_dbus_proxy_call(
media_keys_proxy,
"ReleaseMediaPlayerKeys",
params,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
handle_media_keys_async_done,
NULL
);
}
void setup_mediakeys_interface() {
media_keys_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
g_assert(media_keys_introspection_data != NULL);
GDBusConnection *bus;
GError *error = NULL;
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (bus == NULL) { // Failed to get session bus
g_printerr("Failed to get our session bus: %s\n", error->message);
g_error_free(error);
return;
}
media_keys_proxy = g_dbus_proxy_new_sync(
bus,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.gnome.SettingsDaemon.MediaKeys",
"/org/gnome/SettingsDaemon/MediaKeys",
"org.gnome.SettingsDaemon.MediaKeys",
NULL,
&error
);
if (media_keys_proxy == NULL) {
g_printerr("Failed to get a proxy to GNOME Settings Daemon Media-Keys: %s\n", error->message);
g_error_free(error);
return;
}
g_signal_connect_object(
media_keys_proxy,
"g-signal",
G_CALLBACK(handle_media_keys_signal),
NULL,
0
);
GtkEventController *focus_controller = gtk_event_controller_focus_new(); // Create a new focus controller
g_signal_connect(focus_controller, "enter", G_CALLBACK(handle_window_enter), NULL);
g_signal_connect(focus_controller, "leave", G_CALLBACK(handle_window_leave), NULL);
gtk_widget_add_controller(GTK_WIDGET(main_window), focus_controller);
}

32
src/playback/media-keys.h Normal file
View file

@ -0,0 +1,32 @@
/* media-keys.h
*
* Copyright 2021 Joshua Strobl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <glib-2.0/glib.h>
#include <glib-2.0/gio/gio.h>
#include <gtk-4.0/gtk/gtk.h>
G_BEGIN_DECLS
void grab_media_keys();
void handle_media_keys_async_done(GObject *source_object, GAsyncResult *res, gpointer user_data);
void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data);
void handle_window_enter(GtkEventControllerFocus *controller, gpointer user_data);
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data);
void release_media_keys();
void setup_mediakeys_interface();
G_END_DECLS