Implement GNOME Settings Daemon MediaKeys handling.
Clean up some warnings.
This commit is contained in:
parent
43ebe6d041
commit
e18b8ca100
5 changed files with 210 additions and 10 deletions
174
src/playback/media-keys.c
Normal file
174
src/playback/media-keys.c
Normal 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
32
src/playback/media-keys.h
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue