Implement explicit functions for setting track repeat and shuffling in KotoPlaybackEngine.
Use these new functions as well as new signals to simplify toggle state in playerbar, as well as ensure changes over MPRIS allow for the updating of our UX. Implement method handlers and relevant setters for MPRIS support, as well as a koto_update_mpris_playback_state used to notify on state changes. Clean up some debugging.
This commit is contained in:
parent
07c3c00f1e
commit
43ebe6d041
7 changed files with 201 additions and 60 deletions
|
@ -132,6 +132,8 @@ static void koto_playerbar_constructed(GObject *obj) {
|
||||||
g_signal_connect(playback_engine, "tick-duration", G_CALLBACK(koto_playerbar_handle_tick_duration), self);
|
g_signal_connect(playback_engine, "tick-duration", G_CALLBACK(koto_playerbar_handle_tick_duration), self);
|
||||||
g_signal_connect(playback_engine, "tick-track", G_CALLBACK(koto_playerbar_handle_tick_track), self);
|
g_signal_connect(playback_engine, "tick-track", G_CALLBACK(koto_playerbar_handle_tick_track), self);
|
||||||
g_signal_connect(playback_engine, "track-changed", G_CALLBACK(koto_playerbar_update_track_info), self);
|
g_signal_connect(playback_engine, "track-changed", G_CALLBACK(koto_playerbar_update_track_info), self);
|
||||||
|
g_signal_connect(playback_engine, "track-repeat-changed", G_CALLBACK(koto_playerbar_handle_track_repeat), self);
|
||||||
|
g_signal_connect(playback_engine, "track-shuffle-changed", G_CALLBACK(koto_playerbar_handle_track_shuffle), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playerbar_init(KotoPlayerBar *self) {
|
static void koto_playerbar_init(KotoPlayerBar *self) {
|
||||||
|
@ -290,7 +292,6 @@ void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_d
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_scroll_begin(GtkEventControllerScroll *controller, gpointer data){
|
void koto_playerbar_handle_progressbar_scroll_begin(GtkEventControllerScroll *controller, gpointer data){
|
||||||
(void) controller;
|
(void) controller;
|
||||||
g_message("scroll-begin");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
||||||
|
@ -301,7 +302,6 @@ void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEve
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_message("Begin");
|
|
||||||
bar->is_progressbar_seeking = TRUE;
|
bar->is_progressbar_seeking = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,8 +309,6 @@ void koto_playerbar_handle_progressbar_gesture_end(GtkGesture *gesture, GdkEvent
|
||||||
(void) gesture; (void) seq;
|
(void) gesture; (void) seq;
|
||||||
KotoPlayerBar *bar = data;
|
KotoPlayerBar *bar = data;
|
||||||
|
|
||||||
g_message("Ended");
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -325,7 +323,6 @@ void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_message("Pressed");
|
|
||||||
bar->is_progressbar_seeking = TRUE;
|
bar->is_progressbar_seeking = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +339,6 @@ void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpo
|
||||||
|
|
||||||
int desired_position = (int) gtk_range_get_value(progress_bar);
|
int desired_position = (int) gtk_range_get_value(progress_bar);
|
||||||
|
|
||||||
g_message("value changed");
|
|
||||||
koto_playback_engine_set_position(playback_engine, desired_position); // Update our position
|
koto_playback_engine_set_position(playback_engine, desired_position); // Update our position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +373,42 @@ void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||||
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KotoPlayerBar *bar = user_data;
|
||||||
|
|
||||||
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (koto_playback_engine_get_track_repeat(engine)) { // Is repeating
|
||||||
|
gtk_widget_add_css_class(GTK_WIDGET(bar->repeat_button), "active"); // Add active CSS class
|
||||||
|
} else { // Is not repeating
|
||||||
|
gtk_widget_remove_css_class(GTK_WIDGET(bar->repeat_button), "active"); // Remove active CSS class
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||||
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KotoPlayerBar *bar = user_data;
|
||||||
|
|
||||||
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (koto_playback_engine_get_track_shuffle(engine)) { // Is repeating
|
||||||
|
gtk_widget_add_css_class(GTK_WIDGET(bar->shuffle_button), "active"); // Add active CSS class
|
||||||
|
} else { // Is not repeating
|
||||||
|
gtk_widget_remove_css_class(GTK_WIDGET(bar->shuffle_button), "active"); // Remove active CSS class
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data) {
|
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data) {
|
||||||
(void) button; (void) user_data;
|
(void) button; (void) user_data;
|
||||||
koto_playback_engine_set_volume(playback_engine, value);
|
koto_playback_engine_set_volume(playback_engine, value);
|
||||||
|
@ -409,38 +441,14 @@ void koto_playerbar_toggle_play_pause(GtkGestureClick *gesture, int n_press, dou
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_toggle_playlist_shuffle(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_playerbar_toggle_playlist_shuffle(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
||||||
KotoPlayerBar *bar = data;
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
koto_playback_engine_toggle_track_shuffle(playback_engine); // Call our playback engine's toggle track shuffle function
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(bar->shuffle_button), "active"); // Remove active state
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean currently_shuffling = FALSE;
|
|
||||||
g_object_get(playlist, "is-shuffle-enabled", ¤tly_shuffling, NULL); // Get the current is-shuffle-enabled
|
|
||||||
|
|
||||||
(currently_shuffling) ? gtk_widget_remove_css_class(GTK_WIDGET(bar->shuffle_button), "active") : gtk_widget_add_css_class(GTK_WIDGET(bar->shuffle_button), "active");
|
|
||||||
g_object_set(playlist, "is-shuffle-enabled", !currently_shuffling, NULL); // Provide inverse value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_toggle_track_repeat(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_playerbar_toggle_track_repeat(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
||||||
KotoPlayerBar *bar = data;
|
koto_playback_engine_toggle_track_repeat(playback_engine); // Call our playback engine's toggle track repeat function
|
||||||
|
|
||||||
if (koto_playback_engine_get_track_repeat(playback_engine)) { // Toggled on at the moment
|
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(bar->repeat_button), "active"); // Remove active CSS class
|
|
||||||
} else {
|
|
||||||
gtk_widget_add_css_class(GTK_WIDGET(bar->repeat_button), "active"); // Add active CSS class
|
|
||||||
}
|
|
||||||
|
|
||||||
koto_playback_engine_toggle_track_repeat(playback_engine); // Toggle the state
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_data) {
|
void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||||
|
|
|
@ -42,6 +42,8 @@ void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_p
|
||||||
void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpointer data);
|
void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpointer data);
|
||||||
void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer user_data);
|
void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer user_data);
|
||||||
void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_data);
|
void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_data);
|
||||||
|
void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer user_data);
|
||||||
|
void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer user_data);
|
||||||
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data);
|
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data);
|
||||||
void koto_playerbar_reset_progressbar(KotoPlayerBar* bar);
|
void koto_playerbar_reset_progressbar(KotoPlayerBar* bar);
|
||||||
void koto_playerbar_set_progressbar_duration(KotoPlayerBar* bar, gint64 duration);
|
void koto_playerbar_set_progressbar_duration(KotoPlayerBar* bar, gint64 duration);
|
||||||
|
|
|
@ -70,19 +70,10 @@ int main (int argc, char *argv[]) {
|
||||||
supported_mimes = NULL; // Ensure our mimes GList is initialized
|
supported_mimes = NULL; // Ensure our mimes GList is initialized
|
||||||
koto_playback_engine_get_supported_mimetypes(supported_mimes);
|
koto_playback_engine_get_supported_mimetypes(supported_mimes);
|
||||||
|
|
||||||
g_message("Length: %d", g_list_length(supported_mimes));
|
|
||||||
|
|
||||||
koto_maps = koto_cartographer_new(); // Create our new cartographer and their collection of maps
|
koto_maps = koto_cartographer_new(); // Create our new cartographer and their collection of maps
|
||||||
open_db(); // Open our database
|
open_db(); // Open our database
|
||||||
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
||||||
|
|
||||||
GList *md;
|
|
||||||
md = NULL;
|
|
||||||
for (md = supported_mimes; md != NULL; md = md->next) {
|
|
||||||
g_message("Mimetype: %s", (gchar*) md->data);
|
|
||||||
}
|
|
||||||
g_list_free(md);
|
|
||||||
|
|
||||||
app = gtk_application_new ("com.github.joshstrobl.koto", G_APPLICATION_FLAGS_NONE);
|
app = gtk_application_new ("com.github.joshstrobl.koto", G_APPLICATION_FLAGS_NONE);
|
||||||
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
||||||
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), NULL);
|
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), NULL);
|
||||||
|
|
|
@ -31,6 +31,8 @@ enum {
|
||||||
SIGNAL_TICK_DURATION,
|
SIGNAL_TICK_DURATION,
|
||||||
SIGNAL_TICK_TRACK,
|
SIGNAL_TICK_TRACK,
|
||||||
SIGNAL_TRACK_CHANGE,
|
SIGNAL_TRACK_CHANGE,
|
||||||
|
SIGNAL_TRACK_REPEAT_CHANGE,
|
||||||
|
SIGNAL_TRACK_SHUFFLE_CHANGE,
|
||||||
N_SIGNALS
|
N_SIGNALS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ struct _KotoPlaybackEngineClass {
|
||||||
void (* tick_duration) (KotoPlaybackEngine *engine);
|
void (* tick_duration) (KotoPlaybackEngine *engine);
|
||||||
void (* tick_track) (KotoPlaybackEngine *engine);
|
void (* tick_track) (KotoPlaybackEngine *engine);
|
||||||
void (* track_changed) (KotoPlaybackEngine *engine);
|
void (* track_changed) (KotoPlaybackEngine *engine);
|
||||||
|
void (* track_repeat_changed) (KotoPlaybackEngine *engine);
|
||||||
|
void (* track_shuffle_changed) (KotoPlaybackEngine *engine);
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPlaybackEngine, koto_playback_engine, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoPlaybackEngine, koto_playback_engine, G_TYPE_OBJECT);
|
||||||
|
@ -153,6 +157,30 @@ static void koto_playback_engine_class_init(KotoPlaybackEngineClass *c) {
|
||||||
G_TYPE_NONE,
|
G_TYPE_NONE,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
playback_engine_signals[SIGNAL_TRACK_REPEAT_CHANGE] = g_signal_new(
|
||||||
|
"track-repeat-changed",
|
||||||
|
G_TYPE_FROM_CLASS(gobject_class),
|
||||||
|
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||||||
|
G_STRUCT_OFFSET(KotoPlaybackEngineClass, track_repeat_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
playback_engine_signals[SIGNAL_TRACK_SHUFFLE_CHANGE] = g_signal_new(
|
||||||
|
"track-shuffle-changed",
|
||||||
|
G_TYPE_FROM_CLASS(gobject_class),
|
||||||
|
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||||||
|
G_STRUCT_OFFSET(KotoPlaybackEngineClass, track_shuffle_changed),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_TYPE_NONE,
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playback_engine_init(KotoPlaybackEngine *self) {
|
static void koto_playback_engine_init(KotoPlaybackEngine *self) {
|
||||||
|
@ -255,6 +283,20 @@ gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine *self) {
|
||||||
return self->is_repeat_enabled;
|
return self->is_repeat_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine *self) {
|
||||||
|
(void) self;
|
||||||
|
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||||
|
|
||||||
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean currently_shuffling = FALSE;
|
||||||
|
g_object_get(playlist, "is-shuffle-enabled", ¤tly_shuffling, NULL); // Get the current is-shuffle-enabled
|
||||||
|
|
||||||
|
return currently_shuffling;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data) {
|
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data) {
|
||||||
(void) bus;
|
(void) bus;
|
||||||
KotoPlaybackEngine *self = user_data;
|
KotoPlaybackEngine *self = user_data;
|
||||||
|
@ -308,19 +350,34 @@ void koto_playback_engine_play(KotoPlaybackEngine *self) {
|
||||||
self->tick_track_timer_running = TRUE;
|
self->tick_track_timer_running = TRUE;
|
||||||
g_timeout_add(100, koto_playback_engine_tick_track, self); // Create a 100ms track tick
|
g_timeout_add(100, koto_playback_engine_tick_track, self); // Create a 100ms track tick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
koto_update_mpris_playback_state(GST_STATE_PLAYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_pause(KotoPlaybackEngine *self) {
|
void koto_playback_engine_pause(KotoPlaybackEngine *self) {
|
||||||
self->is_playing = FALSE;
|
self->is_playing = FALSE;
|
||||||
gst_element_change_state(self->player, GST_STATE_CHANGE_PLAYING_TO_PAUSED);
|
gst_element_change_state(self->player, GST_STATE_CHANGE_PLAYING_TO_PAUSED);
|
||||||
|
koto_update_mpris_playback_state(GST_STATE_PAUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position) {
|
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position) {
|
||||||
gst_element_seek_simple(self->playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position * NS);
|
gst_element_seek_simple(self->playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position * NS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable) {
|
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable_repeat) {
|
||||||
self->is_repeat_enabled = enable;
|
self->is_repeat_enabled = enable_repeat;
|
||||||
|
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_REPEAT_CHANGE], 0); // Emit our track repeat changed event
|
||||||
|
}
|
||||||
|
|
||||||
|
void koto_playback_engine_set_track_shuffle(KotoPlaybackEngine *self, gboolean enable_shuffle) {
|
||||||
|
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||||
|
|
||||||
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set(playlist, "is-shuffle-enabled", enable_shuffle, NULL); // Set the is-shuffle-enabled on any existing playlist
|
||||||
|
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_SHUFFLE_CHANGE], 0); // Emit our track shuffle changed event
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid) {
|
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid) {
|
||||||
|
@ -370,6 +427,7 @@ void koto_playback_engine_stop(KotoPlaybackEngine *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_pad_set_offset(pad, 0); // Change offset
|
gst_pad_set_offset(pad, 0); // Change offset
|
||||||
|
koto_update_mpris_playback_state(GST_STATE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_toggle(KotoPlaybackEngine *self) {
|
void koto_playback_engine_toggle(KotoPlaybackEngine *self) {
|
||||||
|
@ -405,7 +463,11 @@ gboolean koto_playback_engine_tick_track(gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self) {
|
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self) {
|
||||||
self->is_repeat_enabled = !self->is_repeat_enabled;
|
koto_playback_engine_set_track_repeat(self, !self->is_repeat_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine *self) {
|
||||||
|
koto_playback_engine_set_track_shuffle(self, !koto_playback_engine_get_track_shuffle(self)); // Invert the currently shuffling vale
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaybackEngine* koto_playback_engine_new() {
|
KotoPlaybackEngine* koto_playback_engine_new() {
|
||||||
|
|
|
@ -50,17 +50,20 @@ gint64 koto_playback_engine_get_duration(KotoPlaybackEngine *self);
|
||||||
GstState koto_playback_engine_get_state(KotoPlaybackEngine *self);
|
GstState koto_playback_engine_get_state(KotoPlaybackEngine *self);
|
||||||
gint64 koto_playback_engine_get_progress(KotoPlaybackEngine *self);
|
gint64 koto_playback_engine_get_progress(KotoPlaybackEngine *self);
|
||||||
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine *self);
|
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine *self);
|
||||||
|
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_mute(KotoPlaybackEngine *self);
|
void koto_playback_engine_mute(KotoPlaybackEngine *self);
|
||||||
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data);
|
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data);
|
||||||
void koto_playback_engine_pause(KotoPlaybackEngine *self);
|
void koto_playback_engine_pause(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_play(KotoPlaybackEngine *self);
|
void koto_playback_engine_play(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_toggle(KotoPlaybackEngine *self);
|
void koto_playback_engine_toggle(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position);
|
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position);
|
||||||
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable);
|
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable_repeat);
|
||||||
|
void koto_playback_engine_set_track_shuffle(KotoPlaybackEngine *self, gboolean enable_shuffle);
|
||||||
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid);
|
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid);
|
||||||
void koto_playback_engine_set_volume(KotoPlaybackEngine *self, gdouble volume);
|
void koto_playback_engine_set_volume(KotoPlaybackEngine *self, gdouble volume);
|
||||||
void koto_playback_engine_stop(KotoPlaybackEngine *self);
|
void koto_playback_engine_stop(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self);
|
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self);
|
||||||
|
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine *self);
|
||||||
void koto_playback_engine_update_duration(KotoPlaybackEngine *self);
|
void koto_playback_engine_update_duration(KotoPlaybackEngine *self);
|
||||||
|
|
||||||
gboolean koto_playback_engine_tick_duration(gpointer user_data);
|
gboolean koto_playback_engine_tick_duration(gpointer user_data);
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
#include "../db/cartographer.h"
|
#include "../db/cartographer.h"
|
||||||
#include "../playlist/current.h"
|
#include "../playlist/current.h"
|
||||||
#include "../playlist/playlist.h"
|
#include "../playlist/playlist.h"
|
||||||
#include "mimes.h"
|
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "mimes.h"
|
||||||
|
#include "mpris.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer *koto_maps;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist *current_playlist;
|
||||||
|
@ -82,7 +83,7 @@ static const gchar introspection_xml[] =
|
||||||
" </interface>"
|
" </interface>"
|
||||||
"</node>";
|
"</node>";
|
||||||
|
|
||||||
void handle_main_mpris_method_call(
|
void handle_method_call(
|
||||||
GDBusConnection *connection,
|
GDBusConnection *connection,
|
||||||
const gchar *sender,
|
const gchar *sender,
|
||||||
const gchar *object_path,
|
const gchar *object_path,
|
||||||
|
@ -92,6 +93,8 @@ void handle_main_mpris_method_call(
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
) {
|
) {
|
||||||
|
(void) connection; (void) sender; (void) object_path; (void) invocation; (void) user_data;
|
||||||
|
|
||||||
if (g_strcmp0(interface_name, "org.mpris.MediaPlayer2") == 0) { // Root mediaplayer2 interface
|
if (g_strcmp0(interface_name, "org.mpris.MediaPlayer2") == 0) { // Root mediaplayer2 interface
|
||||||
if (g_strcmp0(method_name, "Raise") == 0) { // Raise the window
|
if (g_strcmp0(method_name, "Raise") == 0) { // Raise the window
|
||||||
gtk_window_unminimize(main_window); // Ensure we unminimize the window
|
gtk_window_unminimize(main_window); // Ensure we unminimize the window
|
||||||
|
@ -103,7 +106,7 @@ void handle_main_mpris_method_call(
|
||||||
gtk_application_remove_window(app, main_window); // Remove the window, thereby closing the app
|
gtk_application_remove_window(app, main_window); // Remove the window, thereby closing the app
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (g_strcmp0(interface_name, "org.mpris.MediaPlayer2.koto") == 0) { // Root mediaplayer2 interface
|
} else if (g_strcmp0(interface_name, "org.mpris.MediaPlayer2.Player") == 0) { // Root mediaplayer2 interface
|
||||||
if (g_strcmp0(method_name, "Next") == 0) { // Next track
|
if (g_strcmp0(method_name, "Next") == 0) { // Next track
|
||||||
koto_playback_engine_forwards(playback_engine);
|
koto_playback_engine_forwards(playback_engine);
|
||||||
return;
|
return;
|
||||||
|
@ -113,6 +116,26 @@ void handle_main_mpris_method_call(
|
||||||
koto_playback_engine_backwards(playback_engine);
|
koto_playback_engine_backwards(playback_engine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(method_name, "Pause") == 0) { // Explicit pause
|
||||||
|
koto_playback_engine_pause(playback_engine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(method_name, "PlayPause") == 0) { // Explicit playpause
|
||||||
|
koto_playback_engine_toggle(playback_engine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(method_name, "Stop") == 0) { // Explicit stop
|
||||||
|
koto_playback_engine_stop(playback_engine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(method_name, "Play") == 0) { // Explicit play
|
||||||
|
koto_playback_engine_play(playback_engine);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,11 +148,10 @@ GVariant* handle_get_property(
|
||||||
GError **error,
|
GError **error,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
) {
|
) {
|
||||||
|
(void) connection; (void) sender; (void) object_path; (void) interface_name; (void) error; (void) user_data;
|
||||||
GVariant *ret;
|
GVariant *ret;
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
|
|
||||||
g_message("asking for %s", property_name);
|
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "CanQuit") == 0) { // If property is CanQuit
|
if (g_strcmp0(property_name, "CanQuit") == 0) { // If property is CanQuit
|
||||||
ret = g_variant_new_boolean(TRUE); // Allow quitting. You can escape Hotel California for now.
|
ret = g_variant_new_boolean(TRUE); // Allow quitting. You can escape Hotel California for now.
|
||||||
}
|
}
|
||||||
|
@ -190,13 +212,16 @@ GVariant* handle_get_property(
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(g_strcmp0(property_name, "CanPlay") == 0) ||
|
(g_strcmp0(property_name, "CanPlay") == 0) ||
|
||||||
(g_strcmp0(property_name, "CanPause") == 0) ||
|
(g_strcmp0(property_name, "CanPause") == 0)
|
||||||
(g_strcmp0(property_name, "CanSeek") == 0)
|
|
||||||
) {
|
) {
|
||||||
KotoIndexedTrack *current_track = koto_playback_engine_get_current_track(playback_engine);
|
KotoIndexedTrack *current_track = koto_playback_engine_get_current_track(playback_engine);
|
||||||
ret = g_variant_new_boolean(KOTO_IS_INDEXED_TRACK(current_track));
|
ret = g_variant_new_boolean(KOTO_IS_INDEXED_TRACK(current_track));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(property_name, "CanSeek") == 0) { // Can control position over mpris
|
||||||
|
ret = g_variant_new_boolean(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "CanGoNext") == 0) { // Can Go Next
|
if (g_strcmp0(property_name, "CanGoNext") == 0) { // Can Go Next
|
||||||
// TODO: Add some actual logic here
|
// TODO: Add some actual logic here
|
||||||
ret = g_variant_new_boolean(TRUE);
|
ret = g_variant_new_boolean(TRUE);
|
||||||
|
@ -226,6 +251,31 @@ GVariant* handle_get_property(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean handle_set_property(
|
||||||
|
GDBusConnection *connection,
|
||||||
|
const gchar *sender,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *property_name,
|
||||||
|
GVariant *value,
|
||||||
|
GError **error,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
(void) connection; (void) sender; (void) interface_name; (void) object_path; (void) error; (void) user_data;
|
||||||
|
|
||||||
|
if (g_strcmp0(property_name, "LoopStatus") == 0) { // Changing LoopStatus
|
||||||
|
koto_playback_engine_set_track_repeat(playback_engine, g_variant_get_boolean(value)); // Set the loop status state
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_strcmp0(property_name, "Shuffle") == 0) { // Changing Shuffle
|
||||||
|
koto_playback_engine_set_track_shuffle(playback_engine, g_variant_get_boolean(value)); // Set the shuffle state
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack *track) {
|
void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack *track) {
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
|
@ -266,9 +316,8 @@ void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack
|
||||||
|
|
||||||
g_variant_builder_add(builder, "{sv}", "mpris:trackid", g_variant_new_string(track_uuid));
|
g_variant_builder_add(builder, "{sv}", "mpris:trackid", g_variant_new_string(track_uuid));
|
||||||
|
|
||||||
g_message("Art path: %s", album_art_path);
|
|
||||||
if (g_strcmp0(album_art_path, "") != 0) { // Not empty
|
if (g_strcmp0(album_art_path, "") != 0) { // Not empty
|
||||||
album_art_path = g_strconcat("file://", album_art_path); // Prepend with file://
|
album_art_path = g_strconcat("file://", album_art_path, NULL); // Prepend with file://
|
||||||
g_variant_builder_add(builder, "{sv}", "mpris:artUrl", g_variant_new_string(album_art_path));
|
g_variant_builder_add(builder, "{sv}", "mpris:artUrl", g_variant_new_string(album_art_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +339,27 @@ void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack
|
||||||
g_variant_builder_add(builder, "{sv}", "xesam:trackNumber", g_variant_new_uint64(track_position));
|
g_variant_builder_add(builder, "{sv}", "xesam:trackNumber", g_variant_new_uint64(track_position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void koto_update_mpris_playback_state(GstState state) {
|
||||||
|
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||||
|
|
||||||
|
if (state == GST_STATE_PLAYING) {
|
||||||
|
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Playing"));
|
||||||
|
} else if (state == GST_STATE_PAUSED) {
|
||||||
|
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Paused"));
|
||||||
|
} else {
|
||||||
|
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Stopped"));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_connection_emit_signal(dbus_conn,
|
||||||
|
NULL,
|
||||||
|
"/org/mpris/MediaPlayer2",
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"PropertiesChanged",
|
||||||
|
g_variant_new("(sa{sv}as)", "org.mpris.MediaPlayer2.Player", builder, NULL),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
|
@ -297,7 +367,6 @@ void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
||||||
|
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||||
GVariantBuilder *metadata_builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
|
GVariantBuilder *metadata_builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
koto_push_track_info_to_builder(metadata_builder, track);
|
koto_push_track_info_to_builder(metadata_builder, track);
|
||||||
GVariant *metadata_ret = g_variant_builder_end(metadata_builder);
|
GVariant *metadata_ret = g_variant_builder_end(metadata_builder);
|
||||||
|
@ -309,16 +378,18 @@ void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
||||||
"org.freedesktop.DBus.Properties",
|
"org.freedesktop.DBus.Properties",
|
||||||
"PropertiesChanged",
|
"PropertiesChanged",
|
||||||
g_variant_new("(sa{sv}as)", "org.mpris.MediaPlayer2.Player", builder, NULL),
|
g_variant_new("(sa{sv}as)", "org.mpris.MediaPlayer2.Player", builder, NULL),
|
||||||
&error
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GDBusInterfaceVTable main_mpris_interface_vtable = {
|
static const GDBusInterfaceVTable main_mpris_interface_vtable = {
|
||||||
handle_main_mpris_method_call,
|
handle_method_call,
|
||||||
handle_get_property,
|
handle_get_property,
|
||||||
|
handle_set_property,
|
||||||
};
|
};
|
||||||
|
|
||||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
||||||
|
(void) name; (void) user_data;
|
||||||
dbus_conn = connection;
|
dbus_conn = connection;
|
||||||
g_dbus_connection_register_object(dbus_conn,
|
g_dbus_connection_register_object(dbus_conn,
|
||||||
"/org/mpris/MediaPlayer2",
|
"/org/mpris/MediaPlayer2",
|
||||||
|
|
|
@ -17,11 +17,15 @@
|
||||||
|
|
||||||
#include <glib-2.0/glib.h>
|
#include <glib-2.0/glib.h>
|
||||||
#include <glib-2.0/gio/gio.h>
|
#include <glib-2.0/gio/gio.h>
|
||||||
|
#include <gstreamer-1.0/gst/gst.h>
|
||||||
|
#include <gstreamer-1.0/gst/player/player.h>
|
||||||
#include "../indexer/structs.h"
|
#include "../indexer/structs.h"
|
||||||
|
|
||||||
void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack *track);
|
void koto_push_track_info_to_builder(GVariantBuilder *builder, KotoIndexedTrack *track);
|
||||||
|
void koto_update_mpris_playback_state(GstState state);
|
||||||
void koto_update_mpris_info_for_track(KotoIndexedTrack *track);
|
void koto_update_mpris_info_for_track(KotoIndexedTrack *track);
|
||||||
void handle_main_mpris_method_call(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data);
|
void handle_method_call(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data);
|
||||||
GVariant* handle_get_property(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data);
|
GVariant* handle_get_property(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data);
|
||||||
|
gboolean handle_set_property(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data);
|
||||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
||||||
void setup_mpris_interfaces();
|
void setup_mpris_interfaces();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue