2021-02-09 17:37:26 +02:00
/* koto-playerbar.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-03-23 19:50:09 +02:00
# include <gstreamer-1.0/gst/gst.h>
2021-02-24 20:17:18 +02:00
# include <gtk-4.0/gtk/gtk.h>
2021-05-27 12:56:36 +03:00
# include "config/config.h"
2021-03-25 17:29:45 +02:00
# include "db/cartographer.h"
2021-05-07 16:45:57 +03:00
# include "playlist/add-remove-track-popover.h"
2021-04-06 10:41:15 +03:00
# include "playlist/current.h"
# include "playlist/playlist.h"
2021-03-23 19:50:09 +02:00
# include "playback/engine.h"
2021-02-12 12:56:41 +02:00
# include "koto-button.h"
2021-05-27 12:56:36 +03:00
# include "config/config.h"
2021-02-09 17:37:26 +02:00
# include "koto-playerbar.h"
2021-05-11 20:05:04 +03:00
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup ;
extern KotoCartographer * koto_maps ;
2021-05-27 13:03:24 +03:00
extern KotoConfig * config ;
2021-05-27 12:56:36 +03:00
extern KotoCurrentPlaylist * current_playlist ;
2021-05-11 20:05:04 +03:00
extern KotoPlaybackEngine * playback_engine ;
2021-03-23 19:50:09 +02:00
2021-02-09 17:37:26 +02:00
struct _KotoPlayerBar {
2021-02-24 20:17:18 +02:00
GObject parent_instance ;
2021-05-11 20:05:04 +03:00
GtkWidget * main ;
GtkWidget * controls ;
2021-02-09 17:37:26 +02:00
/* Sections */
2021-05-11 20:05:04 +03:00
GtkWidget * playback_section ;
GtkWidget * primary_controls_section ;
GtkWidget * secondary_controls_section ;
2021-02-09 17:37:26 +02:00
/* Primary Buttons */
2021-05-11 20:05:04 +03:00
KotoButton * back_button ;
KotoButton * play_pause_button ;
KotoButton * forward_button ;
KotoButton * repeat_button ;
KotoButton * shuffle_button ;
KotoButton * playlist_button ;
KotoButton * eq_button ;
GtkWidget * volume_button ;
2021-02-09 17:37:26 +02:00
2021-05-11 20:05:04 +03:00
GtkWidget * progress_bar ;
2021-03-23 19:50:09 +02:00
2021-02-09 17:37:26 +02:00
/* Selected Playback Section */
2021-05-11 20:05:04 +03:00
GtkWidget * playback_details_section ;
GtkWidget * artwork ;
GtkWidget * playback_title ;
GtkWidget * playback_album ;
GtkWidget * playback_artist ;
2021-03-25 17:29:45 +02:00
gint64 last_recorded_duration ;
gboolean is_progressbar_seeking ;
2021-02-09 17:37:26 +02:00
} ;
struct _KotoPlayerBarClass {
2021-02-24 20:17:18 +02:00
GObjectClass parent_class ;
2021-02-09 17:37:26 +02:00
} ;
2021-02-24 20:17:18 +02:00
G_DEFINE_TYPE ( KotoPlayerBar , koto_playerbar , G_TYPE_OBJECT ) ;
2021-02-09 17:37:26 +02:00
2021-05-11 20:05:04 +03:00
static void koto_playerbar_constructed ( GObject * obj ) ;
static void koto_playerbar_class_init ( KotoPlayerBarClass * c ) {
GObjectClass * gobject_class ;
2021-02-09 17:37:26 +02:00
gobject_class = G_OBJECT_CLASS ( c ) ;
gobject_class - > constructed = koto_playerbar_constructed ;
}
2021-05-11 20:05:04 +03:00
static void koto_playerbar_constructed ( GObject * obj ) {
KotoPlayerBar * self = KOTO_PLAYERBAR ( obj ) ;
2021-03-23 19:50:09 +02:00
self - > main = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 0 ) ;
2021-05-07 16:45:57 +03:00
gtk_widget_add_css_class ( self - > main , " player-bar " ) ;
2021-03-23 19:50:09 +02:00
self - > progress_bar = gtk_scale_new_with_range ( GTK_ORIENTATION_HORIZONTAL , 0 , 120 , 1 ) ; // Default to 120 as random max
2021-05-07 16:45:57 +03:00
2021-03-23 19:50:09 +02:00
gtk_scale_set_draw_value ( GTK_SCALE ( self - > progress_bar ) , FALSE ) ;
gtk_scale_set_digits ( GTK_SCALE ( self - > progress_bar ) , 0 ) ;
gtk_range_set_increments ( GTK_RANGE ( self - > progress_bar ) , 1 , 1 ) ;
2021-03-25 17:29:45 +02:00
gtk_range_set_round_digits ( GTK_RANGE ( self - > progress_bar ) , 1 ) ;
2021-05-11 20:05:04 +03:00
GtkGesture * press_controller = gtk_gesture_click_new ( ) ; // Create a new GtkGestureLongPress
2021-04-06 10:41:15 +03:00
gtk_gesture_single_set_button ( GTK_GESTURE_SINGLE ( press_controller ) , 1 ) ; // Set to left click
2021-04-07 13:17:33 +03:00
g_signal_connect ( press_controller , " begin " , G_CALLBACK ( koto_playerbar_handle_progressbar_gesture_begin ) , self ) ;
g_signal_connect ( press_controller , " end " , G_CALLBACK ( koto_playerbar_handle_progressbar_gesture_end ) , self ) ;
2021-03-25 17:29:45 +02:00
g_signal_connect ( press_controller , " pressed " , G_CALLBACK ( koto_playerbar_handle_progressbar_pressed ) , self ) ;
2021-04-06 10:41:15 +03:00
2021-03-25 17:29:45 +02:00
gtk_widget_add_controller ( GTK_WIDGET ( self - > progress_bar ) , GTK_EVENT_CONTROLLER ( press_controller ) ) ;
g_signal_connect ( GTK_RANGE ( self - > progress_bar ) , " value-changed " , G_CALLBACK ( koto_playerbar_handle_progressbar_value_changed ) , self ) ;
2021-03-23 19:50:09 +02:00
self - > controls = gtk_center_box_new ( ) ;
gtk_center_box_set_baseline_position ( GTK_CENTER_BOX ( self - > controls ) , GTK_BASELINE_POSITION_CENTER ) ;
2021-02-24 20:17:18 +02:00
2021-02-09 17:37:26 +02:00
self - > primary_controls_section = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
2021-05-07 16:45:57 +03:00
gtk_widget_add_css_class ( self - > primary_controls_section , " playerbar-primary-controls " ) ;
self - > playback_section = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
gtk_widget_add_css_class ( self - > playback_section , " playerbar-info " ) ;
2021-02-09 17:37:26 +02:00
self - > secondary_controls_section = gtk_box_new ( GTK_ORIENTATION_HORIZONTAL , 0 ) ;
2021-05-07 16:45:57 +03:00
gtk_widget_add_css_class ( self - > secondary_controls_section , " playerbar-secondary-controls " ) ;
2021-02-09 17:37:26 +02:00
2021-03-23 19:50:09 +02:00
gtk_center_box_set_start_widget ( GTK_CENTER_BOX ( self - > controls ) , GTK_WIDGET ( self - > primary_controls_section ) ) ;
gtk_center_box_set_center_widget ( GTK_CENTER_BOX ( self - > controls ) , GTK_WIDGET ( self - > playback_section ) ) ;
gtk_center_box_set_end_widget ( GTK_CENTER_BOX ( self - > controls ) , GTK_WIDGET ( self - > secondary_controls_section ) ) ;
2021-02-09 17:37:26 +02:00
koto_playerbar_create_playback_details ( self ) ;
koto_playerbar_create_primary_controls ( self ) ;
koto_playerbar_create_secondary_controls ( self ) ;
2021-03-23 19:50:09 +02:00
gtk_box_prepend ( GTK_BOX ( self - > main ) , self - > progress_bar ) ;
gtk_box_append ( GTK_BOX ( self - > main ) , self - > controls ) ;
2021-02-24 20:17:18 +02:00
gtk_widget_set_hexpand ( GTK_WIDGET ( self - > main ) , TRUE ) ;
2021-03-23 19:50:09 +02:00
2021-05-27 12:56:36 +03:00
// Set up our volume and other playback state bits from our config
koto_playerbar_apply_configuration_state ( config , 0 , self ) ;
2021-03-23 19:50:09 +02:00
// Set up the bindings
2021-05-27 12:56:36 +03:00
g_signal_connect ( config , " notify::playback-last-used-volume " , G_CALLBACK ( koto_playerbar_apply_configuration_state ) , self ) ; // Bind onto the playback last used volume config option
2021-03-25 17:29:45 +02:00
g_signal_connect ( playback_engine , " is-playing " , G_CALLBACK ( koto_playerbar_handle_is_playing ) , self ) ;
g_signal_connect ( playback_engine , " is-paused " , G_CALLBACK ( koto_playerbar_handle_is_paused ) , 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 , " track-changed " , G_CALLBACK ( koto_playerbar_update_track_info ) , self ) ;
2021-04-06 13:56:29 +03:00
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 ) ;
2021-02-09 17:37:26 +02:00
}
2021-05-11 20:05:04 +03:00
static void koto_playerbar_init ( KotoPlayerBar * self ) {
2021-03-25 17:29:45 +02:00
self - > last_recorded_duration = 0 ;
self - > is_progressbar_seeking = FALSE ;
2021-02-09 17:37:26 +02:00
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * koto_playerbar_new ( void ) {
2021-02-24 20:17:18 +02:00
return g_object_new ( KOTO_TYPE_PLAYERBAR , NULL ) ;
2021-02-09 17:37:26 +02:00
}
2021-05-27 12:56:36 +03:00
void koto_playerbar_apply_configuration_state (
KotoConfig * config ,
guint prop_id ,
KotoPlayerBar * self
) {
( void ) prop_id ;
gdouble config_last_used_volume = 0 ;
g_object_get (
config ,
" playback-last-used-volume " ,
& config_last_used_volume ,
NULL
) ;
gtk_scale_button_set_value ( GTK_SCALE_BUTTON ( self - > volume_button ) , config_last_used_volume ) ;
}
2021-02-09 17:37:26 +02:00
void koto_playerbar_create_playback_details ( KotoPlayerBar * bar ) {
bar - > playback_details_section = gtk_box_new ( GTK_ORIENTATION_VERTICAL , 0 ) ;
2021-05-11 20:05:04 +03:00
GtkIconTheme * default_icon_theme = gtk_icon_theme_get_for_display ( gdk_display_get_default ( ) ) ; // Get the icon theme for this display
2021-02-09 17:37:26 +02:00
if ( default_icon_theme ! = NULL ) {
2021-02-27 17:26:24 +02:00
gint scale_factor = gtk_widget_get_scale_factor ( GTK_WIDGET ( bar - > main ) ) ;
2021-02-24 20:17:18 +02:00
GtkIconPaintable * audio_paintable = gtk_icon_theme_lookup_icon ( default_icon_theme , " audio-x-generic-symbolic " , NULL , 96 , scale_factor , GTK_TEXT_DIR_NONE , GTK_ICON_LOOKUP_PRELOAD ) ;
if ( GTK_IS_ICON_PAINTABLE ( audio_paintable ) ) {
if ( GTK_IS_IMAGE ( bar - > artwork ) ) {
gtk_image_set_from_paintable ( GTK_IMAGE ( bar - > artwork ) , GDK_PAINTABLE ( audio_paintable ) ) ;
} else { // Not an image
bar - > artwork = gtk_image_new_from_paintable ( GDK_PAINTABLE ( audio_paintable ) ) ;
2021-05-07 16:45:57 +03:00
gtk_widget_add_css_class ( bar - > artwork , " circular " ) ;
2021-02-24 20:17:18 +02:00
gtk_widget_set_size_request ( bar - > artwork , 96 , 96 ) ;
gtk_box_append ( GTK_BOX ( bar - > playback_section ) , bar - > artwork ) ;
}
2021-02-09 17:37:26 +02:00
}
}
2021-02-12 12:56:41 +02:00
bar - > playback_title = gtk_label_new ( " Title " ) ;
2021-05-07 16:45:57 +03:00
gtk_label_set_xalign ( GTK_LABEL ( bar - > playback_title ) , 0 ) ;
2021-02-12 12:56:41 +02:00
bar - > playback_album = gtk_label_new ( " Album " ) ;
2021-05-07 16:45:57 +03:00
gtk_label_set_xalign ( GTK_LABEL ( bar - > playback_album ) , 0 ) ;
2021-02-12 12:56:41 +02:00
bar - > playback_artist = gtk_label_new ( " Artist " ) ;
2021-05-07 16:45:57 +03:00
gtk_label_set_xalign ( GTK_LABEL ( bar - > playback_artist ) , 0 ) ;
2021-02-09 17:37:26 +02:00
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > playback_details_section ) , GTK_WIDGET ( bar - > playback_title ) ) ;
gtk_box_append ( GTK_BOX ( bar - > playback_details_section ) , GTK_WIDGET ( bar - > playback_album ) ) ;
gtk_box_append ( GTK_BOX ( bar - > playback_details_section ) , GTK_WIDGET ( bar - > playback_artist ) ) ;
2021-02-09 17:37:26 +02:00
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > playback_section ) , GTK_WIDGET ( bar - > playback_details_section ) ) ;
2021-02-09 17:37:26 +02:00
}
void koto_playerbar_create_primary_controls ( KotoPlayerBar * bar ) {
2021-02-25 18:15:36 +02:00
bar - > back_button = koto_button_new_with_icon ( " " , " media-skip-backward-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
2021-03-10 13:44:08 +02:00
bar - > play_pause_button = koto_button_new_with_icon ( " " , " media-playback-start-symbolic " , " media-playback-pause-symbolic " , KOTO_BUTTON_PIXBUF_SIZE_LARGE ) ; // TODO: Have this take in a state and switch to a different icon if necessary
2021-02-25 18:15:36 +02:00
bar - > forward_button = koto_button_new_with_icon ( " " , " media-skip-forward-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
2021-02-09 17:37:26 +02:00
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > back_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > primary_controls_section ) , GTK_WIDGET ( bar - > back_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > back_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_go_backwards ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > play_pause_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > primary_controls_section ) , GTK_WIDGET ( bar - > play_pause_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > play_pause_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_toggle_play_pause ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
2021-03-23 19:50:09 +02:00
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > forward_button ) ) {
gtk_box_append ( GTK_BOX ( bar - > primary_controls_section ) , GTK_WIDGET ( bar - > forward_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > forward_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_go_forwards ) , bar ) ;
2021-04-06 10:41:15 +03:00
}
2021-02-09 17:37:26 +02:00
}
void koto_playerbar_create_secondary_controls ( KotoPlayerBar * bar ) {
2021-02-25 18:15:36 +02:00
bar - > repeat_button = koto_button_new_with_icon ( " " , " media-playlist-repeat-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
bar - > shuffle_button = koto_button_new_with_icon ( " " , " media-playlist-shuffle-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
bar - > playlist_button = koto_button_new_with_icon ( " " , " playlist-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
bar - > eq_button = koto_button_new_with_icon ( " " , " multimedia-equalizer-symbolic " , NULL , KOTO_BUTTON_PIXBUF_SIZE_NORMAL ) ;
2021-02-09 17:37:26 +02:00
2021-04-06 10:41:15 +03:00
bar - > volume_button = gtk_volume_button_new ( ) ; // Have this take in a state and switch to a different icon if necessary
2021-03-25 17:29:45 +02:00
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > repeat_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > secondary_controls_section ) , GTK_WIDGET ( bar - > repeat_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > repeat_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_toggle_track_repeat ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > shuffle_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > secondary_controls_section ) , GTK_WIDGET ( bar - > shuffle_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > shuffle_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_toggle_playlist_shuffle ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > playlist_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > secondary_controls_section ) , GTK_WIDGET ( bar - > playlist_button ) ) ;
2021-05-07 16:45:57 +03:00
koto_button_add_click_handler ( bar - > playlist_button , KOTO_BUTTON_CLICK_TYPE_PRIMARY , G_CALLBACK ( koto_playerbar_handle_playlist_button_clicked ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-06 10:41:15 +03:00
if ( KOTO_IS_BUTTON ( bar - > eq_button ) ) {
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > secondary_controls_section ) , GTK_WIDGET ( bar - > eq_button ) ) ;
2021-02-09 17:37:26 +02:00
}
2021-04-06 10:41:15 +03:00
if ( GTK_IS_VOLUME_BUTTON ( bar - > volume_button ) ) {
2021-05-11 20:05:04 +03:00
GtkAdjustment * granular_volume_change = gtk_adjustment_new ( 0.5 , 0 , 1.0 , 0.02 , 0.02 , 0.02 ) ;
2021-04-06 10:41:15 +03:00
g_object_set ( bar - > volume_button , " use-symbolic " , TRUE , NULL ) ;
gtk_scale_button_set_adjustment ( GTK_SCALE_BUTTON ( bar - > volume_button ) , granular_volume_change ) ; // Set our adjustment
2021-02-24 20:17:18 +02:00
gtk_box_append ( GTK_BOX ( bar - > secondary_controls_section ) , bar - > volume_button ) ;
2021-04-06 10:41:15 +03:00
g_signal_connect ( GTK_SCALE_BUTTON ( bar - > volume_button ) , " value-changed " , G_CALLBACK ( koto_playerbar_handle_volume_button_change ) , bar ) ;
2021-02-09 17:37:26 +02:00
}
}
2021-02-24 20:17:18 +02:00
2021-05-11 20:05:04 +03:00
void koto_playerbar_go_backwards (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
( void ) data ;
2021-03-23 19:50:09 +02:00
koto_playback_engine_backwards ( playback_engine ) ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_go_forwards (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
( void ) data ;
2021-03-23 19:50:09 +02:00
koto_playback_engine_forwards ( playback_engine ) ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_is_playing (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-03-23 19:50:09 +02:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
koto_button_show_image ( bar - > play_pause_button , TRUE ) ; // Set to TRUE to show pause as the next action
2021-03-23 19:50:09 +02:00
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_is_paused (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-03-23 19:50:09 +02:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-03-23 19:50:09 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
2021-03-25 17:29:45 +02:00
koto_button_show_image ( bar - > play_pause_button , FALSE ) ; // Set to FALSE to show play as the next action
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_playlist_button_clicked (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
KotoPlayerBar * self = data ;
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_PLAYERBAR ( self ) ) { // Not a playerbar
return ;
}
koto_add_remove_track_popover_set_pointing_to_widget ( koto_add_remove_track_popup , GTK_WIDGET ( self - > playlist_button ) , GTK_POS_TOP ) ; // Position above the playlist button
gtk_widget_show ( GTK_WIDGET ( koto_add_remove_track_popup ) ) ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_progressbar_gesture_begin (
GtkGesture * gesture ,
GdkEventSequence * seq ,
gpointer data
) {
( void ) gesture ;
( void ) seq ;
KotoPlayerBar * bar = data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
bar - > is_progressbar_seeking = TRUE ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_progressbar_gesture_end (
GtkGesture * gesture ,
GdkEventSequence * seq ,
gpointer data
) {
( void ) gesture ;
( void ) seq ;
KotoPlayerBar * bar = data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
bar - > is_progressbar_seeking = FALSE ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_progressbar_pressed (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
KotoPlayerBar * bar = data ;
2021-04-06 10:41:15 +03:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
bar - > is_progressbar_seeking = TRUE ;
}
2021-03-25 17:29:45 +02:00
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_progressbar_value_changed (
GtkRange * progress_bar ,
gpointer data
) {
KotoPlayerBar * bar = data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
if ( ! bar - > is_progressbar_seeking ) {
return ;
}
2021-03-23 19:50:09 +02:00
2021-03-25 17:29:45 +02:00
int desired_position = ( int ) gtk_range_get_value ( progress_bar ) ;
2021-05-11 20:05:04 +03:00
2021-03-25 17:29:45 +02:00
koto_playback_engine_set_position ( playback_engine , desired_position ) ; // Update our position
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_tick_duration (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
2021-03-23 19:50:09 +02:00
}
2021-03-25 17:29:45 +02:00
koto_playerbar_set_progressbar_duration ( bar , koto_playback_engine_get_duration ( engine ) ) ;
2021-03-23 19:50:09 +02:00
}
2021-03-25 17:29:45 +02:00
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_tick_track (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-03-23 19:50:09 +02:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
if ( ! bar - > is_progressbar_seeking ) {
koto_playerbar_set_progressbar_value ( bar , koto_playback_engine_get_progress ( engine ) ) ;
}
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_track_repeat (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-04-06 13:56:29 +03:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-04-06 13:56:29 +03:00
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
}
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_track_shuffle (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-04-06 13:56:29 +03:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-04-06 13:56:29 +03:00
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
}
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_handle_volume_button_change (
GtkScaleButton * button ,
double value ,
gpointer user_data
) {
( void ) button ;
( void ) user_data ;
2021-03-25 17:29:45 +02:00
koto_playback_engine_set_volume ( playback_engine , value ) ;
2021-03-23 19:50:09 +02:00
}
void koto_playerbar_reset_progressbar ( KotoPlayerBar * bar ) {
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
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_set_progressbar_duration (
KotoPlayerBar * bar ,
gint64 duration
) {
2021-03-25 17:29:45 +02:00
if ( duration < = 0 ) {
2021-03-23 19:50:09 +02:00
return ;
}
2021-03-25 17:29:45 +02:00
if ( duration ! = bar - > last_recorded_duration ) { // Duration is different than what we recorded
bar - > last_recorded_duration = duration ;
gtk_range_set_range ( GTK_RANGE ( bar - > progress_bar ) , 0 , bar - > last_recorded_duration ) ;
}
2021-03-23 19:50:09 +02:00
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_set_progressbar_value (
KotoPlayerBar * bar ,
double progress
) {
2021-03-23 19:50:09 +02:00
gtk_range_set_value ( GTK_RANGE ( bar - > progress_bar ) , progress ) ;
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_toggle_play_pause (
GtkGestureClick * gesture ,
int n_press ,
double x ,
double y ,
gpointer data
) {
( void ) gesture ;
( void ) n_press ;
( void ) x ;
( void ) y ;
( void ) data ;
2021-03-23 19:50:09 +02:00
koto_playback_engine_toggle ( playback_engine ) ;
}
2021-05-11 20:05:04 +03:00
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 ) data ;
2021-04-06 10:41:15 +03:00
2021-04-06 13:56:29 +03:00
koto_playback_engine_toggle_track_shuffle ( playback_engine ) ; // Call our playback engine's toggle track shuffle function
2021-04-06 10:41:15 +03:00
}
2021-05-11 20:05:04 +03:00
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 ) data ;
2021-04-06 13:56:29 +03:00
koto_playback_engine_toggle_track_repeat ( playback_engine ) ; // Call our playback engine's toggle track repeat function
2021-04-06 10:41:15 +03:00
}
2021-05-11 20:05:04 +03:00
void koto_playerbar_update_track_info (
KotoPlaybackEngine * engine ,
gpointer user_data
) {
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYBACK_ENGINE ( engine ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
KotoPlayerBar * bar = user_data ;
2021-03-25 17:29:45 +02:00
if ( ! KOTO_IS_PLAYERBAR ( bar ) ) {
return ;
}
2021-05-11 20:08:39 +03:00
KotoTrack * current_track = koto_playback_engine_get_current_track ( playback_engine ) ; // Get the current track from the playback engine
2021-05-11 20:05:04 +03:00
2021-03-25 17:29:45 +02:00
2021-05-11 20:08:39 +03:00
if ( ! KOTO_IS_TRACK ( current_track ) ) {
2021-03-25 17:29:45 +02:00
return ;
}
2021-05-11 20:05:04 +03:00
gchar * track_name = NULL ;
gchar * artist_uuid = NULL ;
gchar * album_uuid = NULL ;
2021-03-25 17:29:45 +02:00
g_object_get ( current_track , " parsed-name " , & track_name , " artist-uuid " , & artist_uuid , " album-uuid " , & album_uuid , NULL ) ;
2021-05-11 20:08:39 +03:00
KotoArtist * artist = koto_cartographer_get_artist_by_uuid ( koto_maps , artist_uuid ) ;
KotoAlbum * album = koto_cartographer_get_album_by_uuid ( koto_maps , album_uuid ) ;
2021-05-11 20:05:04 +03:00
2021-03-25 17:29:45 +02:00
g_free ( artist_uuid ) ;
g_free ( album_uuid ) ;
if ( ( track_name ! = NULL ) & & ( strcmp ( track_name , " " ) ! = 0 ) ) { // Have a track name
gtk_label_set_text ( GTK_LABEL ( bar - > playback_title ) , track_name ) ; // Set the label
}
2021-05-11 20:08:39 +03:00
if ( KOTO_IS_ARTIST ( artist ) ) {
2021-05-11 20:05:04 +03:00
gchar * artist_name = NULL ;
2021-03-25 17:29:45 +02:00
g_object_get ( artist , " name " , & artist_name , NULL ) ;
if ( ( artist_name ! = NULL ) & & ( strcmp ( artist_name , " " ) ! = 0 ) ) { // Have an artist name
gtk_label_set_text ( GTK_LABEL ( bar - > playback_artist ) , artist_name ) ;
gtk_widget_show ( bar - > playback_artist ) ;
} else { // Don't have an artist name somehow
gtk_widget_hide ( bar - > playback_artist ) ;
}
}
2021-05-11 20:08:39 +03:00
if ( KOTO_IS_ALBUM ( album ) ) {
2021-05-11 20:05:04 +03:00
gchar * album_name = NULL ;
gchar * art_path = NULL ;
2021-03-25 17:29:45 +02:00
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
}
}
}
2021-05-11 20:05:04 +03:00
GtkWidget * koto_playerbar_get_main ( KotoPlayerBar * bar ) {
2021-02-24 20:17:18 +02:00
return bar - > main ;
}