2021-05-07 16:45:57 +03:00
/* koto-action-bar.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 <gtk-4.0/gtk/gtk.h>
# include "koto-action-bar.h"
# include "../db/cartographer.h"
# include "../pages/music/music-local.h"
# include "../playlist/add-remove-track-popover.h"
2021-05-27 12:56:36 +03:00
# include "../playlist/current.h"
2021-05-07 16:45:57 +03:00
# include "../playback/engine.h"
# include "../koto-button.h"
2021-05-07 21:52:42 +03:00
# include "../koto-utils.h"
2021-05-07 16:45:57 +03:00
# include "../koto-window.h"
2021-05-11 20:05:04 +03:00
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup ;
extern KotoCartographer * koto_maps ;
2021-05-27 12:56:36 +03:00
extern KotoCurrentPlaylist * current_playlist ;
2021-05-11 20:05:04 +03:00
extern KotoPageMusicLocal * music_local_page ;
extern KotoPlaybackEngine * playback_engine ;
extern KotoWindow * main_window ;
2021-05-07 16:45:57 +03:00
enum {
SIGNAL_CLOSED ,
N_SIGNALS
} ;
2021-05-11 20:05:04 +03:00
static guint actionbar_signals [ N_SIGNALS ] = {
0
} ;
2021-05-07 16:45:57 +03:00
struct _KotoActionBar {
GObject parent_instance ;
2021-05-11 20:05:04 +03:00
GtkActionBar * main ;
2021-05-07 16:45:57 +03:00
2021-05-11 20:05:04 +03:00
GtkWidget * center_box_content ;
GtkWidget * start_box_content ;
GtkWidget * stop_box_content ;
2021-05-07 16:45:57 +03:00
2021-05-11 20:05:04 +03:00
KotoButton * close_button ;
GtkWidget * go_to_artist ;
GtkWidget * playlists ;
GtkWidget * play_track ;
GtkWidget * remove_from_playlist ;
2021-05-07 16:45:57 +03:00
2021-05-11 20:05:04 +03:00
GList * current_list ;
gchar * current_album_uuid ;
gchar * current_playlist_uuid ;
2021-05-07 16:45:57 +03:00
KotoActionBarRelative relative ;
} ;
struct _KotoActionBarClass {
GObjectClass parent_class ;
2021-05-11 20:05:04 +03:00
void ( * closed ) ( KotoActionBar * self ) ;
2021-05-07 16:45:57 +03:00
} ;
G_DEFINE_TYPE ( KotoActionBar , koto_action_bar , G_TYPE_OBJECT ) ;
KotoActionBar * action_bar ;
2021-05-11 20:05:04 +03:00
static void koto_action_bar_class_init ( KotoActionBarClass * c ) {
GObjectClass * gobject_class = G_OBJECT_CLASS ( c ) ;
2021-05-07 16:45:57 +03:00
actionbar_signals [ SIGNAL_CLOSED ] = g_signal_new (
" closed " ,
G_TYPE_FROM_CLASS ( gobject_class ) ,
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION ,
G_STRUCT_OFFSET ( KotoActionBarClass , closed ) ,
NULL ,
NULL ,
NULL ,
G_TYPE_NONE ,
0
) ;
}
2021-05-11 20:05:04 +03:00
static void koto_action_bar_init ( KotoActionBar * self ) {
2021-05-07 16:45:57 +03:00
self - > main = GTK_ACTION_BAR ( gtk_action_bar_new ( ) ) ; // Create a new action bar
self - > current_list = NULL ;
self - > close_button = koto_button_new_with_icon ( NULL , " window-close-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
self - > go_to_artist = gtk_button_new_with_label ( " Go to Artist " ) ;
self - > playlists = gtk_button_new_with_label ( " Playlists " ) ;
self - > play_track = gtk_button_new_with_label ( " Play " ) ;
self - > remove_from_playlist = gtk_button_new_with_label ( " Remove from Playlist " ) ;
gtk_widget_add_css_class ( self - > playlists , " suggested-action " ) ;
gtk_widget_add_css_class ( self - > play_track , " suggested-action " ) ;
gtk_widget_add_css_class ( self - > remove_from_playlist , " destructive-action " ) ;
gtk_widget_set_size_request ( self - > play_track , 160 , - 1 ) ;
self - > center_box_content = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
self - > start_box_content = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
self - > stop_box_content = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 20 ) ;
gtk_box_prepend ( GTK_BOX ( self - > start_box_content ) , GTK_WIDGET ( self - > go_to_artist ) ) ;
gtk_box_prepend ( GTK_BOX ( self - > center_box_content ) , GTK_WIDGET ( self - > play_track ) ) ;
gtk_box_prepend ( GTK_BOX ( self - > stop_box_content ) , GTK_WIDGET ( self - > playlists ) ) ;
gtk_box_append ( GTK_BOX ( self - > stop_box_content ) , GTK_WIDGET ( self - > remove_from_playlist ) ) ;
gtk_box_append ( GTK_BOX ( self - > stop_box_content ) , GTK_WIDGET ( self - > close_button ) ) ;
gtk_action_bar_pack_start ( self - > main , self - > start_box_content ) ;
gtk_action_bar_pack_end ( self - > main , self - > stop_box_content ) ;
gtk_action_bar_set_center_widget ( self - > main , self - > center_box_content ) ;
// Hide all the widgets by default
gtk_widget_hide ( GTK_WIDGET ( self - > go_to_artist ) ) ;
gtk_widget_hide ( GTK_WIDGET ( self - > playlists ) ) ;
gtk_widget_hide ( GTK_WIDGET ( self - > play_track ) ) ;
gtk_widget_hide ( GTK_WIDGET ( self - > remove_from_playlist ) ) ;
// Set up bindings
koto_button_add_click_handler ( self - > close_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_action_bar_handle_close_button_clicked ) , self ) ;
g_signal_connect ( self - > go_to_artist , " clicked " , G_CALLBACK ( koto_action_bar_handle_go_to_artist_button_clicked ) , self ) ;
g_signal_connect ( self - > playlists , " clicked " , G_CALLBACK ( koto_action_bar_handle_playlists_button_clicked ) , self ) ;
g_signal_connect ( self - > play_track , " clicked " , G_CALLBACK ( koto_action_bar_handle_play_track_button_clicked ) , self ) ;
g_signal_connect ( self - > remove_from_playlist , " clicked " , G_CALLBACK ( koto_action_bar_handle_remove_from_playlist_button_clicked ) , self ) ;
koto_action_bar_toggle_reveal ( self , FALSE ) ; // Hide by default
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_close ( KotoActionBar * self ) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
gtk_widget_hide ( GTK_WIDGET ( koto_add_remove_track_popup ) ) ; // Hide the Add / Remove Track Playlists popover
koto_action_bar_toggle_reveal ( self , FALSE ) ; // Hide the action bar
g_signal_emit (
self ,
actionbar_signals [ SIGNAL_CLOSED ] ,
0 ,
NULL
) ;
}
2021-05-11 20:05:04 +03:00
GtkActionBar * koto_action_bar_get_main ( KotoActionBar * self ) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return NULL ;
}
return self - > main ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_handle_close_button_clicked (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
2021-05-07 16:45:57 +03:00
koto_action_bar_close ( data ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_handle_go_to_artist_button_clicked (
GtkButton * button ,
gpointer data
) {
2021-05-07 16:45:57 +03:00
( void ) button ;
2021-05-11 20:05:04 +03:00
KotoActionBar * self = data ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
if ( self - > current_list = = NULL | | ( g_list_length ( self - > current_list ) ! = 1 ) ) { // Not a list or not exactly one item
return ;
}
2021-05-11 20:08:39 +03:00
KotoTrack * selected_track = g_list_nth_data ( self - > current_list , 0 ) ; // Get the first item
2021-05-11 20:05:04 +03:00
2021-05-07 16:45:57 +03:00
2021-05-11 20:08:39 +03:00
if ( ! KOTO_IS_TRACK ( selected_track ) ) { // Not a track
2021-05-07 16:45:57 +03:00
return ;
}
2021-05-11 20:05:04 +03:00
gchar * artist_uuid = NULL ;
2021-05-07 16:45:57 +03:00
g_object_get (
selected_track ,
" artist-uuid " ,
& artist_uuid ,
NULL
) ;
2021-05-11 20:05:04 +03:00
koto_page_music_local_go_to_artist_by_uuid ( music_local_page , artist_uuid ) ; // Go to the artist
2021-05-07 16:45:57 +03:00
koto_window_go_to_page ( main_window , " music.local " ) ; // Navigate to the local music stack so we can see the substack page
koto_action_bar_close ( self ) ; // Close the action bar
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_handle_playlists_button_clicked (
GtkButton * button ,
gpointer data
) {
2021-05-07 16:45:57 +03:00
( void ) button ;
2021-05-11 20:05:04 +03:00
KotoActionBar * self = data ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
if ( self - > current_list = = NULL | | ( g_list_length ( self - > current_list ) = = 0 ) ) { // Not a list or no content
return ;
}
koto_add_remove_track_popover_set_tracks ( koto_add_remove_track_popup , self - > current_list ) ; // Set the popover tracks
koto_add_remove_track_popover_set_pointing_to_widget ( koto_add_remove_track_popup , GTK_WIDGET ( self - > playlists ) , GTK_POS_TOP ) ; // Show the popover above the button
gtk_widget_show ( GTK_WIDGET ( koto_add_remove_track_popup ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_handle_play_track_button_clicked (
GtkButton * button ,
gpointer data
) {
2021-05-07 16:45:57 +03:00
( void ) button ;
2021-05-11 20:05:04 +03:00
KotoActionBar * self = data ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
if ( self - > current_list = = NULL | | ( g_list_length ( self - > current_list ) ! = 1 ) ) { // Not a list or not exactly 1 item selected
goto doclose ;
}
2021-05-11 20:08:39 +03:00
KotoTrack * track = g_list_nth_data ( self - > current_list , 0 ) ; // Get the first track
2021-05-11 20:05:04 +03:00
2021-05-11 20:08:39 +03:00
if ( ! KOTO_IS_TRACK ( track ) ) { // Not a track
2021-05-07 16:45:57 +03:00
goto doclose ;
}
2021-05-27 12:56:36 +03:00
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 ) ;
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
}
}
koto_playback_engine_set_track_by_uuid ( playback_engine , koto_track_get_uuid ( track ) , TRUE ) ; // Set the track to play
2021-05-07 16:45:57 +03:00
doclose :
koto_action_bar_close ( self ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_handle_remove_from_playlist_button_clicked (
GtkButton * button ,
gpointer data
) {
2021-05-07 16:45:57 +03:00
( void ) button ;
2021-05-11 20:05:04 +03:00
KotoActionBar * self = data ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
if ( self - > current_list = = NULL | | ( g_list_length ( self - > current_list ) = = 0 ) ) { // Not a list or no content
goto doclose ;
}
2021-05-07 21:52:42 +03:00
if ( ! koto_utils_is_string_valid ( self - > current_playlist_uuid ) ) { // Not valid UUID
2021-05-07 16:45:57 +03:00
goto doclose ;
}
2021-05-11 20:05:04 +03:00
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid ( koto_maps , self - > current_playlist_uuid ) ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_PLAYLIST ( playlist ) ) { // Not a playlist
goto doclose ;
}
2021-05-11 20:05:04 +03:00
GList * cur_list ;
2021-05-11 20:08:39 +03:00
for ( cur_list = self - > current_list ; cur_list ! = NULL ; cur_list = cur_list - > next ) { // For each KotoTrack
KotoTrack * track = cur_list - > data ;
koto_playlist_remove_track_by_uuid ( playlist , koto_track_get_uuid ( track ) ) ; // Remove this track
2021-05-07 16:45:57 +03:00
}
doclose :
koto_action_bar_close ( self ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_set_tracks_in_album_selection (
KotoActionBar * self ,
gchar * album_uuid ,
GList * tracks
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
2021-05-07 21:52:42 +03:00
if ( koto_utils_is_string_valid ( self - > current_album_uuid ) ) { // Album UUID currently set
2021-05-07 16:45:57 +03:00
g_free ( self - > current_album_uuid ) ;
}
2021-05-07 21:52:42 +03:00
if ( koto_utils_is_string_valid ( self - > current_playlist_uuid ) ) { // Playlist UUID currently set
2021-05-07 16:45:57 +03:00
g_free ( self - > current_playlist_uuid ) ;
}
self - > current_playlist_uuid = NULL ;
self - > current_album_uuid = g_strdup ( album_uuid ) ;
self - > relative = KOTO_ACTION_BAR_IS_ALBUM_RELATIVE ;
g_list_free ( self - > current_list ) ;
self - > current_list = g_list_copy ( tracks ) ;
koto_add_remove_track_popover_clear_tracks ( koto_add_remove_track_popup ) ; // Clear the current popover contents
koto_add_remove_track_popover_set_tracks ( koto_add_remove_track_popup , self - > current_list ) ; // Set the associated tracks to remove
koto_action_bar_toggle_go_to_artist_visibility ( self , FALSE ) ;
koto_action_bar_toggle_play_button_visibility ( self , g_list_length ( self - > current_list ) = = 1 ) ;
gtk_widget_show ( GTK_WIDGET ( self - > playlists ) ) ;
gtk_widget_hide ( GTK_WIDGET ( self - > remove_from_playlist ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_set_tracks_in_playlist_selection (
KotoActionBar * self ,
gchar * playlist_uuid ,
GList * tracks
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
2021-05-07 21:52:42 +03:00
if ( koto_utils_is_string_valid ( self - > current_album_uuid ) ) { // Album UUID currently set
2021-05-07 16:45:57 +03:00
g_free ( self - > current_album_uuid ) ;
}
2021-05-07 21:52:42 +03:00
if ( koto_utils_is_string_valid ( self - > current_playlist_uuid ) ) { // Playlist UUID currently set
2021-05-07 16:45:57 +03:00
g_free ( self - > current_playlist_uuid ) ;
}
self - > current_album_uuid = NULL ;
self - > current_playlist_uuid = g_strdup ( playlist_uuid ) ;
self - > relative = KOTO_ACTION_BAR_IS_PLAYLIST_RELATIVE ;
g_list_free ( self - > current_list ) ;
self - > current_list = g_list_copy ( tracks ) ;
gboolean single_selected = g_list_length ( tracks ) = = 1 ;
2021-05-11 20:05:04 +03:00
2021-05-07 16:45:57 +03:00
koto_action_bar_toggle_go_to_artist_visibility ( self , single_selected ) ;
koto_action_bar_toggle_play_button_visibility ( self , single_selected ) ;
gtk_widget_hide ( GTK_WIDGET ( self - > playlists ) ) ;
gtk_widget_show ( GTK_WIDGET ( self - > remove_from_playlist ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_toggle_go_to_artist_visibility (
KotoActionBar * self ,
gboolean visible
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
( visible ) ? gtk_widget_show ( GTK_WIDGET ( self - > go_to_artist ) ) : gtk_widget_hide ( GTK_WIDGET ( self - > go_to_artist ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_toggle_play_button_visibility (
KotoActionBar * self ,
gboolean visible
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
( visible ) ? gtk_widget_show ( GTK_WIDGET ( self - > play_track ) ) : gtk_widget_hide ( GTK_WIDGET ( self - > play_track ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_action_bar_toggle_reveal (
KotoActionBar * self ,
gboolean state
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_ACTION_BAR ( self ) ) {
return ;
}
gtk_action_bar_set_revealed ( self - > main , state ) ;
}
2021-05-11 20:05:04 +03:00
KotoActionBar * koto_action_bar_new ( ) {
2021-05-07 16:45:57 +03:00
return g_object_new (
KOTO_TYPE_ACTION_BAR ,
NULL
) ;
}