Implement double-click logic in our Track Table to immediately start playback of track and respective playlist.
Rewrote some legacy KotoCurrentPlaylist code that relied on communicating KotoPlaylist change via a property change. Changed to using a signal. Implemented new koto_album_create_playlist function so we can use our KotoPlaylist generation in the KotoActionBar. Prior to this change, clicking "Play" on a given track in a DiscView would only play that specific track and never give you the opportunity to go backwards or forwards. Now we will use our "continue on playlist" config to determine that behaviour and dynamically generate a playlist when the actionbar is relative to an Album. This functionality is leveraged with a change to koto_current_playlist_set_playlist that now requires a gboolean for determining if we should play immediately as well. Added type checks in our KotoPlayerbar progress / range usage. Prior to this change, you would get a (harmless) GLib Warning when closing the application. Fixed KotoPlayerbar info updating returning early when it failed to get an Album for a track, resulting in the artwork never being reset. Fixed multiple warnings when missing metadata and using g_variants in our koto_playback_set_track_by_uuid.
This commit is contained in:
parent
d8b71b8548
commit
ca4873e07f
13 changed files with 265 additions and 142 deletions
|
@ -18,7 +18,9 @@
|
|||
#include <glib-2.0/glib.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "koto-action-bar.h"
|
||||
#include "../config/config.h"
|
||||
#include "../db/cartographer.h"
|
||||
#include "../indexer/album-playlist-funcs.h"
|
||||
#include "../pages/music/music-local.h"
|
||||
#include "../playlist/add-remove-track-popover.h"
|
||||
#include "../playlist/current.h"
|
||||
|
@ -29,6 +31,7 @@
|
|||
|
||||
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup;
|
||||
extern KotoCartographer * koto_maps;
|
||||
extern KotoConfig * config;
|
||||
extern KotoCurrentPlaylist * current_playlist;
|
||||
extern KotoPageMusicLocal * music_local_page;
|
||||
extern KotoPlaybackEngine * playback_engine;
|
||||
|
@ -252,16 +255,26 @@ void koto_action_bar_handle_play_track_button_clicked(
|
|||
goto doclose;
|
||||
}
|
||||
|
||||
KotoPlaylist * playlist = NULL;
|
||||
|
||||
if (self->relative == KOTO_ACTION_BAR_IS_PLAYLIST_RELATIVE) { // Relative to a playlist
|
||||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->current_playlist_uuid);
|
||||
playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->current_playlist_uuid);
|
||||
} else if (self->relative == KOTO_ACTION_BAR_IS_ALBUM_RELATIVE) { // Relative to an Album
|
||||
KotoAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, self->current_album_uuid); // Get the Album
|
||||
|
||||
if (KOTO_IS_ALBUM(album)) { // Have an Album
|
||||
playlist = koto_album_create_playlist(album); // Create our playlist dynamically for the Album
|
||||
}
|
||||
}
|
||||
|
||||
if (KOTO_IS_PLAYLIST(playlist)) { // Is a playlist
|
||||
koto_current_playlist_set_playlist(current_playlist, playlist); // Update our playlist to the one associated with the track we are playing
|
||||
koto_current_playlist_set_playlist(current_playlist, playlist, FALSE); // Update our playlist to the one associated with the track we are playing
|
||||
koto_playlist_set_track_as_current(playlist, koto_track_get_uuid(track)); // Get this track as the current track in the position
|
||||
}
|
||||
}
|
||||
|
||||
koto_playback_engine_set_track_by_uuid(playback_engine, koto_track_get_uuid(track), TRUE); // Set the track to play
|
||||
gboolean continue_playback = FALSE;
|
||||
g_object_get(config, "playback-continue-on-playlist", &continue_playback, NULL);
|
||||
koto_playback_engine_set_track_by_uuid(playback_engine, koto_track_get_uuid(track), continue_playback); // Set the track to play
|
||||
|
||||
doclose:
|
||||
koto_action_bar_close(self);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <glib-2.0/glib.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../db/cartographer.h"
|
||||
#include "../playback/engine.h"
|
||||
#include "../playlist/current.h"
|
||||
#include "../playlist/playlist.h"
|
||||
#include "../koto-button.h"
|
||||
#include "../koto-utils.h"
|
||||
|
@ -27,6 +29,8 @@
|
|||
|
||||
extern KotoActionBar * action_bar;
|
||||
extern KotoCartographer * koto_maps;
|
||||
extern KotoCurrentPlaylist * current_playlist;
|
||||
extern KotoPlaybackEngine * playback_engine;
|
||||
extern KotoWindow * main_window;
|
||||
|
||||
struct _KotoTrackTable {
|
||||
|
@ -106,7 +110,8 @@ void koto_track_table_bind_track_item(
|
|||
) {
|
||||
(void) factory;
|
||||
|
||||
GtkWidget * track_position_label = gtk_widget_get_first_child(gtk_list_item_get_child(item));
|
||||
GtkWidget * box = gtk_list_item_get_child(item);
|
||||
GtkWidget * track_position_label = gtk_widget_get_first_child(box);
|
||||
GtkWidget * track_name_label = gtk_widget_get_next_sibling(track_position_label);
|
||||
GtkWidget * track_album_label = gtk_widget_get_next_sibling(track_name_label);
|
||||
GtkWidget * track_artist_label = gtk_widget_get_next_sibling(track_album_label);
|
||||
|
@ -150,6 +155,12 @@ void koto_track_table_bind_track_item(
|
|||
if (KOTO_IS_ARTIST(artist)) {
|
||||
gtk_label_set_label(GTK_LABEL(track_artist_label), koto_artist_get_name(artist)); // Get the name of the artist and set it to the label
|
||||
}
|
||||
|
||||
GList * data = NULL;
|
||||
data = g_list_append(data, self); // Reference self first
|
||||
data = g_list_append(data, koto_track_get_uuid(track)); // Next reference the track UUID string
|
||||
|
||||
g_object_set_data(G_OBJECT(box), "data", data); // Bind our list data
|
||||
}
|
||||
|
||||
void koto_track_table_create_tracks_header(KotoTrackTable * self) {
|
||||
|
@ -239,6 +250,45 @@ void koto_track_table_handle_track_artist_clicked(
|
|||
koto_track_table_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST);
|
||||
}
|
||||
|
||||
void koto_track_table_item_handle_clicked(
|
||||
GtkGesture * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) x;
|
||||
(void) y;
|
||||
|
||||
if (n_press != 2) { // Not a double click or tap
|
||||
return;
|
||||
}
|
||||
|
||||
GObject * track_item_as_object = G_OBJECT(user_data);
|
||||
|
||||
if (!G_IS_OBJECT(track_item_as_object)) { // Not a GObject
|
||||
return;
|
||||
}
|
||||
|
||||
GList * data = g_object_get_data(track_item_as_object, "data");
|
||||
|
||||
KotoTrackTable * self = g_list_nth_data(data, 0);
|
||||
gchar * track_uuid = g_list_nth_data(data, 1);
|
||||
|
||||
if (!koto_utils_is_string_valid(track_uuid)) { // Not a valid string
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_selection_model_unselect_all(self->selection_model);
|
||||
gtk_widget_grab_focus(GTK_WIDGET(main_window)); // Focus on the window
|
||||
koto_action_bar_toggle_reveal(action_bar, FALSE);
|
||||
koto_action_bar_close(action_bar); // Close the action bar
|
||||
koto_current_playlist_set_playlist(current_playlist, self->playlist, FALSE); // Set the current playlist to the artist's playlist but do not play immediately
|
||||
koto_playlist_set_track_as_current(self->playlist, track_uuid); // Set this track as the current one for the playlist
|
||||
koto_playback_engine_set_track_by_uuid(playback_engine, track_uuid, FALSE); // Tell our playback engine to start playing at this track
|
||||
}
|
||||
|
||||
void koto_track_table_handle_track_name_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
|
@ -476,6 +526,10 @@ void koto_track_table_setup_track_item(
|
|||
gtk_size_group_add_widget(self->track_artist_size_group, track_artist);
|
||||
|
||||
gtk_list_item_set_child(item, item_content);
|
||||
|
||||
GtkGesture * double_click_gesture = gtk_gesture_click_new(); // Create our new GtkGesture for double-click handling
|
||||
gtk_widget_add_controller(item_content, GTK_EVENT_CONTROLLER(double_click_gesture)); // Have our item handle double clicking
|
||||
g_signal_connect(double_click_gesture, "released", G_CALLBACK(koto_track_table_item_handle_clicked), item_content);
|
||||
}
|
||||
|
||||
KotoTrackTable * koto_track_table_new() {
|
||||
|
|
|
@ -73,6 +73,14 @@ void koto_track_table_handle_track_name_clicked(
|
|||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_track_table_handle_track_name_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_track_table_handle_track_num_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
|
|
25
src/indexer/album-playlist-funcs.h
Normal file
25
src/indexer/album-playlist-funcs.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* album-playlist-funcs.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 "../playlist/playlist.h"
|
||||
#include "structs.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
KotoPlaylist * koto_album_create_playlist(KotoAlbum * self);
|
||||
|
||||
G_END_DECLS
|
|
@ -24,7 +24,7 @@
|
|||
#include "../playlist/current.h"
|
||||
#include "../playlist/playlist.h"
|
||||
#include "../koto-utils.h"
|
||||
#include "structs.h"
|
||||
#include "album-playlist-funcs.h"
|
||||
#include "track-helpers.h"
|
||||
|
||||
extern KotoCartographer * koto_maps;
|
||||
|
@ -284,6 +284,42 @@ void koto_album_commit(KotoAlbum * self) {
|
|||
}
|
||||
}
|
||||
|
||||
KotoPlaylist * koto_album_create_playlist(KotoAlbum * self) {
|
||||
if (!KOTO_IS_ALBUM(self)) { // Not an album
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->tracks == NULL) { // No files to add to the playlist
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KotoPlaylist * new_album_playlist = koto_playlist_new(); // Create a new playlist
|
||||
|
||||
g_object_set(new_album_playlist, "ephemeral", TRUE, NULL); // Set as ephemeral / temporary
|
||||
|
||||
// The following section effectively reverses our tracks, so the first is now last.
|
||||
// It then adds them in reverse order, since our playlist add function will prepend to our queue
|
||||
// This enables the preservation and defaulting of "newest" first everywhere else, while in albums preserving the rightful order of the album
|
||||
// e.g. first track (0) being added last is actually first in the playlist's tracks
|
||||
GList * reversed_tracks = g_list_copy(self->tracks); // Copy our tracks so we can reverse the order
|
||||
|
||||
reversed_tracks = g_list_reverse(reversed_tracks); // Actually reverse it
|
||||
|
||||
GList * t;
|
||||
|
||||
for (t = reversed_tracks; t != NULL; t = t->next) { // For each of the tracks
|
||||
gchar * track_uuid = t->data;
|
||||
koto_playlist_add_track_by_uuid(new_album_playlist, track_uuid, FALSE, FALSE); // Add the UUID, skip commit to table since it is temporary
|
||||
}
|
||||
|
||||
g_list_free(t);
|
||||
g_list_free(reversed_tracks);
|
||||
|
||||
koto_playlist_apply_model(new_album_playlist, KOTO_PREFERRED_MODEL_TYPE_DEFAULT); // Ensure we are using our default model
|
||||
|
||||
return new_album_playlist;
|
||||
}
|
||||
|
||||
void koto_album_find_album_art(KotoAlbum * self) {
|
||||
if (self->has_album_art) { // If we already have album art
|
||||
return;
|
||||
|
@ -588,38 +624,21 @@ void koto_album_set_artist_uuid(
|
|||
}
|
||||
|
||||
void koto_album_set_as_current_playlist(KotoAlbum * self) {
|
||||
if (!KOTO_IS_ALBUM(self)) { // Not an album
|
||||
if (!KOTO_IS_ALBUM(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->tracks == NULL) { // No files to add to the playlist
|
||||
if (!KOTO_IS_CURRENT_PLAYLIST(current_playlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlaylist * new_album_playlist = koto_playlist_new(); // Create a new playlist
|
||||
KotoPlaylist * album_playlist = koto_album_create_playlist(self);
|
||||
|
||||
g_object_set(new_album_playlist, "ephemeral", TRUE, NULL); // Set as ephemeral / temporary
|
||||
|
||||
// The following section effectively reverses our tracks, so the first is now last.
|
||||
// It then adds them in reverse order, since our playlist add function will prepend to our queue
|
||||
// This enables the preservation and defaulting of "newest" first everywhere else, while in albums preserving the rightful order of the album
|
||||
// e.g. first track (0) being added last is actually first in the playlist's tracks
|
||||
GList * reversed_tracks = g_list_copy(self->tracks); // Copy our tracks so we can reverse the order
|
||||
|
||||
reversed_tracks = g_list_reverse(reversed_tracks); // Actually reverse it
|
||||
|
||||
GList * t;
|
||||
|
||||
for (t = reversed_tracks; t != NULL; t = t->next) { // For each of the tracks
|
||||
gchar * track_uuid = t->data;
|
||||
koto_playlist_add_track_by_uuid(new_album_playlist, track_uuid, FALSE, FALSE); // Add the UUID, skip commit to table since it is temporary
|
||||
if (!KOTO_IS_PLAYLIST(album_playlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_list_free(t);
|
||||
g_list_free(reversed_tracks);
|
||||
|
||||
koto_playlist_apply_model(new_album_playlist, KOTO_PREFERRED_MODEL_TYPE_DEFAULT); // Ensure we are using our default model
|
||||
koto_current_playlist_set_playlist(current_playlist, new_album_playlist); // Set our new current playlist
|
||||
koto_current_playlist_set_playlist(current_playlist, album_playlist, TRUE); // Set our new current playlist and start playing immediately
|
||||
}
|
||||
|
||||
void koto_album_set_preparsed_genres(
|
||||
|
|
|
@ -518,6 +518,14 @@ void koto_playerbar_handle_volume_button_change(
|
|||
}
|
||||
|
||||
void koto_playerbar_reset_progressbar(KotoPlayerBar * bar) {
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_RANGE(bar->progress_bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_range_set_range(GTK_RANGE(bar->progress_bar), 0, 0); // Reset range
|
||||
gtk_range_set_value(GTK_RANGE(bar->progress_bar), 0); // Set value to 0
|
||||
}
|
||||
|
@ -526,6 +534,14 @@ void koto_playerbar_set_progressbar_duration(
|
|||
KotoPlayerBar * bar,
|
||||
gint64 duration
|
||||
) {
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_RANGE(bar->progress_bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (duration <= 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -540,6 +556,14 @@ void koto_playerbar_set_progressbar_value(
|
|||
KotoPlayerBar * bar,
|
||||
double progress
|
||||
) {
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_RANGE(bar->progress_bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_range_set_value(GTK_RANGE(bar->progress_bar), progress);
|
||||
}
|
||||
|
||||
|
@ -620,7 +644,7 @@ void koto_playerbar_update_track_info(
|
|||
|
||||
g_free(artist_uuid);
|
||||
|
||||
if ((track_name != NULL) && (strcmp(track_name, "") != 0)) { // Have a track name
|
||||
if (koto_utils_is_string_valid(track_name)) { // Have a track name
|
||||
gtk_label_set_text(GTK_LABEL(bar->playback_title), track_name); // Set the label
|
||||
}
|
||||
|
||||
|
@ -636,16 +660,14 @@ void koto_playerbar_update_track_info(
|
|||
}
|
||||
}
|
||||
|
||||
if (!koto_utils_is_string_valid(album_uuid)) { // Do not have a valid album UUID
|
||||
return;
|
||||
}
|
||||
gchar * art_path = NULL;
|
||||
|
||||
if (koto_utils_is_string_valid(album_uuid)) { // Have a valid album UUID
|
||||
KotoAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||
g_free(album_uuid);
|
||||
|
||||
if (KOTO_IS_ALBUM(album)) {
|
||||
gchar * album_name = NULL;
|
||||
gchar * art_path = NULL;
|
||||
g_object_get(album, "name", &album_name, "art-path", &art_path, NULL); // Get album name and art path
|
||||
|
||||
if ((album_name != NULL) && (strcmp(album_name, "") != 0)) { // Have an album name
|
||||
|
@ -654,13 +676,14 @@ void koto_playerbar_update_track_info(
|
|||
} else {
|
||||
gtk_widget_hide(bar->playback_album);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((art_path != NULL) && g_path_is_absolute(art_path)) { // Have an album artist path
|
||||
gtk_image_set_from_file(GTK_IMAGE(bar->artwork), art_path); // Update the art
|
||||
} else {
|
||||
gtk_image_set_from_icon_name(GTK_IMAGE(bar->artwork), "audio-x-generic-symbolic"); // Use generic instead
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget * koto_playerbar_get_main(KotoPlayerBar * bar) {
|
||||
|
|
|
@ -323,7 +323,7 @@ void koto_artist_view_toggle_playback(
|
|||
return;
|
||||
}
|
||||
|
||||
koto_current_playlist_set_playlist(current_playlist, artist_playlist); // Set our playlist to the one associated with the Artist
|
||||
koto_current_playlist_set_playlist(current_playlist, artist_playlist, TRUE); // Set our playlist to the one associated with the Artist and start playback immediately
|
||||
}
|
||||
|
||||
KotoArtistView * koto_artist_view_new(KotoArtist * artist) {
|
||||
|
|
|
@ -208,6 +208,10 @@ void koto_disc_view_handle_selected_rows_changed(
|
|||
) {
|
||||
KotoDiscView * self = user_data;
|
||||
|
||||
if (!KOTO_IS_DISC_VIEW(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * album_uuid = koto_album_get_album_uuid(self->album); // Get the UUID
|
||||
|
||||
if (!koto_utils_is_string_valid(album_uuid)) { // Not set
|
||||
|
|
|
@ -209,7 +209,7 @@ void koto_playlist_page_handle_cover_art_clicked(
|
|||
return;
|
||||
}
|
||||
|
||||
koto_current_playlist_set_playlist(current_playlist, self->playlist);
|
||||
koto_current_playlist_set_playlist(current_playlist, self->playlist, TRUE); // Switch to this playlist and start playing immediately
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_edit_button_clicked(
|
||||
|
|
|
@ -238,7 +238,7 @@ static void koto_playback_engine_init(KotoPlaybackEngine * self) {
|
|||
g_signal_connect(config, "notify::maintain-shuffle", G_CALLBACK(koto_playback_engine_apply_configuration_state), self); // Handle changes to our config
|
||||
|
||||
if (KOTO_IS_CURRENT_PLAYLIST(current_playlist)) {
|
||||
g_signal_connect(current_playlist, "notify::current-playlist", G_CALLBACK(koto_playback_engine_current_playlist_changed), self);
|
||||
g_signal_connect(current_playlist, "playlist-changed", G_CALLBACK(koto_playback_engine_handle_current_playlist_changed), self);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,29 +287,26 @@ void koto_playback_engine_backwards(KotoPlaybackEngine * self) {
|
|||
koto_playback_engine_set_track_by_uuid(self, koto_playlist_go_to_previous(playlist), FALSE);
|
||||
}
|
||||
|
||||
void koto_playback_engine_current_playlist_changed(
|
||||
void koto_playback_engine_handle_current_playlist_changed(
|
||||
KotoCurrentPlaylist * current_pl,
|
||||
guint prop_id,
|
||||
KotoPlaybackEngine * self
|
||||
KotoPlaylist * playlist,
|
||||
gboolean play_immediately,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) current_pl;
|
||||
(void) prop_id;
|
||||
KotoPlaybackEngine * self = user_data;
|
||||
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlaylist * playlist = koto_current_playlist_get_playlist(current_playlist); // Get the current playlist
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) { // If we do not have a playlist currently
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->is_shuffle_enabled) { // If shuffle is enabled
|
||||
koto_playback_engine_set_track_shuffle(self, self->via_config_maintain_shuffle); // Set to our maintain shuffle value
|
||||
}
|
||||
|
||||
koto_playback_engine_set_track_by_uuid(playback_engine, koto_playlist_go_to_next(playlist), FALSE); // Go to "next" which is the first track
|
||||
if (play_immediately) { // Should play immediately
|
||||
koto_playback_engine_set_track_by_uuid(self, koto_playlist_go_to_next(playlist), FALSE); // Go to "next" which is the first track
|
||||
}
|
||||
}
|
||||
|
||||
void koto_playback_engine_forwards(KotoPlaybackEngine * self) {
|
||||
|
@ -495,6 +492,10 @@ void koto_playback_engine_set_track_by_uuid(
|
|||
gchar * track_uuid,
|
||||
gboolean playing_specific_track
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!koto_utils_is_string_valid(track_uuid)) { // If this is not a valid track uuid string
|
||||
return;
|
||||
}
|
||||
|
@ -534,12 +535,12 @@ void koto_playback_engine_set_track_by_uuid(
|
|||
const gchar * track_name = g_variant_get_string(track_name_var, NULL); // Get the string of the track name
|
||||
|
||||
GVariant * album_name_var = g_variant_dict_lookup_value(metadata_dict, "xesam:album", NULL); // Get the GVariant for the album name
|
||||
const gchar * album_name = g_variant_get_string(album_name_var, NULL); // Get the string for the album name
|
||||
gchar * album_name = (album_name_var != NULL) ? g_strdup(g_variant_get_string(album_name_var, NULL)) : NULL; // Get the string for the album name
|
||||
|
||||
GVariant * artist_name_var = g_variant_dict_lookup_value(metadata_dict, "playbackengine:artist", NULL); // Get the GVariant for the name of the artist
|
||||
const gchar * artist_name = g_variant_get_string(artist_name_var, NULL); // Get the string for the artist name
|
||||
gchar * artist_name = g_strdup(g_variant_get_string(artist_name_var, NULL)); // Get the string for the artist name
|
||||
|
||||
gchar * artist_album_combo = g_strjoin(" - ", artist_name, album_name, NULL); // Join artist and album name separated by " - "
|
||||
gchar * artist_album_combo = koto_utils_is_string_valid(album_name) ? g_strjoin(" - ", artist_name, album_name, NULL) : artist_name; // Join artist and album name separated by " - "
|
||||
|
||||
gchar * icon_name = "audio-x-generic-symbolic";
|
||||
|
||||
|
|
|
@ -52,10 +52,11 @@ void koto_playback_engine_apply_configuration_state(
|
|||
|
||||
void koto_playback_engine_backwards(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_current_playlist_changed(
|
||||
void koto_playback_engine_handle_current_playlist_changed(
|
||||
KotoCurrentPlaylist * current_pl,
|
||||
guint prop_id,
|
||||
KotoPlaybackEngine * self
|
||||
KotoPlaylist * playlist,
|
||||
gboolean play_immediately,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playback_engine_forwards(KotoPlaybackEngine * self);
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
#include "current.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_CURRENT_PLAYLIST,
|
||||
N_PROPERTIES
|
||||
SIGNAL_PLAYLIST_CHANGED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
static guint signals[N_SIGNALS] = {
|
||||
0
|
||||
};
|
||||
|
||||
KotoCurrentPlaylist * current_playlist = NULL;
|
||||
|
@ -35,87 +34,50 @@ struct _KotoCurrentPlaylist {
|
|||
KotoPlaylist * current_playlist;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoCurrentPlaylist, koto_current_playlist, G_TYPE_OBJECT);
|
||||
struct _KotoCurrentPlaylistClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
static void koto_current_playlist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_current_playlist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
void (* playlist_changed) (
|
||||
KotoCurrentPlaylist * self,
|
||||
KotoPlaylist * playlist,
|
||||
gboolean play_immediately
|
||||
);
|
||||
};
|
||||
|
||||
static void koto_current_playlist_class_init(KotoCurrentPlaylistClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_current_playlist_set_property;
|
||||
gobject_class->get_property = koto_current_playlist_get_property;
|
||||
|
||||
props[PROP_CURRENT_PLAYLIST] = g_param_spec_object(
|
||||
"current-playlist",
|
||||
"Current Playlist",
|
||||
"Current Playlist",
|
||||
signals[SIGNAL_PLAYLIST_CHANGED] = g_signal_new(
|
||||
"playlist-changed",
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
|
||||
G_STRUCT_OFFSET(KotoCurrentPlaylistClass, playlist_changed),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
2,
|
||||
KOTO_TYPE_PLAYLIST,
|
||||
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||
G_TYPE_BOOLEAN
|
||||
);
|
||||
|
||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE(KotoCurrentPlaylist, koto_current_playlist, G_TYPE_OBJECT);
|
||||
|
||||
static void koto_current_playlist_init(KotoCurrentPlaylist * self) {
|
||||
self->current_playlist = NULL;
|
||||
}
|
||||
|
||||
void koto_current_playlist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoCurrentPlaylist * self = KOTO_CURRENT_PLAYLIST(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CURRENT_PLAYLIST:
|
||||
g_value_set_object(val, self->current_playlist);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void koto_current_playlist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoCurrentPlaylist * self = KOTO_CURRENT_PLAYLIST(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CURRENT_PLAYLIST:
|
||||
koto_current_playlist_set_playlist(self, (KotoPlaylist*) g_value_get_object(val));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KotoPlaylist * koto_current_playlist_get_playlist(KotoCurrentPlaylist * self) {
|
||||
return self->current_playlist;
|
||||
}
|
||||
|
||||
void koto_current_playlist_set_playlist(
|
||||
KotoCurrentPlaylist * self,
|
||||
KotoPlaylist * playlist
|
||||
KotoPlaylist * playlist,
|
||||
gboolean play_immediately
|
||||
) {
|
||||
if (!KOTO_IS_CURRENT_PLAYLIST(self)) {
|
||||
return;
|
||||
|
@ -142,7 +104,13 @@ void koto_current_playlist_set_playlist(
|
|||
// TODO: Saved state
|
||||
koto_playlist_set_position(self->current_playlist, -1); // Reset our position, use -1 since "next" song is then 0
|
||||
g_object_ref(playlist); // Increment the reference
|
||||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_CURRENT_PLAYLIST]);
|
||||
g_signal_emit(
|
||||
self,
|
||||
signals[SIGNAL_PLAYLIST_CHANGED],
|
||||
0,
|
||||
playlist,
|
||||
play_immediately
|
||||
);
|
||||
}
|
||||
|
||||
KotoCurrentPlaylist * koto_current_playlist_new() {
|
||||
|
|
|
@ -26,9 +26,15 @@ G_BEGIN_DECLS
|
|||
**/
|
||||
|
||||
#define KOTO_TYPE_CURRENT_PLAYLIST koto_current_playlist_get_type()
|
||||
G_DECLARE_FINAL_TYPE(KotoCurrentPlaylist, koto_current_playlist, KOTO, CURRENT_PLAYLIST, GObject);
|
||||
#define KOTO_CURRENT_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KOTO_TYPE_CURRENT_PLAYLIST, KotoCurrentPlaylist))
|
||||
#define KOTO_IS_CURRENT_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_CURRENT_PLAYLIST))
|
||||
|
||||
typedef struct _KotoCurrentPlaylist KotoCurrentPlaylist;
|
||||
typedef struct _KotoCurrentPlaylistClass KotoCurrentPlaylistClass;
|
||||
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GType koto_current_playlist_get_type(void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* Current Playlist Functions
|
||||
**/
|
||||
|
@ -39,7 +45,8 @@ KotoPlaylist * koto_current_playlist_get_playlist(KotoCurrentPlaylist * self);
|
|||
|
||||
void koto_current_playlist_set_playlist(
|
||||
KotoCurrentPlaylist * self,
|
||||
KotoPlaylist * playlist
|
||||
KotoPlaylist * playlist,
|
||||
gboolean play_immediately
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue