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
|
@ -88,10 +88,6 @@ static void koto_playerbar_constructed(GObject *obj) {
|
|||
gtk_range_set_increments(GTK_RANGE(self->progress_bar), 1, 1);
|
||||
gtk_range_set_round_digits(GTK_RANGE(self->progress_bar), 1);
|
||||
|
||||
GtkEventController *scroll_controller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_HORIZONTAL);
|
||||
g_signal_connect(scroll_controller, "scroll-begin", G_CALLBACK(koto_playerbar_handle_progressbar_scroll_begin), self);
|
||||
gtk_widget_add_controller(GTK_WIDGET(self->progress_bar), scroll_controller);
|
||||
|
||||
GtkGesture *press_controller = gtk_gesture_click_new(); // Create a new GtkGestureLongPress
|
||||
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(press_controller), 1); // Set to left click
|
||||
|
||||
|
@ -241,7 +237,6 @@ void koto_playerbar_create_secondary_controls(KotoPlayerBar* bar) {
|
|||
if (GTK_IS_VOLUME_BUTTON(bar->volume_button)) {
|
||||
GtkAdjustment *granular_volume_change = gtk_adjustment_new(0.5, 0, 1.0, 0.02, 0.02, 0.02);
|
||||
g_object_set(bar->volume_button, "use-symbolic", TRUE, NULL);
|
||||
gtk_range_set_round_digits(GTK_RANGE(bar->volume_button), FALSE);
|
||||
gtk_scale_button_set_adjustment(GTK_SCALE_BUTTON(bar->volume_button), granular_volume_change); // Set our adjustment
|
||||
gtk_box_append(GTK_BOX(bar->secondary_controls_section), bar->volume_button);
|
||||
|
||||
|
@ -290,10 +285,6 @@ void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_d
|
|||
koto_button_show_image(bar->play_pause_button, FALSE); // Set to FALSE to show play as the next action
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_progressbar_scroll_begin(GtkEventControllerScroll *controller, gpointer data){
|
||||
(void) controller;
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
||||
(void) gesture; (void) seq;
|
||||
KotoPlayerBar *bar = data;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <gstreamer-1.0/gst/gst.h>
|
||||
#include "db/cartographer.h"
|
||||
#include "db/db.h"
|
||||
#include "playback/media-keys.h"
|
||||
#include "playback/mimes.h"
|
||||
#include "playback/mpris.h"
|
||||
|
||||
|
@ -43,6 +44,8 @@ static void on_activate (GtkApplication *app) {
|
|||
main_window = gtk_application_get_active_window (app);
|
||||
if (main_window == NULL) {
|
||||
main_window = g_object_new(KOTO_TYPE_WINDOW, "application", app, "default-width", 1200, "default-height", 675, NULL);
|
||||
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
||||
setup_mediakeys_interface(); // Set up our media key support
|
||||
}
|
||||
|
||||
gtk_window_present(main_window);
|
||||
|
@ -72,7 +75,6 @@ int main (int argc, char *argv[]) {
|
|||
|
||||
koto_maps = koto_cartographer_new(); // Create our new cartographer and their collection of maps
|
||||
open_db(); // Open our database
|
||||
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
||||
|
||||
app = gtk_application_new ("com.github.joshstrobl.koto", G_APPLICATION_FLAGS_NONE);
|
||||
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
||||
|
|
|
@ -12,6 +12,7 @@ koto_sources = [
|
|||
'pages/music/disc-view.c',
|
||||
'pages/music/music-local.c',
|
||||
'playback/engine.c',
|
||||
'playback/media-keys.c',
|
||||
'playback/mimes.c',
|
||||
'playback/mpris.c',
|
||||
'playlist/current.c',
|
||||
|
|
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