2021-02-09 17:37:26 +02:00
/* koto-window.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 .
*/
2021-02-25 18:15:36 +02:00
# include <gtk-4.0/gdk/x11/gdkx.h>
2021-05-07 16:45:57 +03:00
# include "components/koto-action-bar.h"
# include "db/cartographer.h"
2021-03-02 19:12:12 +02:00
# include "indexer/structs.h"
2021-02-24 20:17:18 +02:00
# include "pages/music/music-local.h"
2021-05-07 16:45:57 +03:00
# include "pages/playlist/list.h"
2021-03-23 19:50:09 +02:00
# include "playback/engine.h"
2021-05-07 16:45:57 +03:00
# include "playlist/add-remove-track-popover.h"
2021-03-10 13:44:08 +02:00
# include "playlist/current.h"
2021-05-07 16:45:57 +03:00
# include "playlist/create-modify-dialog.h"
2021-02-09 17:37:26 +02:00
# include "koto-config.h"
2021-05-07 16:45:57 +03:00
# include "koto-dialog-container.h"
2021-02-09 17:37:26 +02:00
# include "koto-nav.h"
# include "koto-playerbar.h"
# include "koto-window.h"
2021-05-07 16:45:57 +03:00
extern KotoActionBar * action_bar ;
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup ;
extern KotoCartographer * koto_maps ;
extern KotoCreateModifyPlaylistDialog * playlist_create_modify_dialog ;
2021-03-10 13:44:08 +02:00
extern KotoCurrentPlaylist * current_playlist ;
2021-05-07 16:45:57 +03:00
extern KotoPageMusicLocal * music_local_page ;
2021-03-23 19:50:09 +02:00
extern KotoPlaybackEngine * playback_engine ;
2021-03-10 13:44:08 +02:00
2021-02-09 17:37:26 +02:00
struct _KotoWindow {
GtkApplicationWindow parent_instance ;
KotoIndexedLibrary * library ;
2021-03-10 13:44:08 +02:00
KotoCurrentPlaylist * current_playlist ;
2021-02-24 20:17:18 +02:00
2021-05-07 16:45:57 +03:00
KotoDialogContainer * dialogs ;
2021-04-07 13:17:33 +03:00
GtkWidget * overlay ;
2021-02-24 20:17:18 +02:00
GtkWidget * header_bar ;
GtkWidget * menu_button ;
GtkWidget * search_entry ;
2021-02-09 17:37:26 +02:00
GtkWidget * primary_layout ;
GtkWidget * content_layout ;
KotoNav * nav ;
2021-02-24 20:17:18 +02:00
GtkWidget * pages ;
2021-02-09 17:37:26 +02:00
KotoPlayerBar * player_bar ;
} ;
G_DEFINE_TYPE ( KotoWindow , koto_window , GTK_TYPE_APPLICATION_WINDOW )
static void koto_window_class_init ( KotoWindowClass * klass ) {
2021-02-24 20:17:18 +02:00
( void ) klass ;
2021-02-09 17:37:26 +02:00
}
static void koto_window_init ( KotoWindow * self ) {
2021-03-10 13:44:08 +02:00
current_playlist = koto_current_playlist_new ( ) ;
2021-03-23 19:50:09 +02:00
playback_engine = koto_playback_engine_new ( ) ;
2021-03-10 13:44:08 +02:00
2021-02-09 17:37:26 +02:00
GtkCssProvider * provider = gtk_css_provider_new ( ) ;
gtk_css_provider_load_from_resource ( provider , " /com/github/joshstrobl/koto/style.css " ) ;
2021-02-25 18:15:36 +02:00
gtk_style_context_add_provider_for_display ( gdk_display_get_default ( ) , GTK_STYLE_PROVIDER ( provider ) , GTK_STYLE_PROVIDER_PRIORITY_APPLICATION ) ;
2021-02-09 17:37:26 +02:00
2021-02-24 20:17:18 +02:00
create_new_headerbar ( self ) ; // Create our headerbar
2021-02-09 17:37:26 +02:00
2021-04-07 13:17:33 +03:00
self - > overlay = gtk_overlay_new ( ) ; // Create our overlay
2021-05-07 16:45:57 +03:00
self - > dialogs = koto_dialog_container_new ( ) ; // Create our dialog container
2021-04-07 13:17:33 +03:00
2021-02-09 17:37:26 +02:00
self - > primary_layout = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 0 ) ;
2021-02-25 18:15:36 +02:00
gtk_widget_add_css_class ( self - > primary_layout , " primary-layout " ) ;
2021-02-24 20:17:18 +02:00
gtk_widget_set_hexpand ( self - > primary_layout , TRUE ) ;
gtk_widget_set_vexpand ( self - > primary_layout , TRUE ) ;
2021-05-07 16:45:57 +03:00
playlist_create_modify_dialog = koto_create_modify_playlist_dialog_new ( ) ; // Create our Create Playlist dialog
koto_dialog_container_add_dialog ( self - > dialogs , " create-modify-playlist " , GTK_WIDGET ( playlist_create_modify_dialog ) ) ;
2021-04-07 13:17:33 +03:00
gtk_overlay_set_child ( GTK_OVERLAY ( self - > overlay ) , self - > primary_layout ) ; // Add our primary layout to the overlay
2021-05-07 16:45:57 +03:00
gtk_overlay_add_overlay ( GTK_OVERLAY ( self - > overlay ) , GTK_WIDGET ( self - > dialogs ) ) ; // Add the stack as our overlay
2021-04-07 13:17:33 +03:00
2021-02-09 17:37:26 +02:00
self - > content_layout = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
2021-02-25 18:15:36 +02:00
gtk_widget_add_css_class ( self - > content_layout , " content-layout " ) ;
2021-02-24 20:17:18 +02:00
gtk_widget_set_hexpand ( self - > content_layout , TRUE ) ;
gtk_widget_set_vexpand ( self - > content_layout , TRUE ) ;
2021-02-09 17:37:26 +02:00
self - > nav = koto_nav_new ( ) ;
if ( self - > nav ! = NULL ) {
2021-02-24 20:17:18 +02:00
gtk_box_prepend ( GTK_BOX ( self - > content_layout ) , koto_nav_get_nav ( self - > nav ) ) ;
}
self - > pages = gtk_stack_new ( ) ; // New stack to hold our pages
2021-02-09 17:37:26 +02:00
2021-02-24 20:17:18 +02:00
if ( GTK_IS_STACK ( self - > pages ) ) { // Created our stack successfully
gtk_stack_set_transition_type ( GTK_STACK ( self - > pages ) , GTK_STACK_TRANSITION_TYPE_OVER_LEFT_RIGHT ) ;
gtk_box_append ( GTK_BOX ( self - > content_layout ) , self - > pages ) ;
2021-03-09 11:45:44 +02:00
gtk_widget_set_hexpand ( self - > pages , TRUE ) ;
gtk_widget_set_vexpand ( self - > pages , TRUE ) ;
2021-02-09 17:37:26 +02:00
}
2021-02-24 20:17:18 +02:00
gtk_box_prepend ( GTK_BOX ( self - > primary_layout ) , self - > content_layout ) ;
2021-02-09 17:37:26 +02:00
2021-05-07 16:45:57 +03:00
koto_add_remove_track_popup = koto_add_remove_track_popover_new ( ) ; // Create our popover for adding and removing tracks
action_bar = koto_action_bar_new ( ) ; // Create our Koto Action Bar
if ( KOTO_IS_ACTION_BAR ( action_bar ) ) { // Is an action bar
GtkActionBar * bar = koto_action_bar_get_main ( action_bar ) ;
if ( GTK_IS_ACTION_BAR ( bar ) ) {
gtk_box_append ( GTK_BOX ( self - > primary_layout ) , GTK_WIDGET ( bar ) ) ; // Add the action
}
}
2021-02-09 17:37:26 +02:00
self - > player_bar = koto_playerbar_new ( ) ;
2021-05-07 16:45:57 +03:00
if ( KOTO_IS_PLAYERBAR ( self - > player_bar ) ) { // Is a playerbar
2021-02-24 20:17:18 +02:00
GtkWidget * playerbar_main = koto_playerbar_get_main ( self - > player_bar ) ;
gtk_box_append ( GTK_BOX ( self - > primary_layout ) , playerbar_main ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-07 13:17:33 +03:00
gtk_window_set_child ( GTK_WINDOW ( self ) , self - > overlay ) ;
2021-02-25 18:15:36 +02:00
# ifdef GDK_WINDOWING_X11
set_optimal_default_window_size ( self ) ;
# endif
2021-02-12 12:56:41 +02:00
gtk_window_set_title ( GTK_WINDOW ( self ) , " Koto " ) ;
gtk_window_set_icon_name ( GTK_WINDOW ( self ) , " audio-headphones " ) ;
2021-02-24 20:17:18 +02:00
gtk_window_set_startup_id ( GTK_WINDOW ( self ) , " com.github.joshstrobl.koto " ) ;
2021-03-09 11:45:44 +02:00
gtk_widget_queue_draw ( self - > content_layout ) ;
2021-02-24 20:17:18 +02:00
g_thread_new ( " load-library " , ( void * ) load_library , self ) ;
}
2021-05-07 16:45:57 +03:00
void koto_window_add_page ( KotoWindow * self , gchar * page_name , GtkWidget * page ) {
gtk_stack_add_named ( GTK_STACK ( self - > pages ) , page , page_name ) ;
}
void koto_window_go_to_page ( KotoWindow * self , gchar * page_name ) {
gtk_stack_set_visible_child_name ( GTK_STACK ( self - > pages ) , page_name ) ;
}
void koto_window_handle_playlist_added ( KotoCartographer * carto , KotoPlaylist * playlist , gpointer user_data ) {
( void ) carto ;
if ( ! KOTO_IS_PLAYLIST ( playlist ) ) {
return ;
}
KotoWindow * self = user_data ;
gchar * playlist_uuid = koto_playlist_get_uuid ( playlist ) ;
KotoPlaylistPage * playlist_page = koto_playlist_page_new ( playlist_uuid ) ; // Create our new Playlist Page
koto_window_add_page ( self , playlist_uuid , koto_playlist_page_get_main ( playlist_page ) ) ; // Get the GtkScrolledWindow "main" content of the playlist page and add that as a page to our stack by the playlist UUID
}
void koto_window_hide_dialogs ( KotoWindow * self ) {
koto_dialog_container_hide ( self - > dialogs ) ; // Hide the dialog container
}
void koto_window_remove_page ( KotoWindow * self , gchar * page_name ) {
GtkWidget * page = gtk_stack_get_child_by_name ( GTK_STACK ( self - > pages ) , page_name ) ;
g_return_if_fail ( page ! = NULL ) ;
gtk_stack_remove ( GTK_STACK ( self - > pages ) , page ) ;
}
void koto_window_show_dialog ( KotoWindow * self , gchar * dialog_name ) {
koto_dialog_container_show_dialog ( self - > dialogs , dialog_name ) ;
}
2021-02-24 20:17:18 +02:00
void create_new_headerbar ( KotoWindow * self ) {
self - > header_bar = gtk_header_bar_new ( ) ;
2021-02-25 18:15:36 +02:00
gtk_widget_add_css_class ( self - > header_bar , " hdr " ) ;
2021-02-24 20:17:18 +02:00
g_return_if_fail ( GTK_IS_HEADER_BAR ( self - > header_bar ) ) ;
self - > menu_button = gtk_button_new_from_icon_name ( " audio-headphones " ) ;
self - > search_entry = gtk_search_entry_new ( ) ;
gtk_widget_add_css_class ( self - > menu_button , " flat " ) ;
gtk_widget_set_can_focus ( self - > search_entry , TRUE ) ;
gtk_widget_set_size_request ( self - > search_entry , 400 , - 1 ) ; // Have 400px width
g_object_set ( self - > search_entry , " placeholder-text " , " Search... " , NULL ) ;
gtk_header_bar_pack_start ( GTK_HEADER_BAR ( self - > header_bar ) , self - > menu_button ) ;
gtk_header_bar_set_show_title_buttons ( GTK_HEADER_BAR ( self - > header_bar ) , TRUE ) ;
gtk_header_bar_set_title_widget ( GTK_HEADER_BAR ( self - > header_bar ) , self - > search_entry ) ;
2021-02-09 17:37:26 +02:00
2021-02-24 20:17:18 +02:00
gtk_window_set_titlebar ( GTK_WINDOW ( self ) , self - > header_bar ) ;
2021-02-09 17:37:26 +02:00
}
void load_library ( KotoWindow * self ) {
KotoIndexedLibrary * lib = koto_indexed_library_new ( g_get_user_special_dir ( G_USER_DIRECTORY_MUSIC ) ) ;
if ( lib ! = NULL ) {
self - > library = lib ;
2021-05-07 16:45:57 +03:00
music_local_page = koto_page_music_local_new ( ) ;
2021-02-24 20:17:18 +02:00
2021-03-09 11:45:44 +02:00
// TODO: Remove and do some fancy state loading
2021-05-07 16:45:57 +03:00
koto_window_add_page ( self , " music.local " , GTK_WIDGET ( music_local_page ) ) ;
koto_window_go_to_page ( self , " music.local " ) ;
2021-03-09 11:45:44 +02:00
gtk_widget_show ( self - > pages ) ; // Do not remove this. Will cause sporadic hiding of the local page content otherwise.
2021-05-07 16:45:57 +03:00
koto_page_music_local_set_library ( music_local_page , self - > library ) ;
2021-02-09 17:37:26 +02:00
}
2021-03-09 11:45:44 +02:00
g_thread_exit ( 0 ) ;
2021-02-09 17:37:26 +02:00
}
2021-02-25 18:15:36 +02:00
void set_optimal_default_window_size ( KotoWindow * self ) {
GdkDisplay * default_display = gdk_display_get_default ( ) ;
g_return_if_fail ( GDK_IS_X11_DISPLAY ( default_display ) ) ;
GdkMonitor * default_monitor = gdk_x11_display_get_primary_monitor ( GDK_X11_DISPLAY ( default_display ) ) ; // Get primary monitor for the X11
g_return_if_fail ( default_monitor ) ;
GdkRectangle workarea = { 0 } ;
gdk_monitor_get_geometry ( default_monitor , & workarea ) ;
if ( workarea . width < = 1280 ) { // Honestly how do you even get anything done?
gtk_widget_set_size_request ( GTK_WIDGET ( self ) , 1200 , 675 ) ;
} else if ( ( workarea . width > 1280 ) & & ( workarea . width < = 1600 ) ) { // Plebian monitor resolution
2021-02-27 17:53:59 +02:00
gtk_widget_set_size_request ( GTK_WIDGET ( self ) , 1300 , 709 ) ;
2021-02-25 18:15:36 +02:00
} else if ( ( workarea . width > 1600 ) & & ( workarea . width < = 1920 ) ) { // Something slightly normal
gtk_widget_set_size_request ( GTK_WIDGET ( self ) , 1600 , 900 ) ;
} else if ( ( workarea . width > 1920 ) & & ( workarea . width < = 2560 ) ) { // Well aren't you hot stuff?
gtk_widget_set_size_request ( GTK_WIDGET ( self ) , 1920 , 1080 ) ;
} else { // Now you're just flexing
2021-02-27 18:00:45 +02:00
gtk_widget_set_size_request ( GTK_WIDGET ( self ) , 2560 , 1440 ) ;
2021-02-25 18:15:36 +02:00
}
}