diff --git a/src/components/koto-action-bar.c b/src/components/koto-action-bar.c index 31ddd0f..3270d8a 100644 --- a/src/components/koto-action-bar.c +++ b/src/components/koto-action-bar.c @@ -18,7 +18,9 @@ #include #include #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; } - 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); + KotoPlaylist * playlist = NULL; - 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_playlist_set_track_as_current(playlist, koto_track_get_uuid(track)); // Get this track as the current track in the position + if (self->relative == KOTO_ACTION_BAR_IS_PLAYLIST_RELATIVE) { // Relative to a playlist + 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 } } - koto_playback_engine_set_track_by_uuid(playback_engine, koto_track_get_uuid(track), TRUE); // Set the track to play + if (KOTO_IS_PLAYLIST(playlist)) { // Is a playlist + 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 + } + + 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); diff --git a/src/components/track-table.c b/src/components/track-table.c index e1ec15b..0d3cd7f 100644 --- a/src/components/track-table.c +++ b/src/components/track-table.c @@ -18,6 +18,8 @@ #include #include #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() { diff --git a/src/components/track-table.h b/src/components/track-table.h index 5b73212..287d9b4 100644 --- a/src/components/track-table.h +++ b/src/components/track-table.h @@ -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, diff --git a/src/indexer/album-playlist-funcs.h b/src/indexer/album-playlist-funcs.h new file mode 100644 index 0000000..083f284 --- /dev/null +++ b/src/indexer/album-playlist-funcs.h @@ -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 \ No newline at end of file diff --git a/src/indexer/album.c b/src/indexer/album.c index 4f681fa..06b9f73 100644 --- a/src/indexer/album.c +++ b/src/indexer/album.c @@ -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( diff --git a/src/koto-playerbar.c b/src/koto-playerbar.c index 423fc38..6625ef9 100644 --- a/src/koto-playerbar.c +++ b/src/koto-playerbar.c @@ -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,30 +660,29 @@ 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; + 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 + gtk_label_set_text(GTK_LABEL(bar->playback_album), album_name); + gtk_widget_show(bar->playback_album); + } else { + gtk_widget_hide(bar->playback_album); + } + } } - 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 - gtk_label_set_text(GTK_LABEL(bar->playback_album), album_name); - gtk_widget_show(bar->playback_album); - } 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 - } + 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 } } diff --git a/src/pages/music/artist-view.c b/src/pages/music/artist-view.c index 03abfb0..314487f 100644 --- a/src/pages/music/artist-view.c +++ b/src/pages/music/artist-view.c @@ -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) { diff --git a/src/pages/music/disc-view.c b/src/pages/music/disc-view.c index a8487d5..4425baa 100644 --- a/src/pages/music/disc-view.c +++ b/src/pages/music/disc-view.c @@ -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 diff --git a/src/pages/playlist/list.c b/src/pages/playlist/list.c index c5354d5..f35f3e2 100644 --- a/src/pages/playlist/list.c +++ b/src/pages/playlist/list.c @@ -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( diff --git a/src/playback/engine.c b/src/playback/engine.c index abe3e42..e449842 100644 --- a/src/playback/engine.c +++ b/src/playback/engine.c @@ -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"; diff --git a/src/playback/engine.h b/src/playback/engine.h index f90f4a7..88889fb 100644 --- a/src/playback/engine.h +++ b/src/playback/engine.h @@ -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); diff --git a/src/playlist/current.c b/src/playlist/current.c index 52c179b..9275340 100644 --- a/src/playlist/current.c +++ b/src/playlist/current.c @@ -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() { diff --git a/src/playlist/current.h b/src/playlist/current.h index 10cddef..09409e5 100644 --- a/src/playlist/current.h +++ b/src/playlist/current.h @@ -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