Get to the point where we are fairly happy with our uncrustify config. Fixes #6.
This commit is contained in:
parent
d07d3dfe50
commit
62de9c2032
58 changed files with 4811 additions and 1946 deletions
12
.vscode/tasks.json
vendored
12
.vscode/tasks.json
vendored
|
@ -13,6 +13,18 @@
|
|||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Format",
|
||||
"type": "shell",
|
||||
"command": "uncrustify",
|
||||
"args": [
|
||||
"-c",
|
||||
"jsc.cfg",
|
||||
"--no-backup",
|
||||
"**/*.c",
|
||||
"**/*.h"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Meson Configure and Build",
|
||||
"type": "shell",
|
||||
|
|
44
jsc.cfg
44
jsc.cfg
|
@ -157,27 +157,27 @@ sp_before_ptr_star = ignore # ignore/add/remove/force
|
|||
|
||||
# Add or remove space before pointer star '*' that isn't followed by a
|
||||
# variable name. If set to ignore, sp_before_ptr_star is used instead.
|
||||
sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force
|
||||
sp_before_unnamed_ptr_star = remove # ignore/add/remove/force
|
||||
|
||||
# Add or remove space between pointer stars '*'.
|
||||
sp_between_ptr_star = remove # ignore/add/remove/force
|
||||
sp_between_ptr_star = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after pointer star '*', if followed by a word.
|
||||
#
|
||||
# Overrides sp_type_func.
|
||||
sp_after_ptr_star = remove # ignore/add/remove/force
|
||||
sp_after_ptr_star = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after pointer caret '^', if followed by a word.
|
||||
sp_after_ptr_block_caret = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after pointer star '*', if followed by a qualifier.
|
||||
sp_after_ptr_star_qualifier = remove # ignore/add/remove/force
|
||||
sp_after_ptr_star_qualifier = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after a pointer star '*', if followed by a function
|
||||
# prototype or function definition.
|
||||
#
|
||||
# Overrides sp_after_ptr_star and sp_type_func.
|
||||
sp_after_ptr_star_func = remove # ignore/add/remove/force
|
||||
sp_after_ptr_star_func = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove space after a pointer star '*', if followed by an open
|
||||
# parenthesis, as in 'void* (*)().
|
||||
|
@ -1055,7 +1055,7 @@ donot_indent_func_def_close_paren = false # true/false
|
|||
|
||||
# Whether to collapse empty blocks between '{' and '}'.
|
||||
# If true, overrides nl_inside_empty_func
|
||||
nl_collapse_empty_body = true # true/false
|
||||
nl_collapse_empty_body = false # true/false
|
||||
|
||||
# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'.
|
||||
nl_assign_leave_one_liners = false # true/false
|
||||
|
@ -1349,10 +1349,10 @@ nl_func_call_paren = ignore # ignore/add/remove/force
|
|||
nl_func_call_paren_empty = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove newline after '(' in a function declaration.
|
||||
nl_func_decl_start = remove # ignore/add/remove/force
|
||||
nl_func_decl_start = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove newline after '(' in a function definition.
|
||||
nl_func_def_start = remove # ignore/add/remove/force
|
||||
nl_func_def_start = force # ignore/add/remove/force
|
||||
|
||||
# Overrides nl_func_decl_start when there is only one parameter.
|
||||
nl_func_decl_start_single = remove # ignore/add/remove/force
|
||||
|
@ -1369,13 +1369,13 @@ nl_func_decl_start_multi_line = false # true/false
|
|||
nl_func_def_start_multi_line = true # true/false
|
||||
|
||||
# Add or remove newline after each ',' in a function declaration.
|
||||
nl_func_decl_args = ignore # ignore/add/remove/force
|
||||
nl_func_decl_args = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove newline after each ',' in a function definition.
|
||||
nl_func_def_args = remove # ignore/add/remove/force
|
||||
nl_func_def_args = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove newline after each ',' in a function call.
|
||||
nl_func_call_args = ignore # ignore/add/remove/force
|
||||
nl_func_call_args = remove # ignore/add/remove/force
|
||||
|
||||
# Whether to add a newline after each ',' in a function declaration if '('
|
||||
# and ')' are in different lines. If false, nl_func_decl_args is used instead.
|
||||
|
@ -1386,10 +1386,10 @@ nl_func_decl_args_multi_line = true # true/false
|
|||
nl_func_def_args_multi_line = true # true/false
|
||||
|
||||
# Add or remove newline before the ')' in a function declaration.
|
||||
nl_func_decl_end = add # ignore/add/remove/force
|
||||
nl_func_decl_end = force # ignore/add/remove/force
|
||||
|
||||
# Add or remove newline before the ')' in a function definition.
|
||||
nl_func_def_end = ignore # ignore/add/remove/force
|
||||
nl_func_def_end = force # ignore/add/remove/force
|
||||
|
||||
# Overrides nl_func_decl_end when there is only one parameter.
|
||||
nl_func_decl_end_single = remove # ignore/add/remove/force
|
||||
|
@ -1399,7 +1399,7 @@ nl_func_def_end_single = remove # ignore/add/remove/force
|
|||
|
||||
# Whether to add a newline before ')' in a function declaration if '(' and ')'
|
||||
# are in different lines. If false, nl_func_decl_end is used instead.
|
||||
nl_func_decl_end_multi_line = false # true/false
|
||||
nl_func_decl_end_multi_line = true # true/false
|
||||
|
||||
# Whether to add a newline before ')' in a function definition if '(' and ')'
|
||||
# are in different lines. If false, nl_func_def_end is used instead.
|
||||
|
@ -1456,7 +1456,7 @@ nl_fdef_brace_cond = ignore # ignore/add/remove/force
|
|||
nl_return_expr = remove # ignore/add/remove/force
|
||||
|
||||
# Whether to add a newline after semicolons, except in 'for' statements.
|
||||
nl_after_semicolon = false # true/false
|
||||
nl_after_semicolon = true # true/false
|
||||
|
||||
# Whether to add a newline after the type in an unnamed temporary
|
||||
# direct-list-initialization.
|
||||
|
@ -1643,7 +1643,7 @@ nl_before_func_class_proto = 0 # unsigned number
|
|||
nl_before_func_class_def = 0 # unsigned number
|
||||
|
||||
# The number of newlines after a function prototype.
|
||||
nl_after_func_proto = 0 # unsigned number
|
||||
nl_after_func_proto = 2 # unsigned number
|
||||
|
||||
# The number of newlines after a function prototype, if not followed by
|
||||
# another function prototype.
|
||||
|
@ -1734,13 +1734,13 @@ nl_after_multiline_comment = false # true/false
|
|||
nl_after_label_colon = false # true/false
|
||||
|
||||
# The number of newlines after '}' or ';' of a struct/enum/union definition.
|
||||
nl_after_struct = 0 # unsigned number
|
||||
nl_after_struct = 1 # unsigned number
|
||||
|
||||
# The number of newlines before a class definition.
|
||||
nl_before_class = 0 # unsigned number
|
||||
|
||||
# The number of newlines after '}' or ';' of a class definition.
|
||||
nl_after_class = 0 # unsigned number
|
||||
nl_after_class = 1 # unsigned number
|
||||
|
||||
# The number of newlines before a namespace.
|
||||
nl_before_namespace = 0 # unsigned number
|
||||
|
@ -2291,9 +2291,6 @@ mod_full_brace_do = ignore # ignore/add/remove/force
|
|||
# Add or remove braces on a single-line 'for' statement.
|
||||
mod_full_brace_for = ignore # ignore/add/remove/force
|
||||
|
||||
# (Pawn) Add or remove braces on a single-line function definition.
|
||||
mod_full_brace_function = ignore # ignore/add/remove/force
|
||||
|
||||
# Add or remove braces on a single-line 'if' statement. Braces will not be
|
||||
# removed if the braced statement contains an 'else'.
|
||||
mod_full_brace_if = ignore # ignore/add/remove/force
|
||||
|
@ -2337,10 +2334,7 @@ mod_full_brace_nl = 0 # unsigned number
|
|||
mod_full_brace_nl_block_rem_mlcond = false # true/false
|
||||
|
||||
# Add or remove unnecessary parenthesis on 'return' statement.
|
||||
mod_paren_on_return = ignore # ignore/add/remove/force
|
||||
|
||||
# (Pawn) Whether to change optional semicolons to real semicolons.
|
||||
mod_pawn_semicolon = false # true/false
|
||||
mod_paren_on_return = ignore # ignore/add/remove/force´
|
||||
|
||||
# Whether to fully parenthesize Boolean expressions in 'while' and 'if'
|
||||
# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'.
|
||||
|
|
|
@ -37,7 +37,9 @@ enum {
|
|||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint actionbar_signals[N_SIGNALS] = { 0 };
|
||||
static guint actionbar_signals[N_SIGNALS] = {
|
||||
0
|
||||
};
|
||||
|
||||
struct _KotoActionBar {
|
||||
GObject parent_instance;
|
||||
|
@ -73,6 +75,7 @@ KotoActionBar* action_bar;
|
|||
static void koto_action_bar_class_init(KotoActionBarClass * c) {
|
||||
GObjectClass * gobject_class = G_OBJECT_CLASS(c);
|
||||
|
||||
|
||||
actionbar_signals[SIGNAL_CLOSED] = g_signal_new(
|
||||
"closed",
|
||||
G_TYPE_FROM_CLASS(gobject_class),
|
||||
|
@ -159,15 +162,28 @@ GtkActionBar* koto_action_bar_get_main(KotoActionBar *self) {
|
|||
return self->main;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
koto_action_bar_close(data);
|
||||
}
|
||||
|
||||
void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpointer data) {
|
||||
void koto_action_bar_handle_go_to_artist_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
) {
|
||||
(void) button;
|
||||
KotoActionBar * self = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -178,11 +194,14 @@ void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpoin
|
|||
|
||||
KotoIndexedTrack * selected_track = g_list_nth_data(self->current_list, 0); // Get the first item
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(selected_track)) { // Not a track
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(
|
||||
selected_track,
|
||||
"artist-uuid",
|
||||
|
@ -194,10 +213,14 @@ void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpoin
|
|||
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
|
||||
}
|
||||
void koto_action_bar_handle_playlists_button_clicked(GtkButton *button, gpointer data) {
|
||||
void koto_action_bar_handle_playlists_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
) {
|
||||
(void) button;
|
||||
KotoActionBar * self = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -211,10 +234,14 @@ void koto_action_bar_handle_playlists_button_clicked(GtkButton *button, gpointer
|
|||
gtk_widget_show(GTK_WIDGET(koto_add_remove_track_popup));
|
||||
}
|
||||
|
||||
void koto_action_bar_handle_play_track_button_clicked(GtkButton *button, gpointer data) {
|
||||
void koto_action_bar_handle_play_track_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
) {
|
||||
(void) button;
|
||||
KotoActionBar * self = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -225,6 +252,7 @@ void koto_action_bar_handle_play_track_button_clicked(GtkButton *button, gpointe
|
|||
|
||||
KotoIndexedTrack * track = g_list_nth_data(self->current_list, 0); // Get the first track
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||
goto doclose;
|
||||
}
|
||||
|
@ -235,10 +263,14 @@ doclose:
|
|||
koto_action_bar_close(self);
|
||||
}
|
||||
|
||||
void koto_action_bar_handle_remove_from_playlist_button_clicked(GtkButton *button, gpointer data) {
|
||||
void koto_action_bar_handle_remove_from_playlist_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
) {
|
||||
(void) button;
|
||||
KotoActionBar * self = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -253,11 +285,14 @@ void koto_action_bar_handle_remove_from_playlist_button_clicked(GtkButton *butto
|
|||
|
||||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->current_playlist_uuid);
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Not a playlist
|
||||
goto doclose;
|
||||
}
|
||||
|
||||
GList * cur_list;
|
||||
|
||||
|
||||
for (cur_list = self->current_list; cur_list != NULL; cur_list = cur_list->next) { // For each KotoIndexedTrack
|
||||
KotoIndexedTrack * track = cur_list->data;
|
||||
koto_playlist_remove_track_by_uuid(playlist, koto_indexed_track_get_uuid(track)); // Remove this track
|
||||
|
@ -267,7 +302,11 @@ doclose:
|
|||
koto_action_bar_close(self);
|
||||
}
|
||||
|
||||
void koto_action_bar_set_tracks_in_album_selection(KotoActionBar *self, gchar *album_uuid, GList *tracks) {
|
||||
void koto_action_bar_set_tracks_in_album_selection(
|
||||
KotoActionBar * self,
|
||||
gchar * album_uuid,
|
||||
GList * tracks
|
||||
) {
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -297,7 +336,11 @@ void koto_action_bar_set_tracks_in_album_selection(KotoActionBar *self, gchar *a
|
|||
gtk_widget_hide(GTK_WIDGET(self->remove_from_playlist));
|
||||
}
|
||||
|
||||
void koto_action_bar_set_tracks_in_playlist_selection(KotoActionBar *self, gchar *playlist_uuid, GList *tracks) {
|
||||
void koto_action_bar_set_tracks_in_playlist_selection(
|
||||
KotoActionBar * self,
|
||||
gchar * playlist_uuid,
|
||||
GList * tracks
|
||||
) {
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -318,13 +361,18 @@ void koto_action_bar_set_tracks_in_playlist_selection(KotoActionBar *self, gchar
|
|||
self->current_list = g_list_copy(tracks);
|
||||
|
||||
gboolean single_selected = g_list_length(tracks) == 1;
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void koto_action_bar_toggle_go_to_artist_visibility(KotoActionBar *self, gboolean visible) {
|
||||
void koto_action_bar_toggle_go_to_artist_visibility(
|
||||
KotoActionBar * self,
|
||||
gboolean visible
|
||||
) {
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -332,7 +380,10 @@ void koto_action_bar_toggle_go_to_artist_visibility(KotoActionBar *self, gboolea
|
|||
(visible) ? gtk_widget_show(GTK_WIDGET(self->go_to_artist)) : gtk_widget_hide(GTK_WIDGET(self->go_to_artist));
|
||||
}
|
||||
|
||||
void koto_action_bar_toggle_play_button_visibility(KotoActionBar *self, gboolean visible) {
|
||||
void koto_action_bar_toggle_play_button_visibility(
|
||||
KotoActionBar * self,
|
||||
gboolean visible
|
||||
) {
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -340,7 +391,10 @@ void koto_action_bar_toggle_play_button_visibility(KotoActionBar *self, gboolean
|
|||
(visible) ? gtk_widget_show(GTK_WIDGET(self->play_track)) : gtk_widget_hide(GTK_WIDGET(self->play_track));
|
||||
}
|
||||
|
||||
void koto_action_bar_toggle_reveal(KotoActionBar *self, gboolean state) {
|
||||
void koto_action_bar_toggle_reveal(
|
||||
KotoActionBar * self,
|
||||
gboolean state
|
||||
) {
|
||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -42,17 +42,64 @@ GType koto_action_bar_get_type(void) G_GNUC_CONST;
|
|||
**/
|
||||
|
||||
KotoActionBar * koto_action_bar_new(void);
|
||||
|
||||
void koto_action_bar_close(KotoActionBar * self);
|
||||
|
||||
GtkActionBar * koto_action_bar_get_main(KotoActionBar * self);
|
||||
void koto_action_bar_handle_close_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpointer data);
|
||||
void koto_action_bar_handle_playlists_button_clicked(GtkButton *button, gpointer data);
|
||||
void koto_action_bar_handle_play_track_button_clicked(GtkButton *button, gpointer data);
|
||||
void koto_action_bar_handle_remove_from_playlist_button_clicked(GtkButton *button, gpointer data);
|
||||
void koto_action_bar_set_tracks_in_album_selection(KotoActionBar *self, gchar *album_uuid, GList *tracks);
|
||||
void koto_action_bar_set_tracks_in_playlist_selection(KotoActionBar *self, gchar *playlist_uuid, GList *tracks);
|
||||
void koto_action_bar_toggle_go_to_artist_visibility(KotoActionBar *self, gboolean visible);
|
||||
void koto_action_bar_toggle_play_button_visibility(KotoActionBar *self, gboolean visible);
|
||||
void koto_action_bar_toggle_reveal(KotoActionBar *self, gboolean state);
|
||||
|
||||
void koto_action_bar_handle_close_button_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_action_bar_handle_go_to_artist_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_action_bar_handle_playlists_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_action_bar_handle_play_track_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_action_bar_handle_remove_from_playlist_button_clicked(
|
||||
GtkButton * button,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_action_bar_set_tracks_in_album_selection(
|
||||
KotoActionBar * self,
|
||||
gchar * album_uuid,
|
||||
GList * tracks
|
||||
);
|
||||
|
||||
void koto_action_bar_set_tracks_in_playlist_selection(
|
||||
KotoActionBar * self,
|
||||
gchar * playlist_uuid,
|
||||
GList * tracks
|
||||
);
|
||||
|
||||
void koto_action_bar_toggle_go_to_artist_visibility(
|
||||
KotoActionBar * self,
|
||||
gboolean visible
|
||||
);
|
||||
|
||||
void koto_action_bar_toggle_play_button_visibility(
|
||||
KotoActionBar * self,
|
||||
gboolean visible
|
||||
);
|
||||
|
||||
void koto_action_bar_toggle_reveal(
|
||||
KotoActionBar * self,
|
||||
gboolean state
|
||||
);
|
||||
|
||||
G_END_DECLS
|
|
@ -43,12 +43,27 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static void koto_cover_art_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_cover_art_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
static void koto_cover_art_button_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_cover_art_button_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_cover_art_button_class_init(KotoCoverArtButtonClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->get_property = koto_cover_art_button_get_property;
|
||||
gobject_class->set_property = koto_cover_art_button_set_property;
|
||||
|
@ -92,6 +107,8 @@ static void koto_cover_art_button_init(KotoCoverArtButton *self) {
|
|||
gtk_revealer_set_transition_duration(GTK_REVEALER(self->revealer), 400);
|
||||
|
||||
GtkWidget * controls = gtk_center_box_new(); // Create a center box for the controls
|
||||
|
||||
|
||||
self->play_pause_button = koto_button_new_with_icon("", "media-playback-start-symbolic", "media-playback-pause-symbolic", KOTO_BUTTON_PIXBUF_SIZE_NORMAL);
|
||||
gtk_center_box_set_center_widget(GTK_CENTER_BOX(controls), GTK_WIDGET(self->play_pause_button));
|
||||
|
||||
|
@ -100,12 +117,19 @@ static void koto_cover_art_button_init(KotoCoverArtButton *self) {
|
|||
gtk_overlay_add_overlay(GTK_OVERLAY(self->main), self->revealer); // Add our revealer as the overlay
|
||||
|
||||
GtkEventController * motion_controller = gtk_event_controller_motion_new(); // Create our new motion event controller to track mouse leave and enter
|
||||
|
||||
|
||||
g_signal_connect(motion_controller, "enter", G_CALLBACK(koto_cover_art_button_show_overlay_controls), self);
|
||||
g_signal_connect(motion_controller, "leave", G_CALLBACK(koto_cover_art_button_hide_overlay_controls), self);
|
||||
gtk_widget_add_controller(self->main, motion_controller);
|
||||
}
|
||||
|
||||
static void koto_cover_art_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_cover_art_button_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
(void) val;
|
||||
|
||||
switch (prop_id) {
|
||||
|
@ -115,9 +139,15 @@ static void koto_cover_art_button_get_property(GObject *obj, guint prop_id, GVal
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_cover_art_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_cover_art_button_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoCoverArtButton * self = KOTO_COVER_ART_BUTTON(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ART_PATH:
|
||||
koto_cover_art_button_set_art_path(self, (gchar*) g_value_get_string(val)); // Get the value and call our set_art_path with it
|
||||
|
@ -134,9 +164,14 @@ static void koto_cover_art_button_set_property(GObject *obj, guint prop_id, cons
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cover_art_button_hide_overlay_controls(GtkEventControllerFocus *controller, gpointer data) {
|
||||
void koto_cover_art_button_hide_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
) {
|
||||
(void) controller;
|
||||
KotoCoverArtButton* self = data;
|
||||
|
||||
|
||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), FALSE);
|
||||
}
|
||||
|
||||
|
@ -156,13 +191,17 @@ GtkWidget* koto_cover_art_button_get_main(KotoCoverArtButton *self) {
|
|||
return self->main;
|
||||
}
|
||||
|
||||
void koto_cover_art_button_set_art_path(KotoCoverArtButton *self, gchar *art_path) {
|
||||
void koto_cover_art_button_set_art_path(
|
||||
KotoCoverArtButton * self,
|
||||
gchar * art_path
|
||||
) {
|
||||
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gboolean defined_artwork = koto_utils_is_string_valid(art_path);
|
||||
|
||||
|
||||
if (GTK_IS_IMAGE(self->art)) { // Already have an image
|
||||
if (!defined_artwork) { // No art path or empty string
|
||||
gtk_image_set_from_icon_name(GTK_IMAGE(self->art), "audio-x-generic-symbolic");
|
||||
|
@ -175,7 +214,11 @@ void koto_cover_art_button_set_art_path(KotoCoverArtButton *self, gchar *art_pat
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cover_art_button_set_dimensions(KotoCoverArtButton *self, guint height, guint width) {
|
||||
void koto_cover_art_button_set_dimensions(
|
||||
KotoCoverArtButton * self,
|
||||
guint height,
|
||||
guint width
|
||||
) {
|
||||
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -197,15 +240,24 @@ void koto_cover_art_button_set_dimensions(KotoCoverArtButton *self, guint height
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cover_art_button_show_overlay_controls(GtkEventControllerFocus *controller, gpointer data) {
|
||||
void koto_cover_art_button_show_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
) {
|
||||
(void) controller;
|
||||
KotoCoverArtButton* self = data;
|
||||
|
||||
|
||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), TRUE);
|
||||
}
|
||||
|
||||
KotoCoverArtButton* koto_cover_art_button_new(guint height, guint width, gchar *art_path) {
|
||||
return g_object_new(KOTO_TYPE_COVER_ART_BUTTON,
|
||||
KotoCoverArtButton * koto_cover_art_button_new(
|
||||
guint height,
|
||||
guint width,
|
||||
gchar * art_path
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_COVER_ART_BUTTON,
|
||||
"desired-height",
|
||||
height,
|
||||
"desired-width",
|
||||
|
|
|
@ -29,12 +29,35 @@ G_DECLARE_FINAL_TYPE(KotoCoverArtButton, koto_cover_art_button, KOTO, COVER_ART_
|
|||
* Cover Art Functions
|
||||
**/
|
||||
|
||||
KotoCoverArtButton* koto_cover_art_button_new(guint height, guint width, gchar *art_path);
|
||||
KotoCoverArtButton * koto_cover_art_button_new(
|
||||
guint height,
|
||||
guint width,
|
||||
gchar * art_path
|
||||
);
|
||||
|
||||
KotoButton * koto_cover_art_button_get_button(KotoCoverArtButton * self);
|
||||
|
||||
GtkWidget * koto_cover_art_button_get_main(KotoCoverArtButton * self);
|
||||
void koto_cover_art_button_hide_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
||||
void koto_cover_art_button_set_art_path(KotoCoverArtButton *self, gchar *art_path);
|
||||
void koto_cover_art_button_set_dimensions(KotoCoverArtButton *self, guint height, guint width);
|
||||
void koto_cover_art_button_show_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
||||
|
||||
void koto_cover_art_button_hide_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_cover_art_button_set_art_path(
|
||||
KotoCoverArtButton * self,
|
||||
gchar * art_path
|
||||
);
|
||||
|
||||
void koto_cover_art_button_set_dimensions(
|
||||
KotoCoverArtButton * self,
|
||||
guint height,
|
||||
guint width
|
||||
);
|
||||
|
||||
void koto_cover_art_button_show_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
|
@ -30,7 +30,9 @@ enum {
|
|||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint cartographer_signals[N_SIGNALS] = { 0 };
|
||||
static guint cartographer_signals[N_SIGNALS] = {
|
||||
0
|
||||
};
|
||||
|
||||
struct _KotoCartographer {
|
||||
GObject parent_instance;
|
||||
|
@ -44,14 +46,38 @@ struct _KotoCartographer {
|
|||
struct _KotoCartographerClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* album_added) (KotoCartographer *cartographer, KotoIndexedAlbum *album);
|
||||
void (* album_removed) (KotoCartographer *cartographer, KotoIndexedAlbum *album);
|
||||
void (* artist_added) (KotoCartographer *cartographer, KotoIndexedArtist *artist);
|
||||
void (* artist_removed) (KotoCartographer *cartographer, KotoIndexedArtist *artist);
|
||||
void (* playlist_added) (KotoCartographer *cartographer, KotoPlaylist *playlist);
|
||||
void (* playlist_removed) (KotoCartographer *cartographer, KotoPlaylist *playlist);
|
||||
void (* track_added) (KotoCartographer *cartographer, KotoIndexedTrack *track);
|
||||
void (* track_removed) (KotoCartographer *cartographer, KotoIndexedTrack *track);
|
||||
void (* album_added) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
void (* album_removed) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
void (* artist_added) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
void (* artist_removed) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
void (* playlist_added) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
void (* playlist_removed) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
void (* track_added) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
void (* track_removed) (
|
||||
KotoCartographer * cartographer,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoCartographer, koto_cartographer, G_TYPE_OBJECT);
|
||||
|
@ -60,6 +86,8 @@ KotoCartographer *koto_maps = NULL;
|
|||
|
||||
static void koto_cartographer_class_init(KotoCartographerClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
|
||||
cartographer_signals[SIGNAL_ALBUM_ADDED] = g_signal_new(
|
||||
|
@ -174,8 +202,13 @@ static void koto_cartographer_init(KotoCartographer *self) {
|
|||
self->tracks = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
}
|
||||
|
||||
void koto_cartographer_add_album(KotoCartographer *self, KotoIndexedAlbum *album) {
|
||||
void koto_cartographer_add_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
gchar * album_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||
|
||||
if ((album_uuid == NULL) || koto_cartographer_has_album_by_uuid(self, album_uuid)) { // Have the album or invalid UUID
|
||||
|
@ -192,8 +225,13 @@ void koto_cartographer_add_album(KotoCartographer *self, KotoIndexedAlbum *album
|
|||
);
|
||||
}
|
||||
|
||||
void koto_cartographer_add_artist(KotoCartographer *self, KotoIndexedArtist *artist) {
|
||||
void koto_cartographer_add_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||
|
||||
if ((artist_uuid == NULL) || koto_cartographer_has_artist_by_uuid(self, artist_uuid)) { // Have the artist or invalid UUID
|
||||
|
@ -210,8 +248,13 @@ void koto_cartographer_add_artist(KotoCartographer *self, KotoIndexedArtist *art
|
|||
);
|
||||
}
|
||||
|
||||
void koto_cartographer_add_playlist(KotoCartographer *self, KotoPlaylist *playlist) {
|
||||
void koto_cartographer_add_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
) {
|
||||
gchar * playlist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
||||
|
||||
if ((playlist_uuid == NULL) || koto_cartographer_has_playlist_by_uuid(self, playlist_uuid)) { // Have the playlist or invalid UUID
|
||||
|
@ -227,7 +270,10 @@ void koto_cartographer_add_playlist(KotoCartographer *self, KotoPlaylist *playli
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cartographer_emit_playlist_added(KotoPlaylist *playlist, KotoCartographer *self) {
|
||||
void koto_cartographer_emit_playlist_added(
|
||||
KotoPlaylist * playlist,
|
||||
KotoCartographer * self
|
||||
) {
|
||||
g_signal_emit(
|
||||
self,
|
||||
cartographer_signals[SIGNAL_PLAYLIST_ADDED],
|
||||
|
@ -236,8 +282,13 @@ void koto_cartographer_emit_playlist_added(KotoPlaylist *playlist, KotoCartograp
|
|||
);
|
||||
}
|
||||
|
||||
void koto_cartographer_add_track(KotoCartographer *self, KotoIndexedTrack *track) {
|
||||
void koto_cartographer_add_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
gchar * track_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||
|
||||
if ((track_uuid == NULL) || koto_cartographer_has_track_by_uuid(self, track_uuid)) { // Have the track or invalid UUID
|
||||
|
@ -254,11 +305,17 @@ void koto_cartographer_add_track(KotoCartographer *self, KotoIndexedTrack *track
|
|||
);
|
||||
}
|
||||
|
||||
KotoIndexedAlbum* koto_cartographer_get_album_by_uuid(KotoCartographer *self, gchar* album_uuid) {
|
||||
KotoIndexedAlbum * koto_cartographer_get_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
) {
|
||||
return g_hash_table_lookup(self->albums, album_uuid);
|
||||
}
|
||||
|
||||
KotoIndexedArtist* koto_cartographer_get_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid) {
|
||||
KotoIndexedArtist * koto_cartographer_get_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
) {
|
||||
return g_hash_table_lookup(self->artists, artist_uuid);
|
||||
}
|
||||
|
||||
|
@ -266,21 +323,35 @@ GHashTable* koto_cartographer_get_playlists(KotoCartographer *self) {
|
|||
return self->playlists;
|
||||
}
|
||||
|
||||
KotoPlaylist* koto_cartographer_get_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid) {
|
||||
KotoPlaylist * koto_cartographer_get_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
) {
|
||||
return g_hash_table_lookup(self->playlists, playlist_uuid);
|
||||
}
|
||||
|
||||
KotoIndexedTrack* koto_cartographer_get_track_by_uuid(KotoCartographer *self, gchar* track_uuid) {
|
||||
KotoIndexedTrack * koto_cartographer_get_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
) {
|
||||
return g_hash_table_lookup(self->tracks, track_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_album(KotoCartographer *self, KotoIndexedAlbum *album) {
|
||||
gboolean koto_cartographer_has_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
gchar * album_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||
return koto_cartographer_has_album_by_uuid(self, album_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_album_by_uuid(KotoCartographer *self, gchar* album_uuid) {
|
||||
gboolean koto_cartographer_has_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
) {
|
||||
if (album_uuid == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -288,13 +359,21 @@ gboolean koto_cartographer_has_album_by_uuid(KotoCartographer *self, gchar* albu
|
|||
return g_hash_table_contains(self->albums, album_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_artist(KotoCartographer *self, KotoIndexedArtist *artist) {
|
||||
gboolean koto_cartographer_has_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||
return koto_cartographer_has_artist_by_uuid(self, artist_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid) {
|
||||
gboolean koto_cartographer_has_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
) {
|
||||
if (artist_uuid == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -302,13 +381,21 @@ gboolean koto_cartographer_has_artist_by_uuid(KotoCartographer *self, gchar* art
|
|||
return g_hash_table_contains(self->artists, artist_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_playlist(KotoCartographer *self, KotoPlaylist *playlist) {
|
||||
gboolean koto_cartographer_has_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
) {
|
||||
gchar * playlist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
||||
return koto_cartographer_has_playlist_by_uuid(self, playlist_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid) {
|
||||
gboolean koto_cartographer_has_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
) {
|
||||
if (playlist_uuid == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -316,13 +403,21 @@ gboolean koto_cartographer_has_playlist_by_uuid(KotoCartographer *self, gchar* p
|
|||
return g_hash_table_contains(self->playlists, playlist_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_track(KotoCartographer *self, KotoIndexedTrack *track) {
|
||||
gboolean koto_cartographer_has_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
gchar * track_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||
return koto_cartographer_has_album_by_uuid(self, track_uuid);
|
||||
}
|
||||
|
||||
gboolean koto_cartographer_has_track_by_uuid(KotoCartographer *self, gchar* track_uuid) {
|
||||
gboolean koto_cartographer_has_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
) {
|
||||
if (track_uuid == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -330,13 +425,21 @@ gboolean koto_cartographer_has_track_by_uuid(KotoCartographer *self, gchar* trac
|
|||
return g_hash_table_contains(self->tracks, track_uuid);
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_album(KotoCartographer *self, KotoIndexedAlbum *album) {
|
||||
void koto_cartographer_remove_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
gchar * album_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||
koto_cartographer_remove_album_by_uuid(self, album_uuid);
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_album_by_uuid(KotoCartographer *self, gchar* album_uuid) {
|
||||
void koto_cartographer_remove_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
) {
|
||||
if (album_uuid != NULL) {
|
||||
g_hash_table_remove(self->albums, album_uuid);
|
||||
|
||||
|
@ -349,13 +452,21 @@ void koto_cartographer_remove_album_by_uuid(KotoCartographer *self, gchar* album
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_artist(KotoCartographer *self, KotoIndexedArtist *artist) {
|
||||
void koto_cartographer_remove_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||
koto_cartographer_remove_artist_by_uuid(self, artist_uuid);
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid) {
|
||||
void koto_cartographer_remove_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
) {
|
||||
if (artist_uuid == NULL) {
|
||||
g_hash_table_remove(self->artists, artist_uuid);
|
||||
|
||||
|
@ -368,13 +479,21 @@ void koto_cartographer_remove_artist_by_uuid(KotoCartographer *self, gchar* arti
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_playlist(KotoCartographer *self, KotoPlaylist *playlist) {
|
||||
void koto_cartographer_remove_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
) {
|
||||
gchar * playlist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
||||
koto_cartographer_remove_playlist_by_uuid(self, playlist_uuid);
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid) {
|
||||
void koto_cartographer_remove_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
) {
|
||||
if (playlist_uuid != NULL) {
|
||||
g_hash_table_remove(self->playlists, playlist_uuid);
|
||||
|
||||
|
@ -387,13 +506,21 @@ void koto_cartographer_remove_playlist_by_uuid(KotoCartographer *self, gchar* pl
|
|||
}
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_track(KotoCartographer *self, KotoIndexedTrack *track) {
|
||||
void koto_cartographer_remove_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
gchar * track_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||
koto_cartographer_remove_track_by_uuid(self, track_uuid);
|
||||
}
|
||||
|
||||
void koto_cartographer_remove_track_by_uuid(KotoCartographer *self, gchar* track_uuid) {
|
||||
void koto_cartographer_remove_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
) {
|
||||
if (track_uuid != NULL) {
|
||||
g_hash_table_remove(self->tracks, track_uuid);
|
||||
|
||||
|
|
|
@ -40,35 +40,131 @@ GType koto_cartographer_get_type(void) G_GNUC_CONST;
|
|||
|
||||
KotoCartographer * koto_cartographer_new();
|
||||
|
||||
void koto_cartographer_add_album(KotoCartographer *self, KotoIndexedAlbum *album);
|
||||
void koto_cartographer_add_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
||||
void koto_cartographer_add_playlist(KotoCartographer *self, KotoPlaylist *playlist);
|
||||
void koto_cartographer_add_track(KotoCartographer *self, KotoIndexedTrack *track);
|
||||
void koto_cartographer_add_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_cartographer_emit_playlist_added(KotoPlaylist *playlist, KotoCartographer *self);
|
||||
void koto_cartographer_add_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
void koto_cartographer_add_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
|
||||
void koto_cartographer_add_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
void koto_cartographer_emit_playlist_added(
|
||||
KotoPlaylist * playlist,
|
||||
KotoCartographer * self
|
||||
);
|
||||
|
||||
KotoIndexedAlbum * koto_cartographer_get_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
);
|
||||
|
||||
KotoIndexedArtist * koto_cartographer_get_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
);
|
||||
|
||||
KotoPlaylist * koto_cartographer_get_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
);
|
||||
|
||||
KotoIndexedAlbum* koto_cartographer_get_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
||||
KotoIndexedArtist* koto_cartographer_get_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid);
|
||||
KotoPlaylist* koto_cartographer_get_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid);
|
||||
GHashTable * koto_cartographer_get_playlists(KotoCartographer * self);
|
||||
KotoIndexedTrack* koto_cartographer_get_track_by_uuid(KotoCartographer *self, gchar* track_uuid);
|
||||
|
||||
gboolean koto_cartographer_has_album(KotoCartographer *self, KotoIndexedAlbum *album);
|
||||
gboolean koto_cartographer_has_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
||||
gboolean koto_cartographer_has_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
||||
gboolean koto_cartographer_has_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid);
|
||||
gboolean koto_cartographer_has_playlist(KotoCartographer *self, KotoPlaylist *playlist);
|
||||
gboolean koto_cartographer_has_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid);
|
||||
gboolean koto_cartographer_has_track(KotoCartographer *self, KotoIndexedTrack *track);
|
||||
gboolean koto_cartographer_has_track_by_uuid(KotoCartographer *self, gchar* track_uuid);
|
||||
KotoIndexedTrack * koto_cartographer_get_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_album(KotoCartographer *self, KotoIndexedAlbum *album);
|
||||
void koto_cartographer_remove_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
||||
void koto_cartographer_remove_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
||||
void koto_cartographer_remove_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid);
|
||||
void koto_cartographer_remove_playlist(KotoCartographer *self, KotoPlaylist *playlist);
|
||||
void koto_cartographer_remove_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid);
|
||||
void koto_cartographer_remove_track(KotoCartographer *self, KotoIndexedTrack *track);
|
||||
void koto_cartographer_remove_track_by_uuid(KotoCartographer *self, gchar* track_uuid);
|
||||
gboolean koto_cartographer_has_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
gboolean koto_cartographer_has_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_album(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_album_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* album_uuid
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_artist(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_artist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* artist_uuid
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_playlist(
|
||||
KotoCartographer * self,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_playlist_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* playlist_uuid
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_track(
|
||||
KotoCartographer * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
void koto_cartographer_remove_track_by_uuid(
|
||||
KotoCartographer * self,
|
||||
gchar* track_uuid
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -44,6 +44,7 @@ int create_db_tables() {
|
|||
gchar * create_tables_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, tables_creation_queries, 0, 0, &create_tables_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_critical("Failed to create required tables: %s", create_tables_errmsg);
|
||||
}
|
||||
|
@ -55,6 +56,7 @@ int enable_foreign_keys() {
|
|||
gchar * enable_foreign_keys_err = NULL;
|
||||
int rc = sqlite3_exec(koto_db, "PRAGMA foreign_keys = ON;", 0, 0, &enable_foreign_keys_err);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_critical("Failed to enable foreign key support. Ensure your sqlite3 is compiled with neither SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined: %s", enable_foreign_keys_err);
|
||||
}
|
||||
|
@ -78,12 +80,14 @@ int have_existing_db() {
|
|||
struct stat db_stat;
|
||||
int success = stat(get_db_path(), &db_stat);
|
||||
|
||||
|
||||
return ((success == 0) && S_ISREG(db_stat.st_mode)) ? 0 : 1;
|
||||
}
|
||||
|
||||
int open_db() {
|
||||
int ret = KOTO_DB_SUCCESS; // Default to last return being SUCCESS
|
||||
|
||||
|
||||
if (have_existing_db() == 1) { // If we do not have an existing DB
|
||||
const gchar * data_home = g_get_user_data_dir();
|
||||
const gchar * data_dir = g_path_get_dirname(db_filepath);
|
||||
|
|
|
@ -24,8 +24,13 @@ extern int KOTO_DB_FAIL;
|
|||
extern gboolean created_new_db;
|
||||
|
||||
void close_db();
|
||||
|
||||
int create_db_tables();
|
||||
|
||||
gchar * get_db_path();
|
||||
|
||||
int enable_foreign_keys();
|
||||
|
||||
int have_existing_db();
|
||||
|
||||
int open_db();
|
||||
|
|
|
@ -56,13 +56,28 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void koto_indexed_album_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_album_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_album_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_album_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_album_class_init(KotoIndexedAlbumClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_indexed_album_set_property;
|
||||
gobject_class->get_property = koto_indexed_album_get_property;
|
||||
|
@ -123,12 +138,17 @@ static void koto_indexed_album_init(KotoIndexedAlbum *self) {
|
|||
self->tracks = NULL;
|
||||
}
|
||||
|
||||
void koto_indexed_album_add_track(KotoIndexedAlbum *self, KotoIndexedTrack *track) {
|
||||
void koto_indexed_album_add_track(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
if (track == NULL) { // Not a file
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * track_uuid;
|
||||
|
||||
|
||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||
|
||||
if (g_list_index(self->tracks, track_uuid) == -1) {
|
||||
|
@ -155,6 +175,7 @@ void koto_indexed_album_commit(KotoIndexedAlbum *self) {
|
|||
gchar * commit_op_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to write our album to the database: %s", commit_op_errmsg);
|
||||
}
|
||||
|
@ -166,6 +187,7 @@ void koto_indexed_album_commit(KotoIndexedAlbum *self) {
|
|||
void koto_indexed_album_find_album_art(KotoIndexedAlbum * self) {
|
||||
magic_t magic_cookie = magic_open(MAGIC_MIME);
|
||||
|
||||
|
||||
if (magic_cookie == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -177,12 +199,14 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
|||
|
||||
DIR * dir = opendir(self->path); // Attempt to open our directory
|
||||
|
||||
|
||||
if (dir == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent * entry;
|
||||
|
||||
|
||||
while ((entry = readdir(dir))) {
|
||||
if (entry->d_type != DT_REG) { // Not a regular file
|
||||
continue; // SKIP
|
||||
|
@ -226,7 +250,11 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
|||
magic_close(magic_cookie);
|
||||
}
|
||||
|
||||
void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie, const gchar *path) {
|
||||
void koto_indexed_album_find_tracks(
|
||||
KotoIndexedAlbum * self,
|
||||
magic_t magic_cookie,
|
||||
const gchar * path
|
||||
) {
|
||||
if (magic_cookie == NULL) { // No cookie provided
|
||||
magic_cookie = magic_open(MAGIC_MIME);
|
||||
}
|
||||
|
@ -246,12 +274,14 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
|||
|
||||
DIR * dir = opendir(path); // Attempt to open our directory
|
||||
|
||||
|
||||
if (dir == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent * entry;
|
||||
|
||||
|
||||
while ((entry = readdir(dir))) {
|
||||
if (g_str_has_prefix(entry->d_name, ".")) { // Reference to parent dir, self, or a hidden item
|
||||
continue; // Skip
|
||||
|
@ -315,9 +345,15 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_indexed_album_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_album_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedAlbum * self = KOTO_INDEXED_ALBUM(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
g_value_set_string(val, self->uuid);
|
||||
|
@ -343,9 +379,15 @@ static void koto_indexed_album_get_property(GObject *obj, guint prop_id, GValue
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_indexed_album_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec){
|
||||
static void koto_indexed_album_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedAlbum * self = KOTO_INDEXED_ALBUM(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
self->uuid = g_strdup(g_value_get_string(val));
|
||||
|
@ -412,7 +454,10 @@ GList* koto_indexed_album_get_tracks(KotoIndexedAlbum *self) {
|
|||
return self->tracks; // Return
|
||||
}
|
||||
|
||||
void koto_indexed_album_set_album_art(KotoIndexedAlbum *self, const gchar *album_art) {
|
||||
void koto_indexed_album_set_album_art(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * album_art
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||
return;
|
||||
}
|
||||
|
@ -430,7 +475,10 @@ void koto_indexed_album_set_album_art(KotoIndexedAlbum *self, const gchar *album
|
|||
self->has_album_art = TRUE;
|
||||
}
|
||||
|
||||
void koto_indexed_album_remove_file(KotoIndexedAlbum *self, KotoIndexedTrack *track) {
|
||||
void koto_indexed_album_remove_file(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||
return;
|
||||
}
|
||||
|
@ -440,11 +488,16 @@ void koto_indexed_album_remove_file(KotoIndexedAlbum *self, KotoIndexedTrack *tr
|
|||
}
|
||||
|
||||
gchar * track_uuid;
|
||||
|
||||
|
||||
g_object_get(track, "parsed-name", &track_uuid, NULL);
|
||||
self->tracks = g_list_remove(self->tracks, track_uuid);
|
||||
}
|
||||
|
||||
void koto_indexed_album_set_album_name(KotoIndexedAlbum *self, const gchar *album_name) {
|
||||
void koto_indexed_album_set_album_name(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * album_name
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||
return;
|
||||
}
|
||||
|
@ -460,7 +513,10 @@ void koto_indexed_album_set_album_name(KotoIndexedAlbum *self, const gchar *albu
|
|||
self->name = g_strdup(album_name);
|
||||
}
|
||||
|
||||
void koto_indexed_album_set_artist_uuid(KotoIndexedAlbum *self, const gchar *artist_uuid) {
|
||||
void koto_indexed_album_set_artist_uuid(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * artist_uuid
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||
return;
|
||||
}
|
||||
|
@ -486,6 +542,8 @@ void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum *self) {
|
|||
}
|
||||
|
||||
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.
|
||||
|
@ -493,9 +551,13 @@ void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum *self) {
|
|||
// 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
|
||||
|
@ -508,11 +570,16 @@ void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum *self) {
|
|||
koto_current_playlist_set_playlist(current_playlist, new_album_playlist); // Set our new current playlist
|
||||
}
|
||||
|
||||
gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer track2_uuid, gpointer user_data) {
|
||||
gint koto_indexed_album_sort_tracks(
|
||||
gconstpointer track1_uuid,
|
||||
gconstpointer track2_uuid,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
KotoIndexedTrack * track1 = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) track1_uuid);
|
||||
KotoIndexedTrack * track2 = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) track2_uuid);
|
||||
|
||||
|
||||
if ((track1 == NULL) && (track2 == NULL)) { // Neither tracks actually exist
|
||||
return 0;
|
||||
} else if ((track1 != NULL) && (track2 == NULL)) { // Only track2 does not exist
|
||||
|
@ -524,6 +591,7 @@ gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer tra
|
|||
guint * track1_disc = (guint*) 1;
|
||||
guint * track2_disc = (guint*) 2;
|
||||
|
||||
|
||||
g_object_get(track1, "cd", &track1_disc, NULL);
|
||||
g_object_get(track2, "cd", &track2_disc, NULL);
|
||||
|
||||
|
@ -536,6 +604,7 @@ gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer tra
|
|||
guint16 * track1_pos;
|
||||
guint16 * track2_pos;
|
||||
|
||||
|
||||
g_object_get(track1, "position", &track1_pos, NULL);
|
||||
g_object_get(track2, "position", &track2_pos, NULL);
|
||||
|
||||
|
@ -554,7 +623,10 @@ gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer tra
|
|||
}
|
||||
}
|
||||
|
||||
void koto_indexed_album_update_path(KotoIndexedAlbum *self, gchar* new_path) {
|
||||
void koto_indexed_album_update_path(
|
||||
KotoIndexedAlbum * self,
|
||||
gchar* new_path
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||
return;
|
||||
}
|
||||
|
@ -577,32 +649,52 @@ void koto_indexed_album_update_path(KotoIndexedAlbum *self, gchar* new_path) {
|
|||
koto_indexed_album_find_album_art(self); // Update our path for the album art
|
||||
}
|
||||
|
||||
KotoIndexedAlbum* koto_indexed_album_new(KotoIndexedArtist *artist, const gchar *path) {
|
||||
KotoIndexedAlbum * koto_indexed_album_new(
|
||||
KotoIndexedArtist * artist,
|
||||
const gchar * path
|
||||
) {
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||
|
||||
KotoIndexedAlbum* album = g_object_new(KOTO_TYPE_INDEXED_ALBUM,
|
||||
"artist-uuid", artist_uuid,
|
||||
"uuid", g_strdup(g_uuid_string_random()),
|
||||
"do-initial-index", TRUE,
|
||||
"path", path,
|
||||
KotoIndexedAlbum* album = g_object_new(
|
||||
KOTO_TYPE_INDEXED_ALBUM,
|
||||
"artist-uuid",
|
||||
artist_uuid,
|
||||
"uuid",
|
||||
g_strdup(g_uuid_string_random()),
|
||||
"do-initial-index",
|
||||
TRUE,
|
||||
"path",
|
||||
path,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
koto_indexed_album_commit(album);
|
||||
koto_indexed_album_find_tracks(album, NULL, NULL); // Scan for tracks now that we committed to the database (hopefully)
|
||||
|
||||
return album;
|
||||
}
|
||||
|
||||
KotoIndexedAlbum* koto_indexed_album_new_with_uuid(KotoIndexedArtist *artist, const gchar *uuid) {
|
||||
KotoIndexedAlbum * koto_indexed_album_new_with_uuid(
|
||||
KotoIndexedArtist * artist,
|
||||
const gchar * uuid
|
||||
) {
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||
|
||||
return g_object_new(KOTO_TYPE_INDEXED_ALBUM,
|
||||
"artist-uuid", artist,
|
||||
"uuid", g_strdup(uuid),
|
||||
"do-initial-index", FALSE,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_INDEXED_ALBUM,
|
||||
"artist-uuid",
|
||||
artist,
|
||||
"uuid",
|
||||
g_strdup(uuid),
|
||||
"do-initial-index",
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -43,13 +43,28 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void koto_indexed_artist_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_artist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_artist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_artist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_artist_class_init(KotoIndexedArtistClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_indexed_artist_set_property;
|
||||
gobject_class->get_property = koto_indexed_artist_get_property;
|
||||
|
@ -99,6 +114,7 @@ void koto_indexed_artist_commit(KotoIndexedArtist *self) {
|
|||
gchar * commit_opt_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_opt_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to write our artist to the database: %s", commit_opt_errmsg);
|
||||
}
|
||||
|
@ -112,9 +128,15 @@ static void koto_indexed_artist_init(KotoIndexedArtist *self) {
|
|||
self->albums = NULL; // Create a new GList
|
||||
}
|
||||
|
||||
static void koto_indexed_artist_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_artist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedArtist * self = KOTO_INDEXED_ARTIST(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
g_value_set_string(val, self->uuid);
|
||||
|
@ -131,9 +153,15 @@ static void koto_indexed_artist_get_property(GObject *obj, guint prop_id, GValue
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_indexed_artist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_artist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedArtist * self = KOTO_INDEXED_ARTIST(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
self->uuid = g_strdup(g_value_get_string(val));
|
||||
|
@ -151,7 +179,10 @@ static void koto_indexed_artist_set_property(GObject *obj, guint prop_id, const
|
|||
}
|
||||
}
|
||||
|
||||
void koto_indexed_artist_add_album(KotoIndexedArtist *self, gchar *album_uuid) {
|
||||
void koto_indexed_artist_add_album(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * album_uuid
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||
return;
|
||||
}
|
||||
|
@ -162,6 +193,7 @@ void koto_indexed_artist_add_album(KotoIndexedArtist *self, gchar *album_uuid) {
|
|||
|
||||
gchar * uuid = g_strdup(album_uuid); // Duplicate our UUID
|
||||
|
||||
|
||||
if (g_list_index(self->albums, uuid) == -1) {
|
||||
self->albums = g_list_append(self->albums, uuid); // Push to end of list
|
||||
}
|
||||
|
@ -183,7 +215,10 @@ gchar* koto_indexed_artist_get_name(KotoIndexedArtist *self) {
|
|||
return g_strdup(koto_utils_is_string_valid(self->artist_name) ? self->artist_name : ""); // Return artist name if set
|
||||
}
|
||||
|
||||
void koto_indexed_artist_remove_album(KotoIndexedArtist *self, KotoIndexedAlbum *album) {
|
||||
void koto_indexed_artist_remove_album(
|
||||
KotoIndexedArtist * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||
return;
|
||||
}
|
||||
|
@ -193,11 +228,16 @@ void koto_indexed_artist_remove_album(KotoIndexedArtist *self, KotoIndexedAlbum
|
|||
}
|
||||
|
||||
gchar * album_uuid;
|
||||
|
||||
|
||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||
self->albums = g_list_remove(self->albums, album_uuid);
|
||||
}
|
||||
|
||||
void koto_indexed_artist_update_path(KotoIndexedArtist *self, gchar *new_path) {
|
||||
void koto_indexed_artist_update_path(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * new_path
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||
return;
|
||||
}
|
||||
|
@ -214,7 +254,10 @@ void koto_indexed_artist_update_path(KotoIndexedArtist *self, gchar *new_path) {
|
|||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PATH]);
|
||||
}
|
||||
|
||||
void koto_indexed_artist_set_artist_name(KotoIndexedArtist *self, gchar *artist_name) {
|
||||
void koto_indexed_artist_set_artist_name(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * artist_name
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||
return;
|
||||
}
|
||||
|
@ -232,20 +275,27 @@ void koto_indexed_artist_set_artist_name(KotoIndexedArtist *self, gchar *artist_
|
|||
}
|
||||
|
||||
KotoIndexedArtist * koto_indexed_artist_new(gchar * path) {
|
||||
KotoIndexedArtist* artist = g_object_new(KOTO_TYPE_INDEXED_ARTIST,
|
||||
"uuid", g_uuid_string_random(),
|
||||
"path", path,
|
||||
"name", g_path_get_basename(path),
|
||||
KotoIndexedArtist* artist = g_object_new(
|
||||
KOTO_TYPE_INDEXED_ARTIST,
|
||||
"uuid",
|
||||
g_uuid_string_random(),
|
||||
"path",
|
||||
path,
|
||||
"name",
|
||||
g_path_get_basename(path),
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
koto_indexed_artist_commit(artist); // Commit the artist immediately to the database
|
||||
return artist;
|
||||
}
|
||||
|
||||
KotoIndexedArtist * koto_indexed_artist_new_with_uuid(const gchar * uuid) {
|
||||
return g_object_new(KOTO_TYPE_INDEXED_ARTIST,
|
||||
"uuid", g_strdup(uuid),
|
||||
return g_object_new(
|
||||
KOTO_TYPE_INDEXED_ARTIST,
|
||||
"uuid",
|
||||
g_strdup(uuid),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -44,13 +44,28 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void koto_indexed_library_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_library_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_library_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_library_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_library_class_init(KotoIndexedLibraryClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_indexed_library_set_property;
|
||||
gobject_class->get_property = koto_indexed_library_get_property;
|
||||
|
@ -71,7 +86,10 @@ static void koto_indexed_library_init(KotoIndexedLibrary *self) {
|
|||
self->music_artists = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
}
|
||||
|
||||
void koto_indexed_library_add_artist(KotoIndexedLibrary *self, KotoIndexedArtist *artist) {
|
||||
void koto_indexed_library_add_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
if (artist == NULL) { // No artist
|
||||
return;
|
||||
}
|
||||
|
@ -80,6 +98,8 @@ void koto_indexed_library_add_artist(KotoIndexedLibrary *self, KotoIndexedArtist
|
|||
|
||||
gchar * artist_name;
|
||||
gchar * artist_uuid;
|
||||
|
||||
|
||||
g_object_get(artist, "name", &artist_name, "uuid", &artist_uuid, NULL);
|
||||
|
||||
if (g_hash_table_contains(self->music_artists, artist_name)) { // Already have the artist
|
||||
|
@ -90,7 +110,10 @@ void koto_indexed_library_add_artist(KotoIndexedLibrary *self, KotoIndexedArtist
|
|||
g_hash_table_insert(self->music_artists, artist_name, artist_uuid); // Add the artist by its name (this needs to be done so we can get the artist when doing the depth of 2 indexing for the album)
|
||||
}
|
||||
|
||||
KotoIndexedArtist* koto_indexed_library_get_artist(KotoIndexedLibrary *self, gchar *artist_name) {
|
||||
KotoIndexedArtist * koto_indexed_library_get_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar * artist_name
|
||||
) {
|
||||
if (artist_name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -99,6 +122,7 @@ KotoIndexedArtist* koto_indexed_library_get_artist(KotoIndexedLibrary *self, gch
|
|||
|
||||
gchar * artist_uuid = g_hash_table_lookup(self->music_artists, artist_name); // Get the UUID from our music artists
|
||||
|
||||
|
||||
if (artist_uuid != NULL) {
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid); // Return any artist from cartographer
|
||||
return artist;
|
||||
|
@ -115,7 +139,10 @@ GHashTable* koto_indexed_library_get_artists(KotoIndexedLibrary *self) {
|
|||
return self->music_artists;
|
||||
}
|
||||
|
||||
void koto_indexed_library_remove_artist(KotoIndexedLibrary *self, KotoIndexedArtist *artist) {
|
||||
void koto_indexed_library_remove_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
if (artist == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -123,14 +150,22 @@ void koto_indexed_library_remove_artist(KotoIndexedLibrary *self, KotoIndexedArt
|
|||
koto_indexed_library_get_artists(self); // Call to generate if needed
|
||||
|
||||
gchar * artist_name;
|
||||
|
||||
|
||||
g_object_get(artist, "name", &artist_name, NULL);
|
||||
|
||||
g_hash_table_remove(self->music_artists, artist_name); // Remove the artist
|
||||
}
|
||||
|
||||
static void koto_indexed_library_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_library_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedLibrary * self = KOTO_INDEXED_LIBRARY(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PATH:
|
||||
g_value_set_string(val, self->path);
|
||||
|
@ -141,9 +176,15 @@ static void koto_indexed_library_get_property(GObject *obj, guint prop_id, GValu
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_indexed_library_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec){
|
||||
static void koto_indexed_library_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedLibrary * self = KOTO_INDEXED_LIBRARY(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PATH:
|
||||
koto_indexed_library_set_path(self, g_strdup(g_value_get_string(val)));
|
||||
|
@ -154,7 +195,10 @@ static void koto_indexed_library_set_property(GObject *obj, guint prop_id, const
|
|||
}
|
||||
}
|
||||
|
||||
void koto_indexed_library_set_path(KotoIndexedLibrary *self, gchar *path) {
|
||||
void koto_indexed_library_set_path(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar * path
|
||||
) {
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -172,8 +216,14 @@ void koto_indexed_library_set_path(KotoIndexedLibrary *self, gchar *path) {
|
|||
}
|
||||
}
|
||||
|
||||
int process_artists(void *data, int num_columns, char **fields, char **column_names) {
|
||||
(void) num_columns; (void) column_names; // Don't need any of the params
|
||||
int process_artists(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
) {
|
||||
(void) num_columns;
|
||||
(void) column_names; // Don't need any of the params
|
||||
|
||||
KotoIndexedLibrary * library = (KotoIndexedLibrary*) data;
|
||||
gchar * artist_uuid = g_strdup(koto_utils_unquote_string(fields[0])); // First column is UUID
|
||||
|
@ -182,15 +232,21 @@ int process_artists(void *data, int num_columns, char **fields, char **column_na
|
|||
|
||||
KotoIndexedArtist * artist = koto_indexed_artist_new_with_uuid(artist_uuid); // Create our artist with the UUID
|
||||
|
||||
g_object_set(artist,
|
||||
"path", artist_path, // Set path
|
||||
"name", artist_name, // Set name
|
||||
|
||||
g_object_set(
|
||||
artist,
|
||||
"path",
|
||||
artist_path, // Set path
|
||||
"name",
|
||||
artist_name, // Set name
|
||||
NULL);
|
||||
|
||||
koto_cartographer_add_artist(koto_maps, artist); // Add the artist to our global cartographer
|
||||
koto_indexed_library_add_artist(library, artist);
|
||||
|
||||
int albums_rc = sqlite3_exec(koto_db, g_strdup_printf("SELECT * FROM albums WHERE artist_id=\"%s\"", artist_uuid), process_albums, artist, NULL); // Process our albums
|
||||
|
||||
|
||||
if (albums_rc != SQLITE_OK) { // Failed to get our albums
|
||||
g_critical("Failed to read our albums: %s", sqlite3_errmsg(koto_db));
|
||||
return 1;
|
||||
|
@ -203,8 +259,14 @@ int process_artists(void *data, int num_columns, char **fields, char **column_na
|
|||
return 0;
|
||||
}
|
||||
|
||||
int process_albums(void *data, int num_columns, char **fields, char **column_names) {
|
||||
(void) num_columns; (void) column_names; // Don't need these
|
||||
int process_albums(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
) {
|
||||
(void) num_columns;
|
||||
(void) column_names; // Don't need these
|
||||
|
||||
KotoIndexedArtist * artist = (KotoIndexedArtist*) data;
|
||||
|
||||
|
@ -216,16 +278,23 @@ int process_albums(void *data, int num_columns, char **fields, char **column_nam
|
|||
|
||||
KotoIndexedAlbum * album = koto_indexed_album_new_with_uuid(artist, album_uuid); // Create our album
|
||||
|
||||
g_object_set(album,
|
||||
"path", path, // Set the path
|
||||
"name", album_name, // Set name
|
||||
"art-path", album_art, // Set art path if any
|
||||
|
||||
g_object_set(
|
||||
album,
|
||||
"path",
|
||||
path, // Set the path
|
||||
"name",
|
||||
album_name, // Set name
|
||||
"art-path",
|
||||
album_art, // Set art path if any
|
||||
NULL);
|
||||
|
||||
koto_cartographer_add_album(koto_maps, album); // Add the album to our global cartographer
|
||||
koto_indexed_artist_add_album(artist, album_uuid); // Add the album
|
||||
|
||||
int tracks_rc = sqlite3_exec(koto_db, g_strdup_printf("SELECT * FROM tracks WHERE album_id=\"%s\"", album_uuid), process_tracks, album, NULL); // Process our tracks
|
||||
|
||||
|
||||
if (tracks_rc != SQLITE_OK) { // Failed to get our tracks
|
||||
g_critical("Failed to read our tracks: %s", sqlite3_errmsg(koto_db));
|
||||
return 1;
|
||||
|
@ -243,20 +312,31 @@ int process_albums(void *data, int num_columns, char **fields, char **column_nam
|
|||
return 0;
|
||||
}
|
||||
|
||||
int process_playlists(void *data, int num_columns, char **fields, char **column_names) {
|
||||
(void) data; (void) num_columns; (void) column_names; // Don't need any of the params
|
||||
int process_playlists(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
) {
|
||||
(void) data;
|
||||
(void) num_columns;
|
||||
(void) column_names; // Don't need any of the params
|
||||
|
||||
gchar * playlist_uuid = g_strdup(koto_utils_unquote_string(fields[0])); // First column is UUID
|
||||
gchar * playlist_name = g_strdup(koto_utils_unquote_string(fields[1])); // Second column is playlist name
|
||||
gchar * playlist_art_path = g_strdup(koto_utils_unquote_string(fields[2])); // Third column is any art path
|
||||
|
||||
KotoPlaylist * playlist = koto_playlist_new_with_uuid(playlist_uuid); // Create a playlist using the existing UUID
|
||||
|
||||
|
||||
koto_playlist_set_name(playlist, playlist_name); // Add the playlist name
|
||||
koto_playlist_set_artwork(playlist, playlist_art_path); // Add the playlist art path
|
||||
|
||||
koto_cartographer_add_playlist(koto_maps, playlist); // Add to cartographer
|
||||
|
||||
int playlist_tracks_rc = sqlite3_exec(koto_db, g_strdup_printf("SELECT * FROM playlist_tracks WHERE playlist_id=\"%s\" ORDER BY position ASC", playlist_uuid), process_playlists_tracks, playlist, NULL); // Process our playlist tracks
|
||||
|
||||
|
||||
if (playlist_tracks_rc != SQLITE_OK) { // Failed to get our playlist tracks
|
||||
g_critical("Failed to read our playlist tracks: %s", sqlite3_errmsg(koto_db));
|
||||
return 1;
|
||||
|
@ -271,8 +351,15 @@ int process_playlists(void *data, int num_columns, char **fields, char **column_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int process_playlists_tracks(void *data, int num_columns, char **fields, char **column_names) {
|
||||
(void) data; (void) num_columns; (void) column_names; // Don't need these
|
||||
int process_playlists_tracks(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
) {
|
||||
(void) data;
|
||||
(void) num_columns;
|
||||
(void) column_names; // Don't need these
|
||||
|
||||
gchar * playlist_uuid = g_strdup(koto_utils_unquote_string(fields[1]));
|
||||
gchar * track_uuid = g_strdup(koto_utils_unquote_string(fields[2]));
|
||||
|
@ -281,6 +368,7 @@ int process_playlists_tracks(void *data, int num_columns, char **fields, char **
|
|||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid); // Get the playlist
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid); // Get the track
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
goto freeforret;
|
||||
}
|
||||
|
@ -294,8 +382,14 @@ freeforret:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int process_tracks(void *data, int num_columns, char **fields, char **column_names) {
|
||||
(void) num_columns; (void) column_names; // Don't need these
|
||||
int process_tracks(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
) {
|
||||
(void) num_columns;
|
||||
(void) column_names; // Don't need these
|
||||
|
||||
KotoIndexedAlbum * album = (KotoIndexedAlbum*) data;
|
||||
gchar * track_uuid = g_strdup(koto_utils_unquote_string(fields[0]));
|
||||
|
@ -308,15 +402,9 @@ int process_tracks(void *data, int num_columns, char **fields, char **column_nam
|
|||
guint * position = (guint*) g_ascii_strtoull(fields[8], NULL, 10);
|
||||
|
||||
KotoIndexedTrack * track = koto_indexed_track_new_with_uuid(track_uuid); // Create our file
|
||||
g_object_set(track,
|
||||
"artist-uuid", artist_uuid,
|
||||
"album-uuid", album_uuid,
|
||||
"path", path,
|
||||
"file-name", file_name,
|
||||
"parsed-name", name,
|
||||
"cd", disc_num,
|
||||
"position", position,
|
||||
NULL);
|
||||
|
||||
|
||||
g_object_set(track, "artist-uuid", artist_uuid, "album-uuid", album_uuid, "path", path, "file-name", file_name, "parsed-name", name, "cd", disc_num, "position", position, NULL);
|
||||
|
||||
koto_cartographer_add_track(koto_maps, track); // Add the track to cartographer
|
||||
koto_indexed_album_add_track(album, track); // Add the track
|
||||
|
@ -333,6 +421,8 @@ int process_tracks(void *data, int num_columns, char **fields, char **column_nam
|
|||
|
||||
void read_from_db(KotoIndexedLibrary * self) {
|
||||
int artists_rc = sqlite3_exec(koto_db, "SELECT * FROM artists", process_artists, self, NULL); // Process our artists
|
||||
|
||||
|
||||
if (artists_rc != SQLITE_OK) { // Failed to get our artists
|
||||
g_critical("Failed to read our artists: %s", sqlite3_errmsg(koto_db));
|
||||
return;
|
||||
|
@ -341,6 +431,8 @@ void read_from_db(KotoIndexedLibrary *self) {
|
|||
g_hash_table_foreach(self->music_artists, output_artists, NULL);
|
||||
|
||||
int playlist_rc = sqlite3_exec(koto_db, "SELECT * FROM playlist_meta", process_playlists, self, NULL); // Process our playlists
|
||||
|
||||
|
||||
if (playlist_rc != SQLITE_OK) { // Failed to get our playlists
|
||||
g_critical("Failed to read our playlists: %s", sqlite3_errmsg(koto_db));
|
||||
return;
|
||||
|
@ -351,6 +443,7 @@ void start_indexing(KotoIndexedLibrary *self) {
|
|||
struct stat library_stat;
|
||||
int success = stat(self->path, &library_stat);
|
||||
|
||||
|
||||
if (success != 0) { // Failed to read the library path
|
||||
return;
|
||||
}
|
||||
|
@ -377,23 +470,31 @@ void start_indexing(KotoIndexedLibrary *self) {
|
|||
}
|
||||
|
||||
KotoIndexedLibrary * koto_indexed_library_new(const gchar * path) {
|
||||
return g_object_new(KOTO_TYPE_INDEXED_LIBRARY,
|
||||
"path", path,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_INDEXED_LIBRARY,
|
||||
"path",
|
||||
path,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
||||
void index_folder(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar * path,
|
||||
guint depth
|
||||
) {
|
||||
depth++;
|
||||
|
||||
DIR * dir = opendir(path); // Attempt to open our directory
|
||||
|
||||
|
||||
if (dir == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent * entry;
|
||||
|
||||
|
||||
while ((entry = readdir(dir))) {
|
||||
if (g_str_has_prefix(entry->d_name, ".")) { // A reference to parent dir, self, or a hidden item
|
||||
continue;
|
||||
|
@ -406,8 +507,10 @@ void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
|||
KotoIndexedArtist * artist = koto_indexed_artist_new(full_path); // Attempt to get the artist
|
||||
gchar * artist_name;
|
||||
|
||||
g_object_get(artist,
|
||||
"name", &artist_name,
|
||||
g_object_get(
|
||||
artist,
|
||||
"name",
|
||||
&artist_name,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
@ -439,25 +542,36 @@ void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
|||
closedir(dir); // Close the directory
|
||||
}
|
||||
|
||||
void output_artists(gpointer artist_key, gpointer artist_ptr, gpointer data) {
|
||||
(void) artist_ptr; (void) data;
|
||||
void output_artists(
|
||||
gpointer artist_key,
|
||||
gpointer artist_ptr,
|
||||
gpointer data
|
||||
) {
|
||||
(void) artist_ptr;
|
||||
(void) data;
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, (gchar*) artist_key);
|
||||
|
||||
|
||||
if (artist == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * artist_name;
|
||||
|
||||
|
||||
g_object_get(artist, "name", &artist_name, NULL);
|
||||
g_debug("Artist: %s", artist_name);
|
||||
|
||||
GList * albums = koto_indexed_artist_get_albums(artist); // Get the albums for this artist
|
||||
|
||||
|
||||
if (albums != NULL) {
|
||||
g_debug("Length of Albums: %d", g_list_length(albums));
|
||||
}
|
||||
|
||||
GList * a;
|
||||
|
||||
|
||||
for (a = albums; a != NULL; a = a->next) {
|
||||
gchar * album_uuid = a->data;
|
||||
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||
|
@ -476,11 +590,15 @@ void output_artists(gpointer artist_key, gpointer artist_ptr, gpointer data) {
|
|||
}
|
||||
}
|
||||
|
||||
void output_track(gpointer data, gpointer user_data) {
|
||||
void output_track(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) data);
|
||||
|
||||
|
||||
if (track == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -489,11 +607,8 @@ void output_track(gpointer data, gpointer user_data) {
|
|||
gchar * parsed_name;
|
||||
guint * pos;
|
||||
|
||||
g_object_get(track,
|
||||
"path", &filepath,
|
||||
"parsed-name", &parsed_name,
|
||||
"position", &pos,
|
||||
NULL);
|
||||
|
||||
g_object_get(track, "path", &filepath, "parsed-name", &parsed_name, "position", &pos, NULL);
|
||||
g_debug("File Path: %s", filepath);
|
||||
g_debug("Parsed Name: %s", parsed_name);
|
||||
g_debug("Position: %d", GPOINTER_TO_INT(pos));
|
||||
|
|
|
@ -47,80 +47,254 @@ G_DECLARE_FINAL_TYPE(KotoIndexedTrack, koto_indexed_track, KOTO, INDEXED_TRACK,
|
|||
|
||||
KotoIndexedLibrary * koto_indexed_library_new(const gchar * path);
|
||||
|
||||
void koto_indexed_library_add_artist(KotoIndexedLibrary *self, KotoIndexedArtist *artist);
|
||||
KotoIndexedArtist* koto_indexed_library_get_artist(KotoIndexedLibrary *self, gchar* artist_name);
|
||||
void koto_indexed_library_add_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
KotoIndexedArtist * koto_indexed_library_get_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar* artist_name
|
||||
);
|
||||
|
||||
GHashTable * koto_indexed_library_get_artists(KotoIndexedLibrary * self);
|
||||
void koto_indexed_library_remove_artist(KotoIndexedLibrary *self, KotoIndexedArtist *artist);
|
||||
void koto_indexed_library_set_path(KotoIndexedLibrary *self, gchar *path);
|
||||
int process_artists(void *data, int num_columns, char **fields, char **column_names);
|
||||
int process_albums(void *data, int num_columns, char **fields, char **column_names);
|
||||
int process_playlists(void *data, int num_columns, char **fields, char **column_names);
|
||||
int process_playlists_tracks(void *data, int num_columns, char **fields, char **column_names);
|
||||
int process_tracks(void *data, int num_columns, char **fields, char **column_names);
|
||||
|
||||
void koto_indexed_library_remove_artist(
|
||||
KotoIndexedLibrary * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
void koto_indexed_library_set_path(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar * path
|
||||
);
|
||||
|
||||
int process_artists(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
);
|
||||
|
||||
int process_albums(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
);
|
||||
|
||||
int process_playlists(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
);
|
||||
|
||||
int process_playlists_tracks(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
);
|
||||
|
||||
int process_tracks(
|
||||
void * data,
|
||||
int num_columns,
|
||||
char ** fields,
|
||||
char ** column_names
|
||||
);
|
||||
|
||||
void read_from_db(KotoIndexedLibrary * self);
|
||||
|
||||
void start_indexing(KotoIndexedLibrary * self);
|
||||
void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth);
|
||||
void output_track(gpointer data, gpointer user_data);
|
||||
|
||||
void index_folder(
|
||||
KotoIndexedLibrary * self,
|
||||
gchar * path,
|
||||
guint depth
|
||||
);
|
||||
|
||||
void output_track(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
/**
|
||||
* Artist Functions
|
||||
**/
|
||||
|
||||
KotoIndexedArtist * koto_indexed_artist_new(gchar * path);
|
||||
|
||||
KotoIndexedArtist * koto_indexed_artist_new_with_uuid(const gchar * uuid);
|
||||
|
||||
void koto_indexed_artist_add_album(KotoIndexedArtist *self, gchar *album_uuid);
|
||||
void koto_indexed_artist_add_album(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * album_uuid
|
||||
);
|
||||
|
||||
void koto_indexed_artist_commit(KotoIndexedArtist * self);
|
||||
guint koto_indexed_artist_find_album_with_name(gconstpointer *album_data, gconstpointer *album_name_data);
|
||||
|
||||
guint koto_indexed_artist_find_album_with_name(
|
||||
gconstpointer * album_data,
|
||||
gconstpointer * album_name_data
|
||||
);
|
||||
|
||||
GList * koto_indexed_artist_get_albums(KotoIndexedArtist * self);
|
||||
|
||||
gchar * koto_indexed_artist_get_name(KotoIndexedArtist * self);
|
||||
void koto_indexed_artist_remove_album(KotoIndexedArtist *self, KotoIndexedAlbum *album);
|
||||
void koto_indexed_artist_remove_album_by_name(KotoIndexedArtist *self, gchar *album_name);
|
||||
void koto_indexed_artist_set_artist_name(KotoIndexedArtist *self, gchar *artist_name);
|
||||
void koto_indexed_artist_update_path(KotoIndexedArtist *self, gchar *new_path);
|
||||
void output_artists(gpointer artist_key, gpointer artist_ptr, gpointer data);
|
||||
|
||||
void koto_indexed_artist_remove_album(
|
||||
KotoIndexedArtist * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_indexed_artist_remove_album_by_name(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * album_name
|
||||
);
|
||||
|
||||
void koto_indexed_artist_set_artist_name(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * artist_name
|
||||
);
|
||||
|
||||
void koto_indexed_artist_update_path(
|
||||
KotoIndexedArtist * self,
|
||||
gchar * new_path
|
||||
);
|
||||
|
||||
void output_artists(
|
||||
gpointer artist_key,
|
||||
gpointer artist_ptr,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
/**
|
||||
* Album Functions
|
||||
**/
|
||||
|
||||
KotoIndexedAlbum* koto_indexed_album_new(KotoIndexedArtist *artist, const gchar *path);
|
||||
KotoIndexedAlbum* koto_indexed_album_new_with_uuid(KotoIndexedArtist *artist, const gchar *uuid);
|
||||
KotoIndexedAlbum * koto_indexed_album_new(
|
||||
KotoIndexedArtist * artist,
|
||||
const gchar * path
|
||||
);
|
||||
|
||||
KotoIndexedAlbum * koto_indexed_album_new_with_uuid(
|
||||
KotoIndexedArtist * artist,
|
||||
const gchar * uuid
|
||||
);
|
||||
|
||||
void koto_indexed_album_add_track(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
void koto_indexed_album_add_track(KotoIndexedAlbum *self, KotoIndexedTrack *track);
|
||||
void koto_indexed_album_commit(KotoIndexedAlbum * self);
|
||||
|
||||
void koto_indexed_album_find_album_art(KotoIndexedAlbum * self);
|
||||
void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie, const gchar *path);
|
||||
|
||||
void koto_indexed_album_find_tracks(
|
||||
KotoIndexedAlbum * self,
|
||||
magic_t magic_cookie,
|
||||
const gchar * path
|
||||
);
|
||||
|
||||
gchar * koto_indexed_album_get_album_art(KotoIndexedAlbum * self);
|
||||
|
||||
gchar * koto_indexed_album_get_album_name(KotoIndexedAlbum * self);
|
||||
|
||||
gchar * koto_indexed_album_get_album_uuid(KotoIndexedAlbum * self);
|
||||
|
||||
GList * koto_indexed_album_get_tracks(KotoIndexedAlbum * self);
|
||||
void koto_indexed_album_remove_file(KotoIndexedAlbum *self, KotoIndexedTrack *track);
|
||||
void koto_indexed_album_set_album_art(KotoIndexedAlbum *self, const gchar *album_art);
|
||||
void koto_indexed_album_set_album_name(KotoIndexedAlbum *self, const gchar *album_name);
|
||||
void koto_indexed_album_set_artist_uuid(KotoIndexedAlbum *self, const gchar *artist_uuid);
|
||||
|
||||
void koto_indexed_album_remove_file(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
void koto_indexed_album_set_album_art(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * album_art
|
||||
);
|
||||
|
||||
void koto_indexed_album_set_album_name(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * album_name
|
||||
);
|
||||
|
||||
void koto_indexed_album_set_artist_uuid(
|
||||
KotoIndexedAlbum * self,
|
||||
const gchar * artist_uuid
|
||||
);
|
||||
|
||||
void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum * self);
|
||||
void koto_indexed_album_update_path(KotoIndexedAlbum *self, gchar *path);
|
||||
gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer track2_uuid, gpointer user_data);
|
||||
|
||||
void koto_indexed_album_update_path(
|
||||
KotoIndexedAlbum * self,
|
||||
gchar * path
|
||||
);
|
||||
|
||||
gint koto_indexed_album_sort_tracks(
|
||||
gconstpointer track1_uuid,
|
||||
gconstpointer track2_uuid,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
/**
|
||||
* File / Track Functions
|
||||
**/
|
||||
|
||||
KotoIndexedTrack* koto_indexed_track_new(KotoIndexedAlbum *album, const gchar *path, guint *cd);
|
||||
KotoIndexedTrack * koto_indexed_track_new(
|
||||
KotoIndexedAlbum * album,
|
||||
const gchar * path,
|
||||
guint * cd
|
||||
);
|
||||
|
||||
KotoIndexedTrack * koto_indexed_track_new_with_uuid(const gchar * uuid);
|
||||
|
||||
void koto_indexed_track_commit(KotoIndexedTrack * self);
|
||||
|
||||
GVariant * koto_indexed_track_get_metadata_vardict(KotoIndexedTrack * self);
|
||||
|
||||
gchar * koto_indexed_track_get_uuid(KotoIndexedTrack * self);
|
||||
|
||||
void koto_indexed_track_parse_name(KotoIndexedTrack * self);
|
||||
void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *playlist_uuid);
|
||||
void koto_indexed_track_save_to_playlist(KotoIndexedTrack *self, gchar *playlist_uuid, gint current);
|
||||
void koto_indexed_track_set_file_name(KotoIndexedTrack *self, gchar *new_file_name);
|
||||
void koto_indexed_track_set_cd(KotoIndexedTrack *self, guint cd);
|
||||
void koto_indexed_track_set_parsed_name(KotoIndexedTrack *self, gchar *new_parsed_name);
|
||||
void koto_indexed_track_set_position(KotoIndexedTrack *self, guint pos);
|
||||
|
||||
void koto_indexed_track_remove_from_playlist(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * playlist_uuid
|
||||
);
|
||||
|
||||
void koto_indexed_track_save_to_playlist(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * playlist_uuid,
|
||||
gint current
|
||||
);
|
||||
|
||||
void koto_indexed_track_set_file_name(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * new_file_name
|
||||
);
|
||||
|
||||
void koto_indexed_track_set_cd(
|
||||
KotoIndexedTrack * self,
|
||||
guint cd
|
||||
);
|
||||
|
||||
void koto_indexed_track_set_parsed_name(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * new_parsed_name
|
||||
);
|
||||
|
||||
void koto_indexed_track_set_position(
|
||||
KotoIndexedTrack * self,
|
||||
guint pos
|
||||
);
|
||||
|
||||
void koto_indexed_track_update_metadata(KotoIndexedTrack * self);
|
||||
void koto_indexed_track_update_path(KotoIndexedTrack *self, const gchar *new_path);
|
||||
|
||||
void koto_indexed_track_update_path(
|
||||
KotoIndexedTrack * self,
|
||||
const gchar * new_path
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -59,13 +59,28 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static void koto_indexed_track_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_track_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_indexed_track_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_track_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_indexed_track_class_init(KotoIndexedTrackClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_indexed_track_set_property;
|
||||
gobject_class->get_property = koto_indexed_track_get_property;
|
||||
|
@ -163,9 +178,15 @@ static void koto_indexed_track_init(KotoIndexedTrack *self) {
|
|||
self->acquired_metadata_from_id3 = FALSE;
|
||||
}
|
||||
|
||||
static void koto_indexed_track_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_track_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedTrack * self = KOTO_INDEXED_TRACK(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST_UUID:
|
||||
g_value_set_string(val, self->artist_uuid);
|
||||
|
@ -200,9 +221,15 @@ static void koto_indexed_track_get_property(GObject *obj, guint prop_id, GValue
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_indexed_track_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_indexed_track_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoIndexedTrack * self = KOTO_INDEXED_TRACK(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST_UUID:
|
||||
self->artist_uuid = g_strdup(g_value_get_string(val));
|
||||
|
@ -270,6 +297,7 @@ void koto_indexed_track_commit(KotoIndexedTrack *self) {
|
|||
gchar * commit_op_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to write our file to the database: %s", commit_op_errmsg);
|
||||
}
|
||||
|
@ -292,14 +320,10 @@ GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self) {
|
|||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, self->artist_uuid);
|
||||
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, self->album_uuid);
|
||||
|
||||
g_object_get(album,
|
||||
"art-path", &album_art_path,
|
||||
"name", &album_name,
|
||||
NULL);
|
||||
|
||||
g_object_get(artist,
|
||||
"name", &artist_name,
|
||||
NULL);
|
||||
g_object_get(album, "art-path", &album_art_path, "name", &album_name, NULL);
|
||||
|
||||
g_object_get(artist, "name", &artist_name, NULL);
|
||||
|
||||
g_variant_builder_add(builder, "{sv}", "mpris:trackid", g_variant_new_string(self->uuid));
|
||||
|
||||
|
@ -328,6 +352,7 @@ GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self) {
|
|||
|
||||
GVariant * metadata_ret = g_variant_builder_end(builder);
|
||||
|
||||
|
||||
return metadata_ret;
|
||||
}
|
||||
|
||||
|
@ -343,6 +368,8 @@ void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
|||
gchar * copied_file_name = g_strdelimit(g_strdup(self->file_name), "_", ' '); // Replace _ with whitespace for starters
|
||||
|
||||
KotoIndexedArtist * artist = NULL;
|
||||
|
||||
|
||||
artist = koto_cartographer_get_artist_by_uuid(koto_maps, self->artist_uuid);
|
||||
|
||||
if (artist != NULL) { // If we have artist
|
||||
|
@ -361,10 +388,13 @@ void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
|||
}
|
||||
|
||||
gchar * file_without_ext = koto_utils_get_filename_without_extension(copied_file_name);
|
||||
|
||||
|
||||
g_free(copied_file_name);
|
||||
|
||||
gchar ** split = g_regex_split_simple("^([\\d]+)", file_without_ext, G_REGEX_JAVASCRIPT_COMPAT, 0);
|
||||
|
||||
|
||||
if (g_strv_length(split) > 1) { // Has positional info at the beginning of the file
|
||||
gchar * num = split[1];
|
||||
|
||||
|
@ -396,7 +426,10 @@ void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
|||
g_free(file_without_ext);
|
||||
}
|
||||
|
||||
void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *playlist_uuid) {
|
||||
void koto_indexed_track_remove_from_playlist(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * playlist_uuid
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -409,6 +442,8 @@ void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *play
|
|||
|
||||
gchar * commit_op_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to remove track from playlist: %s", commit_op_errmsg);
|
||||
}
|
||||
|
@ -417,7 +452,11 @@ void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *play
|
|||
g_free(commit_op_errmsg);
|
||||
}
|
||||
|
||||
void koto_indexed_track_save_to_playlist(KotoIndexedTrack *self, gchar *playlist_uuid, gint current) {
|
||||
void koto_indexed_track_save_to_playlist(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * playlist_uuid,
|
||||
gint current
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -433,6 +472,7 @@ void koto_indexed_track_save_to_playlist(KotoIndexedTrack *self, gchar *playlist
|
|||
gchar * commit_op_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to save track to playlist: %s", commit_op_errmsg);
|
||||
}
|
||||
|
@ -441,7 +481,10 @@ void koto_indexed_track_save_to_playlist(KotoIndexedTrack *self, gchar *playlist
|
|||
g_free(commit_op_errmsg);
|
||||
}
|
||||
|
||||
void koto_indexed_track_set_file_name(KotoIndexedTrack *self, gchar *new_file_name) {
|
||||
void koto_indexed_track_set_file_name(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * new_file_name
|
||||
) {
|
||||
if (new_file_name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -462,7 +505,10 @@ void koto_indexed_track_set_file_name(KotoIndexedTrack *self, gchar *new_file_na
|
|||
}
|
||||
}
|
||||
|
||||
void koto_indexed_track_set_cd(KotoIndexedTrack *self, guint cd) {
|
||||
void koto_indexed_track_set_cd(
|
||||
KotoIndexedTrack * self,
|
||||
guint cd
|
||||
) {
|
||||
if (cd == 0) { // No change really
|
||||
return;
|
||||
}
|
||||
|
@ -471,7 +517,10 @@ void koto_indexed_track_set_cd(KotoIndexedTrack *self, guint cd) {
|
|||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_CD]);
|
||||
}
|
||||
|
||||
void koto_indexed_track_set_parsed_name(KotoIndexedTrack *self, gchar *new_parsed_name) {
|
||||
void koto_indexed_track_set_parsed_name(
|
||||
KotoIndexedTrack * self,
|
||||
gchar * new_parsed_name
|
||||
) {
|
||||
if (new_parsed_name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -488,7 +537,10 @@ void koto_indexed_track_set_parsed_name(KotoIndexedTrack *self, gchar *new_parse
|
|||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PARSED_NAME]);
|
||||
}
|
||||
|
||||
void koto_indexed_track_set_position(KotoIndexedTrack *self, guint pos) {
|
||||
void koto_indexed_track_set_position(
|
||||
KotoIndexedTrack * self,
|
||||
guint pos
|
||||
) {
|
||||
if (pos == 0) { // No position change really
|
||||
return;
|
||||
}
|
||||
|
@ -500,6 +552,7 @@ void koto_indexed_track_set_position(KotoIndexedTrack *self, guint pos) {
|
|||
void koto_indexed_track_update_metadata(KotoIndexedTrack * self) {
|
||||
TagLib_File * t_file = taglib_file_new(self->path); // Get a taglib file for this file
|
||||
|
||||
|
||||
if ((t_file != NULL) && taglib_file_is_valid(t_file)) { // If we got the taglib file and it is valid
|
||||
self->acquired_metadata_from_id3 = TRUE;
|
||||
TagLib_Tag * tag = taglib_file_tag(t_file); // Get our tag
|
||||
|
@ -514,7 +567,10 @@ void koto_indexed_track_update_metadata(KotoIndexedTrack *self) {
|
|||
taglib_file_free(t_file); // Free the file
|
||||
}
|
||||
|
||||
void koto_indexed_track_update_path(KotoIndexedTrack *self, const gchar *new_path) {
|
||||
void koto_indexed_track_update_path(
|
||||
KotoIndexedTrack * self,
|
||||
const gchar * new_path
|
||||
) {
|
||||
if (new_path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -532,29 +588,44 @@ void koto_indexed_track_update_path(KotoIndexedTrack *self, const gchar *new_pat
|
|||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PATH]);
|
||||
}
|
||||
|
||||
KotoIndexedTrack* koto_indexed_track_new(KotoIndexedAlbum *album, const gchar *path, guint *cd) {
|
||||
KotoIndexedTrack * koto_indexed_track_new(
|
||||
KotoIndexedAlbum * album,
|
||||
const gchar * path,
|
||||
guint * cd
|
||||
) {
|
||||
gchar * artist_uuid;
|
||||
gchar * album_uuid;
|
||||
|
||||
|
||||
g_object_get(album, "artist-uuid", &artist_uuid, "uuid", &album_uuid, NULL); // Get the artist and album uuids from our Album
|
||||
|
||||
KotoIndexedTrack *track = g_object_new(KOTO_TYPE_INDEXED_TRACK,
|
||||
"artist-uuid", artist_uuid,
|
||||
"album-uuid", album_uuid,
|
||||
"do-initial-index", TRUE,
|
||||
"uuid", g_uuid_string_random(),
|
||||
"path", path,
|
||||
"cd", cd,
|
||||
KotoIndexedTrack * track = g_object_new(
|
||||
KOTO_TYPE_INDEXED_TRACK,
|
||||
"artist-uuid",
|
||||
artist_uuid,
|
||||
"album-uuid",
|
||||
album_uuid,
|
||||
"do-initial-index",
|
||||
TRUE,
|
||||
"uuid",
|
||||
g_uuid_string_random(),
|
||||
"path",
|
||||
path,
|
||||
"cd",
|
||||
cd,
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
koto_indexed_track_commit(track); // Immediately commit to the database
|
||||
return track;
|
||||
}
|
||||
|
||||
KotoIndexedTrack * koto_indexed_track_new_with_uuid(const gchar * uuid) {
|
||||
return g_object_new(KOTO_TYPE_INDEXED_TRACK,
|
||||
"uuid", g_strdup(uuid),
|
||||
return g_object_new(
|
||||
KOTO_TYPE_INDEXED_TRACK,
|
||||
"uuid",
|
||||
g_strdup(uuid),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,9 @@ enum {
|
|||
N_BTN_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *btn_props[N_BTN_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * btn_props[N_BTN_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct _KotoButton {
|
||||
GtkBox parent_instance;
|
||||
|
@ -93,11 +95,25 @@ struct _KotoButtonClass {
|
|||
G_DEFINE_TYPE(KotoButton, koto_button, GTK_TYPE_BOX);
|
||||
|
||||
static void koto_button_constructed(GObject * obj);
|
||||
static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
|
||||
static void koto_button_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_button_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_button_class_init(KotoButtonClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->constructed = koto_button_constructed;
|
||||
gobject_class->set_property = koto_button_set_property;
|
||||
|
@ -181,14 +197,22 @@ static void koto_button_init(KotoButton *self) {
|
|||
static void koto_button_constructed(GObject * obj) {
|
||||
KotoButton * self = KOTO_BUTTON(obj);
|
||||
GtkStyleContext * style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
||||
|
||||
|
||||
gtk_style_context_add_class(style, "koto-button");
|
||||
|
||||
G_OBJECT_CLASS(koto_button_parent_class)->constructed(obj);
|
||||
}
|
||||
|
||||
static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_button_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoButton * self = KOTO_BUTTON(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_IMAGE_FILE_PATH:
|
||||
g_value_set_string(val, self->image_file_path);
|
||||
|
@ -217,9 +241,15 @@ static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, G
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_button_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoButton * self = KOTO_BUTTON(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PIX_SIZE:
|
||||
koto_button_set_pixbuf_size(self, g_value_get_uint(val));
|
||||
|
@ -257,7 +287,12 @@ static void koto_button_set_property(GObject *obj, guint prop_id, const GValue *
|
|||
}
|
||||
}
|
||||
|
||||
void koto_button_add_click_handler(KotoButton *self, KotoButtonClickType button, GCallback handler, gpointer user_data) {
|
||||
void koto_button_add_click_handler(
|
||||
KotoButton * self,
|
||||
KotoButtonClickType button,
|
||||
GCallback handler,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_BUTTON(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -283,7 +318,10 @@ void koto_button_hide_image(KotoButton *self) {
|
|||
}
|
||||
}
|
||||
|
||||
void koto_button_set_badge_text(KotoButton *self, gchar *text) {
|
||||
void koto_button_set_badge_text(
|
||||
KotoButton * self,
|
||||
gchar * text
|
||||
) {
|
||||
if ((text == NULL) || (strcmp(text, "") == 0)) { // If the text is empty
|
||||
self->badge_text = g_strdup("");
|
||||
} else {
|
||||
|
@ -307,7 +345,10 @@ void koto_button_set_badge_text(KotoButton *self, gchar *text) {
|
|||
g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_BADGE_TEXT]);
|
||||
}
|
||||
|
||||
void koto_button_set_file_path(KotoButton *self, gchar *file_path) {
|
||||
void koto_button_set_file_path(
|
||||
KotoButton * self,
|
||||
gchar * file_path
|
||||
) {
|
||||
if (!KOTO_IS_BUTTON(self)) { // Not a button
|
||||
return;
|
||||
}
|
||||
|
@ -324,9 +365,14 @@ void koto_button_set_file_path(KotoButton *self, gchar *file_path) {
|
|||
koto_button_show_image(self, FALSE);
|
||||
}
|
||||
|
||||
void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_alt) {
|
||||
void koto_button_set_icon_name(
|
||||
KotoButton * self,
|
||||
gchar * icon_name,
|
||||
gboolean for_alt
|
||||
) {
|
||||
gchar * copied_icon_name = g_strdup(icon_name);
|
||||
|
||||
|
||||
if (for_alt) { // Is for the alternate icon
|
||||
if ((self->alt_icon_name != NULL) && strcmp(icon_name, self->alt_icon_name) != 0) { // If the icons are different
|
||||
g_free(self->alt_icon_name);
|
||||
|
@ -342,6 +388,8 @@ void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_
|
|||
}
|
||||
|
||||
gboolean hide_image = FALSE;
|
||||
|
||||
|
||||
if (for_alt && self->currently_showing_alt && ((self->alt_icon_name == NULL) || strcmp(self->alt_icon_name, "") == 0)) { // For alt, alt is currently showing, and no longer have alt
|
||||
hide_image = TRUE;
|
||||
} else if (!for_alt && ((self->icon_name == NULL) || (strcmp(self->icon_name, "") == 0))) { // Not for alt, no icon
|
||||
|
@ -359,7 +407,10 @@ void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_
|
|||
g_object_notify_by_pspec(G_OBJECT(self), for_alt ? btn_props[PROP_ALT_ICON_NAME] : btn_props[PROP_ICON_NAME]);
|
||||
}
|
||||
|
||||
void koto_button_set_image_position(KotoButton *self, KotoButtonImagePosition pos) {
|
||||
void koto_button_set_image_position(
|
||||
KotoButton * self,
|
||||
KotoButtonImagePosition pos
|
||||
) {
|
||||
if (self->image_position == pos) { // Is a different position that currently
|
||||
return;
|
||||
}
|
||||
|
@ -375,7 +426,10 @@ void koto_button_set_image_position(KotoButton *self, KotoButtonImagePosition po
|
|||
self->image_position = pos;
|
||||
}
|
||||
|
||||
void koto_button_set_pixbuf_size(KotoButton *self, guint size) {
|
||||
void koto_button_set_pixbuf_size(
|
||||
KotoButton * self,
|
||||
guint size
|
||||
) {
|
||||
if (size == self->pix_size) {
|
||||
return;
|
||||
}
|
||||
|
@ -386,7 +440,10 @@ void koto_button_set_pixbuf_size(KotoButton *self, guint size) {
|
|||
g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_PIX_SIZE]);
|
||||
}
|
||||
|
||||
void koto_button_set_text(KotoButton *self, gchar *text) {
|
||||
void koto_button_set_text(
|
||||
KotoButton * self,
|
||||
gchar * text
|
||||
) {
|
||||
if (text == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -421,7 +478,10 @@ void koto_button_set_text(KotoButton *self, gchar *text) {
|
|||
g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_TEXT]);
|
||||
}
|
||||
|
||||
void koto_button_show_image(KotoButton *self, gboolean use_alt) {
|
||||
void koto_button_show_image(
|
||||
KotoButton * self,
|
||||
gboolean use_alt
|
||||
) {
|
||||
if (!KOTO_IS_BUTTON(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -470,25 +530,43 @@ void koto_button_unflatten(KotoButton *self) {
|
|||
}
|
||||
|
||||
KotoButton * koto_button_new_plain(gchar * label) {
|
||||
return g_object_new(KOTO_TYPE_BUTTON,
|
||||
"button-text", label,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_BUTTON,
|
||||
"button-text",
|
||||
label,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, gchar *alt_icon_name, KotoButtonPixbufSize size) {
|
||||
return g_object_new(KOTO_TYPE_BUTTON,
|
||||
"button-text", label,
|
||||
"icon-name", icon_name,
|
||||
"alt-icon-name", alt_icon_name,
|
||||
"pixbuf-size", koto_get_pixbuf_size(size),
|
||||
KotoButton * koto_button_new_with_icon(
|
||||
gchar * label,
|
||||
gchar * icon_name,
|
||||
gchar * alt_icon_name,
|
||||
KotoButtonPixbufSize size
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_BUTTON,
|
||||
"button-text",
|
||||
label,
|
||||
"icon-name",
|
||||
icon_name,
|
||||
"alt-icon-name",
|
||||
alt_icon_name,
|
||||
"pixbuf-size",
|
||||
koto_get_pixbuf_size(size),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
KotoButton *koto_button_new_with_file(gchar *label, gchar *file_path, KotoButtonPixbufSize size) {
|
||||
return g_object_new(KOTO_TYPE_BUTTON,
|
||||
"button-text", label,
|
||||
KotoButton * koto_button_new_with_file(
|
||||
gchar * label,
|
||||
gchar * file_path,
|
||||
KotoButtonPixbufSize size
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_BUTTON,
|
||||
"button-text",
|
||||
label,
|
||||
"use-from-file",
|
||||
TRUE,
|
||||
"image-file-path",
|
||||
|
|
|
@ -52,20 +52,72 @@ G_DECLARE_FINAL_TYPE (KotoButton, koto_button, KOTO, BUTTON, GtkBox)
|
|||
guint koto_get_pixbuf_size(KotoButtonPixbufSize size);
|
||||
|
||||
KotoButton * koto_button_new_plain(gchar * label);
|
||||
KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, gchar *alt_icon_name, KotoButtonPixbufSize size);
|
||||
KotoButton *koto_button_new_with_file(gchar *label, gchar *file_path, KotoButtonPixbufSize size);
|
||||
|
||||
void koto_button_add_click_handler(KotoButton *self, KotoButtonClickType button, GCallback handler, gpointer user_data);
|
||||
KotoButton * koto_button_new_with_icon(
|
||||
gchar * label,
|
||||
gchar * icon_name,
|
||||
gchar * alt_icon_name,
|
||||
KotoButtonPixbufSize size
|
||||
);
|
||||
|
||||
KotoButton * koto_button_new_with_file(
|
||||
gchar * label,
|
||||
gchar * file_path,
|
||||
KotoButtonPixbufSize size
|
||||
);
|
||||
|
||||
void koto_button_add_click_handler(
|
||||
KotoButton * self,
|
||||
KotoButtonClickType button,
|
||||
GCallback handler,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_button_flip(KotoButton * self);
|
||||
|
||||
void koto_button_hide_image(KotoButton * self);
|
||||
void koto_button_set_badge_text(KotoButton *self, gchar *text);
|
||||
void koto_button_set_file_path(KotoButton *self, gchar *file_path);
|
||||
void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_alt);
|
||||
void koto_button_set_image_position(KotoButton *self, KotoButtonImagePosition pos);
|
||||
void koto_button_set_pixbuf(KotoButton *self, GdkPixbuf *pix);
|
||||
void koto_button_set_pixbuf_size(KotoButton *self, guint size);
|
||||
void koto_button_set_text(KotoButton *self, gchar *text);
|
||||
void koto_button_show_image(KotoButton *self, gboolean use_alt);
|
||||
|
||||
void koto_button_set_badge_text(
|
||||
KotoButton * self,
|
||||
gchar * text
|
||||
);
|
||||
|
||||
void koto_button_set_file_path(
|
||||
KotoButton * self,
|
||||
gchar * file_path
|
||||
);
|
||||
|
||||
void koto_button_set_icon_name(
|
||||
KotoButton * self,
|
||||
gchar * icon_name,
|
||||
gboolean for_alt
|
||||
);
|
||||
|
||||
void koto_button_set_image_position(
|
||||
KotoButton * self,
|
||||
KotoButtonImagePosition pos
|
||||
);
|
||||
|
||||
void koto_button_set_pixbuf(
|
||||
KotoButton * self,
|
||||
GdkPixbuf * pix
|
||||
);
|
||||
|
||||
void koto_button_set_pixbuf_size(
|
||||
KotoButton * self,
|
||||
guint size
|
||||
);
|
||||
|
||||
void koto_button_set_text(
|
||||
KotoButton * self,
|
||||
gchar * text
|
||||
);
|
||||
|
||||
void koto_button_show_image(
|
||||
KotoButton * self,
|
||||
gboolean use_alt
|
||||
);
|
||||
|
||||
void koto_button_unflatten(KotoButton * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -35,12 +35,7 @@ static void koto_dialog_container_class_init(KotoDialogContainerClass *c) {
|
|||
static void koto_dialog_container_init(KotoDialogContainer * self) {
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self), "koto-dialog-container");
|
||||
|
||||
g_object_set(GTK_WIDGET(self),
|
||||
"hexpand",
|
||||
TRUE,
|
||||
"vexpand",
|
||||
TRUE,
|
||||
NULL);
|
||||
g_object_set(GTK_WIDGET(self), "hexpand", TRUE, "vexpand", TRUE, NULL);
|
||||
|
||||
self->close_button = koto_button_new_with_icon(NULL, "window-close-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_LARGE);
|
||||
gtk_widget_set_halign(GTK_WIDGET(self->close_button), GTK_ALIGN_END);
|
||||
|
@ -60,7 +55,11 @@ static void koto_dialog_container_init(KotoDialogContainer *self) {
|
|||
gtk_widget_hide(GTK_WIDGET(self)); // Hide by default
|
||||
}
|
||||
|
||||
void koto_dialog_container_add_dialog(KotoDialogContainer *self, gchar *dialog_name, GtkWidget *dialog) {
|
||||
void koto_dialog_container_add_dialog(
|
||||
KotoDialogContainer * self,
|
||||
gchar * dialog_name,
|
||||
GtkWidget * dialog
|
||||
) {
|
||||
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
||||
return;
|
||||
}
|
||||
|
@ -68,8 +67,17 @@ void koto_dialog_container_add_dialog(KotoDialogContainer *self, gchar *dialog_n
|
|||
gtk_stack_add_named(GTK_STACK(self->dialogs), dialog, dialog_name); // Add the dialog to the stack
|
||||
}
|
||||
|
||||
void koto_dialog_container_handle_close_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_dialog_container_handle_close_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
koto_dialog_container_hide((KotoDialogContainer*) user_data);
|
||||
}
|
||||
|
||||
|
@ -81,7 +89,10 @@ void koto_dialog_container_hide(KotoDialogContainer *self) {
|
|||
gtk_widget_hide(GTK_WIDGET(self));
|
||||
}
|
||||
|
||||
void koto_dialog_container_show_dialog(KotoDialogContainer *self, gchar *dialog_name) {
|
||||
void koto_dialog_container_show_dialog(
|
||||
KotoDialogContainer * self,
|
||||
gchar * dialog_name
|
||||
) {
|
||||
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
||||
return;
|
||||
}
|
||||
|
@ -91,7 +102,8 @@ void koto_dialog_container_show_dialog(KotoDialogContainer *self, gchar *dialog_
|
|||
}
|
||||
|
||||
KotoDialogContainer * koto_dialog_container_new() {
|
||||
return g_object_new(KOTO_TYPE_DIALOG_CONTAINER,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_DIALOG_CONTAINER,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
NULL
|
||||
|
|
|
@ -34,9 +34,26 @@ G_DECLARE_FINAL_TYPE(KotoDialogContainer, koto_dialog_container, KOTO, DIALOG_CO
|
|||
**/
|
||||
|
||||
KotoDialogContainer * koto_dialog_container_new();
|
||||
void koto_dialog_container_add_dialog(KotoDialogContainer *self, gchar *dialog_name, GtkWidget *dialog);
|
||||
void koto_dialog_container_handle_close_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
|
||||
void koto_dialog_container_add_dialog(
|
||||
KotoDialogContainer * self,
|
||||
gchar * dialog_name,
|
||||
GtkWidget * dialog
|
||||
);
|
||||
|
||||
void koto_dialog_container_handle_close_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_dialog_container_hide(KotoDialogContainer * self);
|
||||
void koto_dialog_container_show_dialog(KotoDialogContainer *self, gchar *dialog_name);
|
||||
|
||||
void koto_dialog_container_show_dialog(
|
||||
KotoDialogContainer * self,
|
||||
gchar * dialog_name
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -30,7 +30,9 @@ enum {
|
|||
N_EXP_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *expander_props[N_EXP_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * expander_props[N_EXP_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct _KotoExpander {
|
||||
GtkBox parent_instance;
|
||||
|
@ -54,11 +56,24 @@ struct _KotoExpanderClass {
|
|||
|
||||
G_DEFINE_TYPE(KotoExpander, koto_expander, GTK_TYPE_BOX);
|
||||
|
||||
static void koto_expander_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_expander_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_expander_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_expander_class_init(KotoExpanderClass * c) {
|
||||
GObjectClass * gobject_class = G_OBJECT_CLASS(c);
|
||||
|
||||
|
||||
gobject_class->set_property = koto_expander_set_property;
|
||||
gobject_class->get_property = koto_expander_get_property;
|
||||
|
||||
|
@ -97,9 +112,15 @@ static void koto_expander_class_init(KotoExpanderClass *c) {
|
|||
g_object_class_install_properties(gobject_class, N_EXP_PROPERTIES, expander_props);
|
||||
}
|
||||
|
||||
static void koto_expander_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_expander_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoExpander * self = KOTO_EXPANDER(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_HEADER_ICON_NAME:
|
||||
g_value_set_string(val, self->icon_name);
|
||||
|
@ -119,9 +140,15 @@ static void koto_expander_get_property(GObject *obj, guint prop_id, GValue *val,
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_expander_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoExpander * self = KOTO_EXPANDER(obj);
|
||||
|
||||
|
||||
if (!GTK_IS_WIDGET(self->header_button)) { // Header Button is not a widget
|
||||
KotoButton * new_button = koto_button_new_with_icon(NULL, "emblem-favorite-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||
|
||||
|
@ -155,12 +182,16 @@ static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue
|
|||
|
||||
static void koto_expander_init(KotoExpander * self) {
|
||||
GtkStyleContext * style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
||||
|
||||
|
||||
gtk_style_context_add_class(style, "expander");
|
||||
gtk_widget_set_hexpand((GTK_WIDGET(self)), TRUE);
|
||||
|
||||
self->header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
|
||||
GtkStyleContext * header_style = gtk_widget_get_style_context(self->header);
|
||||
|
||||
|
||||
gtk_style_context_add_class(header_style, "expander-header");
|
||||
|
||||
self->revealer = gtk_revealer_new();
|
||||
|
@ -178,7 +209,10 @@ static void koto_expander_init(KotoExpander *self) {
|
|||
koto_button_add_click_handler(self->header_expand_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_expander_toggle_content), self);
|
||||
}
|
||||
|
||||
void koto_expander_set_secondary_button(KotoExpander *self, KotoButton *new_button) {
|
||||
void koto_expander_set_secondary_button(
|
||||
KotoExpander * self,
|
||||
KotoButton * new_button
|
||||
) {
|
||||
if (!self->constructed) {
|
||||
return;
|
||||
}
|
||||
|
@ -197,7 +231,10 @@ void koto_expander_set_secondary_button(KotoExpander *self, KotoButton *new_butt
|
|||
g_object_notify_by_pspec(G_OBJECT(self), expander_props[PROP_HEADER_SECONDARY_BUTTON]);
|
||||
}
|
||||
|
||||
void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content) {
|
||||
void koto_expander_set_content(
|
||||
KotoExpander * self,
|
||||
GtkWidget * new_content
|
||||
) {
|
||||
if (!self->constructed) {
|
||||
return;
|
||||
}
|
||||
|
@ -217,30 +254,58 @@ GtkWidget* koto_expander_get_content(KotoExpander *self) {
|
|||
return self->content;
|
||||
}
|
||||
|
||||
void koto_expander_toggle_content(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_expander_toggle_content(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoExpander* self = data;
|
||||
|
||||
|
||||
koto_button_flip(KOTO_BUTTON(self->header_expand_button));
|
||||
GtkRevealer* rev = GTK_REVEALER(self->revealer);
|
||||
|
||||
|
||||
gtk_revealer_set_reveal_child(rev, !gtk_revealer_get_reveal_child(rev)); // Invert our values
|
||||
}
|
||||
|
||||
KotoExpander* koto_expander_new(gchar *primary_icon_name, gchar *primary_label_text) {
|
||||
return g_object_new(KOTO_TYPE_EXPANDER,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
"icon-name", primary_icon_name,
|
||||
"label", primary_label_text,
|
||||
KotoExpander * koto_expander_new(
|
||||
gchar * primary_icon_name,
|
||||
gchar * primary_label_text
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_EXPANDER,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
"icon-name",
|
||||
primary_icon_name,
|
||||
"label",
|
||||
primary_label_text,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, KotoButton *secondary_button) {
|
||||
return g_object_new(KOTO_TYPE_EXPANDER,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
"icon-name", primary_icon_name,
|
||||
"label", primary_label_text,
|
||||
"secondary-button", secondary_button,
|
||||
KotoExpander * koto_expander_new_with_button(
|
||||
gchar * primary_icon_name,
|
||||
gchar * primary_label_text,
|
||||
KotoButton * secondary_button
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_EXPANDER,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
"icon-name",
|
||||
primary_icon_name,
|
||||
"label",
|
||||
primary_label_text,
|
||||
"secondary-button",
|
||||
secondary_button,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,12 +27,40 @@ G_DECLARE_FINAL_TYPE (KotoExpander, koto_expander, KOTO, EXPANDER, GtkBox)
|
|||
#define KOTO_IS_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_EXPANDER))
|
||||
|
||||
KotoExpander * koto_expander_new(gchar * primary_icon_name, gchar * primary_label_text);
|
||||
KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, KotoButton *secondary_button);
|
||||
KotoExpander * koto_expander_new_with_button(
|
||||
gchar * primary_icon_name,
|
||||
gchar * primary_label_text,
|
||||
KotoButton * secondary_button
|
||||
);
|
||||
|
||||
GtkWidget * koto_expander_get_content(KotoExpander * self);
|
||||
void koto_expander_set_icon_name(KotoExpander *self, const gchar *in);
|
||||
void koto_expander_set_label(KotoExpander *self, const gchar *label);
|
||||
void koto_expander_set_secondary_button(KotoExpander *self, KotoButton *new_button);
|
||||
void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content);
|
||||
void koto_expander_toggle_content(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
|
||||
void koto_expander_set_icon_name(
|
||||
KotoExpander * self,
|
||||
const gchar* in
|
||||
);
|
||||
|
||||
void koto_expander_set_label(
|
||||
KotoExpander * self,
|
||||
const gchar * label
|
||||
);
|
||||
|
||||
void koto_expander_set_secondary_button(
|
||||
KotoExpander * self,
|
||||
KotoButton * new_button
|
||||
);
|
||||
|
||||
void koto_expander_set_content(
|
||||
KotoExpander * self,
|
||||
GtkWidget * new_content
|
||||
);
|
||||
|
||||
void koto_expander_toggle_content(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -90,6 +90,7 @@ static void koto_nav_init(KotoNav *self) {
|
|||
|
||||
KotoButton * h_button = koto_button_new_with_icon("Home", "user-home-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||
|
||||
|
||||
if (h_button != NULL) {
|
||||
self->home_button = h_button;
|
||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->home_button));
|
||||
|
@ -104,10 +105,13 @@ static void koto_nav_init(KotoNav *self) {
|
|||
void koto_nav_create_audiobooks_section(KotoNav * self) {
|
||||
KotoExpander * a_expander = koto_expander_new("ephy-bookmarks-symbolic", "Audiobooks");
|
||||
|
||||
|
||||
self->audiobook_expander = a_expander;
|
||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->audiobook_expander));
|
||||
|
||||
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
|
||||
koto_expander_set_content(a_expander, new_content);
|
||||
|
||||
self->audiobooks_local = koto_button_new_plain("Local Library");
|
||||
|
@ -121,11 +125,14 @@ void koto_nav_create_audiobooks_section(KotoNav *self) {
|
|||
|
||||
void koto_nav_create_music_section(KotoNav * self) {
|
||||
KotoExpander * m_expander = koto_expander_new("emblem-music-symbolic", "Music");
|
||||
|
||||
|
||||
self->music_expander = m_expander;
|
||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->music_expander));
|
||||
|
||||
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
|
||||
self->music_local = koto_button_new_plain("Local Library");
|
||||
self->music_radio = koto_button_new_plain("Radio");
|
||||
|
||||
|
@ -140,12 +147,14 @@ void koto_nav_create_playlist_section(KotoNav *self) {
|
|||
KotoButton * playlist_add_button = koto_button_new_with_icon("", "list-add-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||
KotoExpander * pl_expander = koto_expander_new_with_button("playlist-symbolic", "Playlists", playlist_add_button);
|
||||
|
||||
|
||||
self->playlists_expander = pl_expander;
|
||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->playlists_expander));
|
||||
|
||||
// TODO: Turn into ListBox to sort playlists
|
||||
GtkWidget * playlist_list = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
|
||||
koto_expander_set_content(self->playlists_expander, playlist_list);
|
||||
koto_button_add_click_handler(playlist_add_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_nav_handle_playlist_add_click), NULL);
|
||||
|
||||
|
@ -155,11 +164,14 @@ void koto_nav_create_playlist_section(KotoNav *self) {
|
|||
|
||||
void koto_nav_create_podcasts_section(KotoNav * self) {
|
||||
KotoExpander * p_expander = koto_expander_new("microphone-sensitivity-high-symbolic", "Podcasts");
|
||||
|
||||
|
||||
self->podcast_expander = p_expander;
|
||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->podcast_expander));
|
||||
|
||||
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
|
||||
self->podcasts_local = koto_button_new_plain("Library");
|
||||
self->podcasts_discover = koto_button_new_plain("Find New Podcasts");
|
||||
|
||||
|
@ -169,35 +181,73 @@ void koto_nav_create_podcasts_section(KotoNav *self) {
|
|||
koto_expander_set_content(p_expander, new_content);
|
||||
}
|
||||
|
||||
void koto_nav_handle_playlist_add_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) user_data;
|
||||
void koto_nav_handle_playlist_add_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) user_data;
|
||||
koto_window_show_dialog(main_window, "create-modify-playlist");
|
||||
}
|
||||
|
||||
void koto_nav_handle_local_music_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) user_data;
|
||||
void koto_nav_handle_local_music_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) user_data;
|
||||
koto_window_go_to_page(main_window, "music.local"); // Go to the playlist page
|
||||
}
|
||||
|
||||
void koto_nav_handle_playlist_button_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_nav_handle_playlist_button_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
gchar * playlist_uuid = user_data;
|
||||
|
||||
|
||||
koto_window_go_to_page(main_window, playlist_uuid); // Go to the playlist page
|
||||
}
|
||||
|
||||
void koto_nav_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data) {
|
||||
void koto_nav_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) carto;
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoNav * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_NAV(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID for a playlist
|
||||
|
||||
|
||||
if (g_hash_table_contains(self->playlist_buttons, playlist_uuid)) { // Already added button
|
||||
g_free(playlist_uuid);
|
||||
return;
|
||||
|
@ -207,6 +257,7 @@ void koto_nav_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playl
|
|||
gchar * playlist_art_path = koto_playlist_get_artwork(playlist); // Get any file path for it
|
||||
KotoButton * playlist_button = NULL;
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(playlist_art_path)) { // Have a file associated
|
||||
playlist_button = koto_button_new_with_file(playlist_name, playlist_art_path, KOTO_BUTTON_PIXBUF_SIZE_NORMAL);
|
||||
} else { // No file associated
|
||||
|
@ -229,12 +280,17 @@ void koto_nav_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playl
|
|||
}
|
||||
}
|
||||
|
||||
void koto_nav_handle_playlist_modified(KotoPlaylist *playlist, gpointer user_data) {
|
||||
void koto_nav_handle_playlist_modified(
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoNav * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_NAV(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -243,36 +299,49 @@ void koto_nav_handle_playlist_modified(KotoPlaylist *playlist, gpointer user_dat
|
|||
|
||||
KotoButton * playlist_button = g_hash_table_lookup(self->playlist_buttons, playlist_uuid);
|
||||
|
||||
|
||||
if (!KOTO_IS_BUTTON(playlist_button)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(artwork)) { // Have valid artwork
|
||||
koto_button_set_file_path(playlist_button, artwork); // Update the artwork path
|
||||
}
|
||||
|
||||
gchar * name = koto_playlist_get_name(playlist); // Get the name
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(name)) { // Have valid name
|
||||
koto_button_set_text(playlist_button, name); // Update the button text
|
||||
}
|
||||
}
|
||||
|
||||
void koto_nav_handle_playlist_removed(KotoCartographer *carto, gchar *playlist_uuid, gpointer user_data) {
|
||||
void koto_nav_handle_playlist_removed(
|
||||
KotoCartographer * carto,
|
||||
gchar * playlist_uuid,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) carto;
|
||||
KotoNav * self = user_data;
|
||||
|
||||
|
||||
if (!g_hash_table_contains(self->playlist_buttons, playlist_uuid)) { // Does not contain this
|
||||
return;
|
||||
}
|
||||
|
||||
KotoButton * playlist_btn = g_hash_table_lookup(self->playlist_buttons, playlist_uuid); // Get the playlist button
|
||||
|
||||
|
||||
if (!KOTO_IS_BUTTON(playlist_btn)) { // Not a playlist button
|
||||
return;
|
||||
}
|
||||
|
||||
GtkBox * playlist_expander_content = GTK_BOX(koto_expander_get_content(self->playlists_expander));
|
||||
|
||||
|
||||
gtk_box_remove(playlist_expander_content, GTK_WIDGET(playlist_btn)); // Remove the button
|
||||
g_hash_table_remove(self->playlist_buttons, playlist_uuid); // Remove from the playlist buttons hash table
|
||||
}
|
||||
|
|
|
@ -28,14 +28,45 @@ G_DECLARE_FINAL_TYPE (KotoNav, koto_nav, KOTO, NAV, GObject)
|
|||
|
||||
KotoNav* koto_nav_new(void);
|
||||
void koto_nav_create_audiobooks_section(KotoNav * self);
|
||||
|
||||
void koto_nav_create_music_section(KotoNav * self);
|
||||
|
||||
void koto_nav_create_playlist_section(KotoNav * self);
|
||||
|
||||
void koto_nav_create_podcasts_section(KotoNav * self);
|
||||
void koto_nav_handle_playlist_add_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_nav_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data);
|
||||
void koto_nav_handle_playlist_modified(KotoPlaylist *playlist, gpointer user_data);
|
||||
void koto_nav_handle_playlist_removed(KotoCartographer *carto, gchar *playlist_uuid, gpointer user_data);
|
||||
void koto_nav_handle_local_music_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
|
||||
void koto_nav_handle_playlist_add_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_nav_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_nav_handle_playlist_modified(
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_nav_handle_playlist_removed(
|
||||
KotoCartographer * carto,
|
||||
gchar * playlist_uuid,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_nav_handle_local_music_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
GtkWidget * koto_nav_get_nav(KotoNav * self);
|
||||
|
||||
|
|
|
@ -76,6 +76,8 @@ static void koto_playerbar_constructed(GObject *obj);
|
|||
|
||||
static void koto_playerbar_class_init(KotoPlayerBarClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
|
||||
gobject_class->constructed = koto_playerbar_constructed;
|
||||
|
@ -83,6 +85,8 @@ static void koto_playerbar_class_init(KotoPlayerBarClass *c) {
|
|||
|
||||
static void koto_playerbar_constructed(GObject * obj) {
|
||||
KotoPlayerBar * self = KOTO_PLAYERBAR(obj);
|
||||
|
||||
|
||||
self->main = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_widget_add_css_class(self->main, "player-bar");
|
||||
|
||||
|
@ -94,6 +98,8 @@ static void koto_playerbar_constructed(GObject *obj) {
|
|||
gtk_range_set_round_digits(GTK_RANGE(self->progress_bar), 1);
|
||||
|
||||
GtkGesture * press_controller = gtk_gesture_click_new(); // Create a new GtkGestureLongPress
|
||||
|
||||
|
||||
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(press_controller), 1); // Set to left click
|
||||
|
||||
g_signal_connect(press_controller, "begin", G_CALLBACK(koto_playerbar_handle_progressbar_gesture_begin), self);
|
||||
|
@ -154,6 +160,7 @@ void koto_playerbar_create_playback_details(KotoPlayerBar* bar) {
|
|||
|
||||
GtkIconTheme * default_icon_theme = gtk_icon_theme_get_for_display(gdk_display_get_default()); // Get the icon theme for this display
|
||||
|
||||
|
||||
if (default_icon_theme != NULL) {
|
||||
gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(bar->main));
|
||||
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);
|
||||
|
@ -245,25 +252,49 @@ void koto_playerbar_create_secondary_controls(KotoPlayerBar* bar) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
koto_playback_engine_backwards(playback_engine);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
koto_playback_engine_forwards(playback_engine);
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_is_playing(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_is_playing(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -271,13 +302,17 @@ void koto_playerbar_handle_is_playing(KotoPlaybackEngine *engine, gpointer user_
|
|||
koto_button_show_image(bar->play_pause_button, TRUE); // Set to TRUE to show pause as the next action
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_is_paused(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -285,10 +320,20 @@ void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_d
|
|||
koto_button_show_image(bar->play_pause_button, FALSE); // Set to FALSE to show play as the next action
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(self)) { // Not a playerbar
|
||||
return;
|
||||
}
|
||||
|
@ -297,10 +342,16 @@ void koto_playerbar_handle_playlist_button_clicked(GtkGestureClick *gesture, int
|
|||
gtk_widget_show(GTK_WIDGET(koto_add_remove_track_popup));
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
||||
(void) gesture; (void) seq;
|
||||
void koto_playerbar_handle_progressbar_gesture_begin(
|
||||
GtkGesture * gesture,
|
||||
GdkEventSequence * seq,
|
||||
gpointer data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) seq;
|
||||
KotoPlayerBar * bar = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -308,20 +359,36 @@ void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEve
|
|||
bar->is_progressbar_seeking = TRUE;
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_progressbar_gesture_end(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
||||
(void) gesture; (void) seq;
|
||||
void koto_playerbar_handle_progressbar_gesture_end(
|
||||
GtkGesture * gesture,
|
||||
GdkEventSequence * seq,
|
||||
gpointer data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) seq;
|
||||
KotoPlayerBar * bar = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
bar->is_progressbar_seeking = FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -329,9 +396,13 @@ void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_p
|
|||
bar->is_progressbar_seeking = TRUE;
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpointer data) {
|
||||
void koto_playerbar_handle_progressbar_value_changed(
|
||||
GtkRange * progress_bar,
|
||||
gpointer data
|
||||
) {
|
||||
KotoPlayerBar * bar = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -342,16 +413,21 @@ void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpo
|
|||
|
||||
int desired_position = (int) gtk_range_get_value(progress_bar);
|
||||
|
||||
|
||||
koto_playback_engine_set_position(playback_engine, desired_position); // Update our position
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_tick_duration(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -360,13 +436,17 @@ void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer us
|
|||
}
|
||||
|
||||
|
||||
void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_tick_track(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -376,13 +456,17 @@ void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_track_repeat(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -394,13 +478,17 @@ void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer use
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_handle_track_shuffle(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
@ -412,8 +500,13 @@ void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer us
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data) {
|
||||
(void) button; (void) user_data;
|
||||
void koto_playerbar_handle_volume_button_change(
|
||||
GtkScaleButton * button,
|
||||
double value,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) button;
|
||||
(void) user_data;
|
||||
koto_playback_engine_set_volume(playback_engine, value);
|
||||
}
|
||||
|
||||
|
@ -422,7 +515,10 @@ void koto_playerbar_reset_progressbar(KotoPlayerBar* bar) {
|
|||
gtk_range_set_value(GTK_RANGE(bar->progress_bar), 0); // Set value to 0
|
||||
}
|
||||
|
||||
void koto_playerbar_set_progressbar_duration(KotoPlayerBar* bar, gint64 duration) {
|
||||
void koto_playerbar_set_progressbar_duration(
|
||||
KotoPlayerBar* bar,
|
||||
gint64 duration
|
||||
) {
|
||||
if (duration <= 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -433,40 +529,78 @@ void koto_playerbar_set_progressbar_duration(KotoPlayerBar* bar, gint64 duration
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playerbar_set_progressbar_value(KotoPlayerBar* bar, double progress) {
|
||||
void koto_playerbar_set_progressbar_value(
|
||||
KotoPlayerBar* bar,
|
||||
double progress
|
||||
) {
|
||||
gtk_range_set_value(GTK_RANGE(bar->progress_bar), progress);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
koto_playback_engine_toggle(playback_engine);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
koto_playback_engine_toggle_track_shuffle(playback_engine); // Call our playback engine's toggle track shuffle function
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
koto_playback_engine_toggle_track_repeat(playback_engine); // Call our playback engine's toggle track repeat function
|
||||
}
|
||||
|
||||
void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_data) {
|
||||
void koto_playerbar_update_track_info(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlayerBar * bar = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoIndexedTrack * current_track = koto_playback_engine_get_current_track(playback_engine); // Get the current track from the playback engine
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(current_track)) {
|
||||
return;
|
||||
}
|
||||
|
@ -475,11 +609,13 @@ void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_
|
|||
gchar * artist_uuid = NULL;
|
||||
gchar * album_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(current_track, "parsed-name", &track_name, "artist-uuid", &artist_uuid, "album-uuid", &album_uuid, NULL);
|
||||
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid);
|
||||
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||
|
||||
|
||||
g_free(artist_uuid);
|
||||
g_free(album_uuid);
|
||||
|
||||
|
|
|
@ -28,30 +28,142 @@ G_DECLARE_FINAL_TYPE (KotoPlayerBar, koto_playerbar, KOTO, PLAYERBAR, GObject)
|
|||
|
||||
KotoPlayerBar * koto_playerbar_new(void);
|
||||
GtkWidget * koto_playerbar_get_main(KotoPlayerBar* bar);
|
||||
|
||||
void koto_playerbar_create_playback_details(KotoPlayerBar* bar);
|
||||
|
||||
void koto_playerbar_create_primary_controls(KotoPlayerBar* bar);
|
||||
|
||||
void koto_playerbar_create_secondary_controls(KotoPlayerBar* bar);
|
||||
void koto_playerbar_go_backwards(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_go_forwards(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_handle_is_playing(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_playlist_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_handle_progressbar_scroll_begin(GtkEventControllerScroll *controller, gpointer data);
|
||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data);
|
||||
void koto_playerbar_handle_progressbar_gesture_end(GtkGesture *gesture, GdkEventSequence *seq, gpointer data);
|
||||
void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpointer data);
|
||||
void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data);
|
||||
|
||||
void koto_playerbar_go_backwards(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_go_forwards(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_is_playing(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_is_paused(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_playlist_button_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_progressbar_scroll_begin(
|
||||
GtkEventControllerScroll * controller,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_progressbar_gesture_begin(
|
||||
GtkGesture * gesture,
|
||||
GdkEventSequence * seq,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_progressbar_gesture_end(
|
||||
GtkGesture * gesture,
|
||||
GdkEventSequence * seq,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_progressbar_pressed(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_progressbar_value_changed(
|
||||
GtkRange * progress_bar,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_tick_duration(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_tick_track(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_track_repeat(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_track_shuffle(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_handle_volume_button_change(
|
||||
GtkScaleButton * button,
|
||||
double value,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playerbar_reset_progressbar(KotoPlayerBar* bar);
|
||||
void koto_playerbar_set_progressbar_duration(KotoPlayerBar* bar, gint64 duration);
|
||||
void koto_playerbar_set_progressbar_value(KotoPlayerBar* bar, gdouble progress);
|
||||
void koto_playerbar_toggle_play_pause(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_toggle_playlist_shuffle(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_toggle_track_repeat(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_data);
|
||||
|
||||
void koto_playerbar_set_progressbar_duration(
|
||||
KotoPlayerBar* bar,
|
||||
gint64 duration
|
||||
);
|
||||
|
||||
void koto_playerbar_set_progressbar_value(
|
||||
KotoPlayerBar* bar,
|
||||
gdouble progress
|
||||
);
|
||||
|
||||
void koto_playerbar_toggle_play_pause(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_toggle_playlist_shuffle(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_toggle_track_repeat(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playerbar_update_track_info(
|
||||
KotoPlaybackEngine * engine,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -40,15 +40,30 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoTrackItem, koto_track_item, GTK_TYPE_BOX);
|
||||
|
||||
static void koto_track_item_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_track_item_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_track_item_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_track_item_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_track_item_class_init(KotoTrackItemClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_track_item_set_property;
|
||||
gobject_class->get_property = koto_track_item_get_property;
|
||||
|
@ -64,9 +79,15 @@ static void koto_track_item_class_init(KotoTrackItemClass *c) {
|
|||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
static void koto_track_item_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_track_item_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoTrackItem * self = KOTO_TRACK_ITEM(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TRACK:
|
||||
g_value_set_object(val, self->track);
|
||||
|
@ -77,9 +98,15 @@ static void koto_track_item_get_property(GObject *obj, guint prop_id, GValue *va
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_track_item_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_track_item_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoTrackItem * self = KOTO_TRACK_ITEM(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TRACK:
|
||||
koto_track_item_set_track(self, (KotoIndexedTrack*) g_value_get_object(val));
|
||||
|
@ -105,19 +132,25 @@ KotoIndexedTrack* koto_track_item_get_track(KotoTrackItem *self) {
|
|||
return self->track;
|
||||
}
|
||||
|
||||
void koto_track_item_set_track(KotoTrackItem *self, KotoIndexedTrack *track) {
|
||||
void koto_track_item_set_track(
|
||||
KotoTrackItem * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
if (track == NULL) { // Not a track
|
||||
return;
|
||||
}
|
||||
|
||||
self->track = track;
|
||||
gchar * track_name;
|
||||
|
||||
|
||||
g_object_get(self->track, "parsed-name", &track_name, NULL);
|
||||
gtk_label_set_text(GTK_LABEL(self->track_label), track_name); // Update the text
|
||||
}
|
||||
|
||||
KotoTrackItem * koto_track_item_new(KotoIndexedTrack * track) {
|
||||
return g_object_new(KOTO_TYPE_TRACK_ITEM,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_TRACK_ITEM,
|
||||
"track",
|
||||
track,
|
||||
NULL
|
||||
|
|
|
@ -28,8 +28,19 @@ G_BEGIN_DECLS
|
|||
G_DECLARE_FINAL_TYPE(KotoTrackItem, koto_track_item, KOTO, TRACK_ITEM, GtkBox)
|
||||
|
||||
KotoTrackItem* koto_track_item_new(KotoIndexedTrack * track);
|
||||
void koto_track_item_handle_add_to_playlist_button_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_track_item_handle_add_to_playlist_button_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
KotoIndexedTrack * koto_track_item_get_track(KotoTrackItem * self);
|
||||
void koto_track_item_set_track(KotoTrackItem *self, KotoIndexedTrack *track);
|
||||
|
||||
void koto_track_item_set_track(
|
||||
KotoTrackItem * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -30,6 +30,8 @@ GtkFileChooserNative* koto_utils_create_image_file_chooser(gchar *file_chooser_l
|
|||
);
|
||||
|
||||
GtkFileFilter * image_filter = gtk_file_filter_new(); // Create our file filter
|
||||
|
||||
|
||||
gtk_file_filter_add_mime_type(image_filter, "image/*"); // Only allow for images
|
||||
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(chooser), image_filter); // Only allow picking images
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), FALSE);
|
||||
|
@ -37,9 +39,15 @@ GtkFileChooserNative* koto_utils_create_image_file_chooser(gchar *file_chooser_l
|
|||
return chooser;
|
||||
}
|
||||
|
||||
GtkWidget* koto_utils_create_image_from_filepath(gchar *filepath, gchar *fallback_icon, guint width, guint height) {
|
||||
GtkWidget * koto_utils_create_image_from_filepath(
|
||||
gchar * filepath,
|
||||
gchar * fallback_icon,
|
||||
guint width,
|
||||
guint height
|
||||
) {
|
||||
GtkWidget* image = NULL;
|
||||
|
||||
|
||||
if ((filepath != NULL) && (strcmp(filepath, "") != 0)) { // If we have a filepath
|
||||
if (g_file_test(filepath, G_FILE_TEST_EXISTS)) { // File exists
|
||||
image = gtk_image_new_from_file(filepath); // Load from the filepath
|
||||
|
@ -60,9 +68,12 @@ GtkWidget* koto_utils_create_image_from_filepath(gchar *filepath, gchar *fallbac
|
|||
gchar * koto_utils_get_filename_without_extension(gchar * filename) {
|
||||
gchar * trimmed_file_name = g_strdup(filename);
|
||||
gchar ** split = g_strsplit(filename, ".", -1); // Split every time we see .
|
||||
|
||||
|
||||
g_free(trimmed_file_name);
|
||||
guint len_of_extension_split = g_strv_length(split);
|
||||
|
||||
|
||||
if (len_of_extension_split == 2) { // Only have two elements
|
||||
trimmed_file_name = g_strdup(split[0]); // Get the first element
|
||||
} else {
|
||||
|
@ -83,6 +94,8 @@ gchar* koto_utils_get_filename_without_extension(gchar *filename) {
|
|||
}
|
||||
|
||||
gchar * stripped_file_name = g_strstrip(g_strdup(trimmed_file_name)); // Strip leading and trailing whitespace
|
||||
|
||||
|
||||
g_free(trimmed_file_name);
|
||||
return stripped_file_name;
|
||||
}
|
||||
|
@ -91,14 +104,22 @@ gboolean koto_utils_is_string_valid(gchar *str) {
|
|||
return ((str != NULL) && (g_strcmp0(str, "") != 0));
|
||||
}
|
||||
|
||||
void koto_utils_push_queue_element_to_store(gpointer data, gpointer user_data) {
|
||||
void koto_utils_push_queue_element_to_store(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
) {
|
||||
g_list_store_append(G_LIST_STORE(user_data), data);
|
||||
}
|
||||
|
||||
gchar* koto_utils_replace_string_all(gchar *str, gchar *find, gchar *repl) {
|
||||
gchar * koto_utils_replace_string_all(
|
||||
gchar * str,
|
||||
gchar * find,
|
||||
gchar * repl
|
||||
) {
|
||||
gchar * cleaned_string = "";
|
||||
gchar ** split = g_strsplit(str, find, -1); // Split on find
|
||||
|
||||
|
||||
for (guint i = 0; i < g_strv_length(split); i++) { // For each split
|
||||
cleaned_string = g_strjoin(repl, cleaned_string, split[i], NULL); // Join the strings with our replace string
|
||||
}
|
||||
|
@ -110,6 +131,7 @@ gchar* koto_utils_replace_string_all(gchar *str, gchar *find, gchar *repl) {
|
|||
gchar * koto_utils_unquote_string(gchar * s) {
|
||||
gchar * new_s = NULL;
|
||||
|
||||
|
||||
if (g_str_has_prefix(s, "'") && g_str_has_suffix(s, "'")) { // Begins and ends with '
|
||||
new_s = g_utf8_substring(s, 1, g_utf8_strlen(s, -1) - 1); // Start at 1 and end at n-1
|
||||
} else {
|
||||
|
@ -117,6 +139,8 @@ gchar* koto_utils_unquote_string(gchar *s) {
|
|||
}
|
||||
|
||||
gchar ** split_on_double_single = g_strsplit(new_s, "''", -1); // Split on instances of ''
|
||||
|
||||
|
||||
new_s = g_strjoinv("'", split_on_double_single); // Rejoin as '
|
||||
g_strfreev(split_on_double_single); // Free our array
|
||||
|
||||
|
|
|
@ -22,11 +22,29 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
GtkFileChooserNative * koto_utils_create_image_file_chooser(gchar * file_chooser_label);
|
||||
GtkWidget* koto_utils_create_image_from_filepath(gchar *filepath, gchar *fallback_icon, guint width, guint height);
|
||||
|
||||
GtkWidget * koto_utils_create_image_from_filepath(
|
||||
gchar * filepath,
|
||||
gchar * fallback_icon,
|
||||
guint width,
|
||||
guint height
|
||||
);
|
||||
|
||||
gchar * koto_utils_get_filename_without_extension(gchar * filename);
|
||||
|
||||
gboolean koto_utils_is_string_valid(gchar * str);
|
||||
void koto_utils_push_queue_element_to_store(gpointer data, gpointer user_data);
|
||||
gchar *koto_utils_replace_string_all(gchar *str, gchar *find, gchar *repl);
|
||||
|
||||
void koto_utils_push_queue_element_to_store(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
gchar * koto_utils_replace_string_all(
|
||||
gchar * str,
|
||||
gchar * find,
|
||||
gchar * repl
|
||||
);
|
||||
|
||||
gchar * koto_utils_unquote_string(gchar * s);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -70,6 +70,8 @@ static void koto_window_init (KotoWindow *self) {
|
|||
playback_engine = koto_playback_engine_new();
|
||||
|
||||
GtkCssProvider* provider = gtk_css_provider_new();
|
||||
|
||||
|
||||
gtk_css_provider_load_from_resource(provider, "/com/github/joshstrobl/koto/style.css");
|
||||
gtk_style_context_add_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
||||
|
@ -141,15 +143,26 @@ static void koto_window_init (KotoWindow *self) {
|
|||
g_thread_new("load-library", (void*) load_library, self);
|
||||
}
|
||||
|
||||
void koto_window_add_page(KotoWindow *self, gchar *page_name, GtkWidget *page) {
|
||||
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) {
|
||||
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 koto_window_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) carto;
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
|
@ -160,6 +173,8 @@ void koto_window_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *pl
|
|||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -167,15 +182,22 @@ 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) {
|
||||
void koto_window_remove_page(
|
||||
KotoWindow * self,
|
||||
gchar * page_name
|
||||
) {
|
||||
GtkWidget * page = gtk_stack_get_child_by_name(GTK_STACK(self->pages), page_name);
|
||||
|
||||
|
||||
if (GTK_IS_WIDGET(page)) {
|
||||
gtk_stack_remove(GTK_STACK(self->pages), page);
|
||||
}
|
||||
}
|
||||
|
||||
void koto_window_show_dialog(KotoWindow *self, gchar *dialog_name) {
|
||||
void koto_window_show_dialog(
|
||||
KotoWindow * self,
|
||||
gchar * dialog_name
|
||||
) {
|
||||
koto_dialog_container_show_dialog(self->dialogs, dialog_name);
|
||||
}
|
||||
|
||||
|
@ -202,6 +224,7 @@ void create_new_headerbar(KotoWindow *self) {
|
|||
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;
|
||||
music_local_page = koto_page_music_local_new();
|
||||
|
@ -219,17 +242,23 @@ void load_library(KotoWindow *self) {
|
|||
void set_optimal_default_window_size(KotoWindow * self) {
|
||||
GdkDisplay * default_display = gdk_display_get_default();
|
||||
|
||||
|
||||
if (!GDK_IS_X11_DISPLAY(default_display)) { // Not an X11 display
|
||||
return;
|
||||
}
|
||||
|
||||
GdkMonitor * default_monitor = gdk_x11_display_get_primary_monitor(GDK_X11_DISPLAY(default_display)); // Get primary monitor for the X11
|
||||
|
||||
|
||||
if (!GDK_IS_X11_MONITOR(default_monitor)) { // Not an X11 Monitor
|
||||
return;
|
||||
}
|
||||
|
||||
GdkRectangle workarea = {0};
|
||||
GdkRectangle workarea = {
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
gdk_monitor_get_geometry(default_monitor, &workarea);
|
||||
|
||||
if (workarea.width <= 1280) { // Honestly how do you even get anything done?
|
||||
|
|
|
@ -27,16 +27,41 @@ G_BEGIN_DECLS
|
|||
|
||||
G_DECLARE_FINAL_TYPE(KotoWindow, koto_window, KOTO, WINDOW, GtkApplicationWindow)
|
||||
|
||||
void koto_window_add_page(KotoWindow *self, gchar *page_name, GtkWidget *page);
|
||||
void koto_window_go_to_page(KotoWindow *self, gchar *page_name);
|
||||
void koto_window_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data);
|
||||
void koto_window_add_page(
|
||||
KotoWindow * self,
|
||||
gchar * page_name,
|
||||
GtkWidget * page
|
||||
);
|
||||
|
||||
void koto_window_go_to_page(
|
||||
KotoWindow * self,
|
||||
gchar * page_name
|
||||
);
|
||||
|
||||
void koto_window_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_window_hide_dialogs(KotoWindow * self);
|
||||
void koto_window_remove_page(KotoWindow *self, gchar *page_name);
|
||||
void koto_window_show_dialog(KotoWindow *self, gchar *dialog_name);
|
||||
|
||||
void koto_window_remove_page(
|
||||
KotoWindow * self,
|
||||
gchar * page_name
|
||||
);
|
||||
|
||||
void koto_window_show_dialog(
|
||||
KotoWindow * self,
|
||||
gchar * dialog_name
|
||||
);
|
||||
|
||||
void create_new_headerbar(KotoWindow * self);
|
||||
|
||||
void handle_album_added();
|
||||
|
||||
void load_library(KotoWindow * self);
|
||||
|
||||
void set_optimal_default_window_size(KotoWindow * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -58,9 +58,13 @@ static void on_shutdown(GtkApplication *app) {
|
|||
g_dbus_node_info_unref(introspection_data);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
int main (
|
||||
int argc,
|
||||
char * argv[]
|
||||
) {
|
||||
int ret;
|
||||
|
||||
|
||||
/* Set up gettext translations */
|
||||
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
||||
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||
|
|
|
@ -52,12 +52,27 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_album_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
static void koto_album_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_album_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_album_view_class_init(KotoAlbumViewClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_album_view_set_property;
|
||||
gobject_class->get_property = koto_album_view_get_property;
|
||||
|
@ -114,6 +129,8 @@ static void koto_album_view_init(KotoAlbumView *self) {
|
|||
gtk_box_prepend(GTK_BOX(self->main), self->album_overlay_container); // Add our album overlay container
|
||||
|
||||
GtkEventController * motion_controller = gtk_event_controller_motion_new(); // Create our new motion event controller to track mouse leave and enter
|
||||
|
||||
|
||||
g_signal_connect(motion_controller, "enter", G_CALLBACK(koto_album_view_show_overlay_controls), self);
|
||||
g_signal_connect(motion_controller, "leave", G_CALLBACK(koto_album_view_hide_overlay_controls), self);
|
||||
gtk_widget_add_controller(self->album_overlay_container, motion_controller);
|
||||
|
@ -125,9 +142,15 @@ GtkWidget* koto_album_view_get_main(KotoAlbumView *self) {
|
|||
return self->main;
|
||||
}
|
||||
|
||||
static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_album_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoAlbumView * self = KOTO_ALBUM_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ALBUM:
|
||||
g_value_set_object(val, self->album);
|
||||
|
@ -138,9 +161,15 @@ static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *va
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_album_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_album_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoAlbumView * self = KOTO_ALBUM_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ALBUM:
|
||||
koto_album_view_set_album(self, (KotoIndexedAlbum*) g_value_get_object(val));
|
||||
|
@ -151,17 +180,29 @@ static void koto_album_view_set_property(GObject *obj, guint prop_id, const GVal
|
|||
}
|
||||
}
|
||||
|
||||
void koto_album_view_add_track_to_listbox(KotoIndexedAlbum *self, KotoIndexedTrack *track) {
|
||||
(void) self; (void) track;
|
||||
void koto_album_view_add_track_to_listbox(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
(void) self;
|
||||
(void) track;
|
||||
}
|
||||
|
||||
void koto_album_view_hide_overlay_controls(GtkEventControllerFocus *controller, gpointer data) {
|
||||
void koto_album_view_hide_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
) {
|
||||
(void) controller;
|
||||
KotoAlbumView* self = data;
|
||||
|
||||
|
||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->album_overlay_revealer), FALSE);
|
||||
}
|
||||
|
||||
void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
||||
void koto_album_view_set_album(
|
||||
KotoAlbumView * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
if (album == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -169,9 +210,13 @@ void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
|||
self->album = album;
|
||||
|
||||
gchar * album_art = koto_indexed_album_get_album_art(self->album); // Get the art for the album
|
||||
|
||||
|
||||
gtk_image_set_from_file(GTK_IMAGE(self->album_overlay_art), album_art);
|
||||
|
||||
gchar * album_name;
|
||||
|
||||
|
||||
g_object_get(album, "name", &album_name, NULL); // Get the album name
|
||||
|
||||
self->album_label = gtk_label_new(album_name);
|
||||
|
@ -181,6 +226,7 @@ void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
|||
GHashTable * discs = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
GList * tracks = koto_indexed_album_get_tracks(album); // Get the tracks for this album
|
||||
|
||||
|
||||
for (guint i = 0; i < g_list_length(tracks); i++) {
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) g_list_nth_data(tracks, i)); // Get the track by its UUID
|
||||
|
||||
|
@ -212,14 +258,22 @@ void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
|||
g_hash_table_destroy(discs);
|
||||
}
|
||||
|
||||
void koto_album_view_show_overlay_controls(GtkEventControllerFocus *controller, gpointer data) {
|
||||
void koto_album_view_show_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
) {
|
||||
(void) controller;
|
||||
KotoAlbumView* self = data;
|
||||
|
||||
|
||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->album_overlay_revealer), TRUE);
|
||||
}
|
||||
|
||||
int koto_album_view_sort_discs(GtkListBoxRow *disc1, GtkListBoxRow *disc2, gpointer user_data) {
|
||||
int koto_album_view_sort_discs(
|
||||
GtkListBoxRow * disc1,
|
||||
GtkListBoxRow * disc2,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
KotoDiscView * disc1_item = KOTO_DISC_VIEW(gtk_list_box_row_get_child(disc1));
|
||||
KotoDiscView * disc2_item = KOTO_DISC_VIEW(gtk_list_box_row_get_child(disc2));
|
||||
|
@ -227,6 +281,7 @@ int koto_album_view_sort_discs(GtkListBoxRow *disc1, GtkListBoxRow *disc2, gpoin
|
|||
guint disc1_num;
|
||||
guint disc2_num;
|
||||
|
||||
|
||||
g_object_get(disc1_item, "disc", &disc1_num, NULL);
|
||||
g_object_get(disc2_item, "disc", &disc2_num, NULL);
|
||||
|
||||
|
@ -239,10 +294,20 @@ int koto_album_view_sort_discs(GtkListBoxRow *disc1, GtkListBoxRow *disc2, gpoin
|
|||
}
|
||||
}
|
||||
|
||||
void koto_album_view_toggle_album_playback(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_album_view_toggle_album_playback(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoAlbumView* self = data;
|
||||
|
||||
|
||||
koto_button_show_image(KOTO_BUTTON(self->play_pause_button), TRUE);
|
||||
koto_indexed_album_set_as_current_playlist(self->album); // Set as the current playlist
|
||||
}
|
||||
|
|
|
@ -29,11 +29,39 @@ G_DECLARE_FINAL_TYPE(KotoAlbumView, koto_album_view, KOTO, ALBUM_VIEW, GObject)
|
|||
|
||||
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum * album);
|
||||
GtkWidget * koto_album_view_get_main(KotoAlbumView * self);
|
||||
void koto_album_view_add_track_to_listbox(KotoIndexedAlbum *self, KotoIndexedTrack *track);
|
||||
void koto_album_view_hide_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
||||
void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album);
|
||||
void koto_album_view_show_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
||||
void koto_album_view_toggle_album_playback(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
int koto_album_view_sort_discs(GtkListBoxRow *track1, GtkListBoxRow *track2, gpointer user_data);
|
||||
|
||||
void koto_album_view_add_track_to_listbox(
|
||||
KotoIndexedAlbum * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
void koto_album_view_hide_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_album_view_set_album(
|
||||
KotoAlbumView * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_album_view_show_overlay_controls(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_album_view_toggle_album_playback(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
int koto_album_view_sort_discs(
|
||||
GtkListBoxRow * track1,
|
||||
GtkListBoxRow * track2,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -47,13 +47,29 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
static void koto_artist_view_constructed(GObject * obj);
|
||||
static void koto_artist_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_artist_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
|
||||
static void koto_artist_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_artist_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_artist_view_class_init(KotoArtistViewClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->constructed = koto_artist_view_constructed;
|
||||
gobject_class->set_property = koto_artist_view_set_property;
|
||||
|
@ -70,9 +86,15 @@ static void koto_artist_view_class_init(KotoArtistViewClass *c) {
|
|||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
static void koto_artist_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_artist_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST:
|
||||
g_value_set_object(val, self->artist);
|
||||
|
@ -83,9 +105,15 @@ static void koto_artist_view_get_property(GObject *obj, guint prop_id, GValue *v
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_artist_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_artist_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST:
|
||||
koto_artist_view_add_artist(self, (KotoIndexedArtist*) g_value_get_object(val));
|
||||
|
@ -103,6 +131,8 @@ static void koto_artist_view_init(KotoArtistView *self) {
|
|||
|
||||
static void koto_artist_view_constructed(GObject * obj) {
|
||||
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||
|
||||
|
||||
self->albums_to_component = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
self->scrolled_window = gtk_scrolled_window_new(); // Create our scrolled window
|
||||
self->content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); // Create our content as a GtkBox
|
||||
|
@ -136,19 +166,29 @@ static void koto_artist_view_constructed(GObject *obj) {
|
|||
self->constructed = TRUE;
|
||||
}
|
||||
|
||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album) {
|
||||
void koto_artist_view_add_album(
|
||||
KotoArtistView * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
gchar * album_art = koto_indexed_album_get_album_art(album); // Get the art for the album
|
||||
|
||||
GtkWidget * art_image = koto_utils_create_image_from_filepath(album_art, "audio-x-generic-symbolic", 220, 220);
|
||||
|
||||
|
||||
gtk_widget_set_halign(art_image, GTK_ALIGN_START); // Align to start
|
||||
gtk_flow_box_insert(GTK_FLOW_BOX(self->favorites_list), art_image, -1); // Append the album art
|
||||
|
||||
KotoAlbumView* album_view = koto_album_view_new(album); // Create our new album view
|
||||
GtkWidget* album_view_main = koto_album_view_get_main(album_view);
|
||||
|
||||
|
||||
gtk_flow_box_insert(GTK_FLOW_BOX(self->album_list), album_view_main, -1); // Append the album view to the album list
|
||||
}
|
||||
|
||||
void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist) {
|
||||
void koto_artist_view_add_artist(
|
||||
KotoArtistView * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
if (artist == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -162,6 +202,8 @@ void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist
|
|||
GList * albums = koto_indexed_artist_get_albums(self->artist); // Get the albums
|
||||
|
||||
GList * a;
|
||||
|
||||
|
||||
for (a = albums; a != NULL; a = a->next) {
|
||||
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, (gchar*) a->data);
|
||||
|
||||
|
|
|
@ -28,8 +28,16 @@ G_BEGIN_DECLS
|
|||
G_DECLARE_FINAL_TYPE(KotoArtistView, koto_artist_view, KOTO, ARTIST_VIEW, GObject)
|
||||
|
||||
KotoArtistView* koto_artist_view_new();
|
||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album);
|
||||
void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist);
|
||||
void koto_artist_view_add_album(
|
||||
KotoArtistView * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_artist_view_add_artist(
|
||||
KotoArtistView * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
GtkWidget * koto_artist_view_get_main(KotoArtistView * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -45,12 +45,27 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static void koto_disc_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_disc_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
static void koto_disc_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_disc_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_disc_view_class_init(KotoDiscViewClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_disc_view_set_property;
|
||||
gobject_class->get_property = koto_disc_view_get_property;
|
||||
|
@ -76,9 +91,15 @@ static void koto_disc_view_class_init(KotoDiscViewClass *c) {
|
|||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
static void koto_disc_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_disc_view_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoDiscView * self = KOTO_DISC_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DISC:
|
||||
g_value_set_uint(val, GPOINTER_TO_UINT(self->disc_number));
|
||||
|
@ -92,9 +113,15 @@ static void koto_disc_view_get_property(GObject *obj, guint prop_id, GValue *val
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_disc_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_disc_view_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoDiscView * self = KOTO_DISC_VIEW(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_DISC:
|
||||
koto_disc_view_set_disc_number(self, g_value_get_uint(val));
|
||||
|
@ -116,6 +143,8 @@ static void koto_disc_view_init(KotoDiscView *self) {
|
|||
gtk_widget_set_size_request(self->header, 16, -1);
|
||||
|
||||
GtkWidget * ico = gtk_image_new_from_icon_name("drive-optical-symbolic");
|
||||
|
||||
|
||||
gtk_box_prepend(GTK_BOX(self->header), ico);
|
||||
|
||||
self->label = gtk_label_new(NULL); // Create an empty label
|
||||
|
@ -137,11 +166,16 @@ static void koto_disc_view_init(KotoDiscView *self) {
|
|||
g_signal_connect(self->list, "selected-rows-changed", G_CALLBACK(koto_disc_view_handle_selected_rows_changed), self);
|
||||
}
|
||||
|
||||
void koto_disc_view_list_tracks(gpointer data, gpointer selfptr) {
|
||||
void koto_disc_view_list_tracks(
|
||||
gpointer data,
|
||||
gpointer selfptr
|
||||
) {
|
||||
KotoDiscView * self = (KotoDiscView*) selfptr;
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) data); // Get the track by its UUID
|
||||
|
||||
guint * disc_number;
|
||||
|
||||
|
||||
g_object_get(track, "cd", &disc_number, NULL); // get the disc number
|
||||
|
||||
if (GPOINTER_TO_UINT(self->disc_number) != GPOINTER_TO_UINT(disc_number)) { // Track does not belong to this CD
|
||||
|
@ -149,20 +183,27 @@ void koto_disc_view_list_tracks(gpointer data, gpointer selfptr) {
|
|||
}
|
||||
|
||||
KotoTrackItem * track_item = koto_track_item_new(track); // Create our new track item
|
||||
|
||||
|
||||
gtk_list_box_append(GTK_LIST_BOX(self->list), GTK_WIDGET(track_item)); // Add to our tracks list box
|
||||
}
|
||||
|
||||
void koto_disc_view_handle_selected_rows_changed(GtkListBox *box, gpointer user_data) {
|
||||
void koto_disc_view_handle_selected_rows_changed(
|
||||
GtkListBox * box,
|
||||
gpointer user_data
|
||||
) {
|
||||
KotoDiscView * self = user_data;
|
||||
|
||||
gchar * album_uuid = koto_indexed_album_get_album_uuid(self->album); // Get the UUID
|
||||
|
||||
|
||||
if (!koto_utils_is_string_valid(album_uuid)) { // Not set
|
||||
return;
|
||||
}
|
||||
|
||||
GList * selected_rows = gtk_list_box_get_selected_rows(box); // Get the selected rows
|
||||
|
||||
|
||||
if (g_list_length(selected_rows) == 0) { // No rows selected
|
||||
koto_action_bar_toggle_reveal(action_bar, FALSE); // Close the action bar
|
||||
return;
|
||||
|
@ -170,6 +211,8 @@ void koto_disc_view_handle_selected_rows_changed(GtkListBox *box, gpointer user_
|
|||
|
||||
GList * selected_tracks = NULL; // Create our list of KotoIndexedTracks
|
||||
GList * cur_selected_rows;
|
||||
|
||||
|
||||
for (cur_selected_rows = selected_rows; cur_selected_rows != NULL; cur_selected_rows = cur_selected_rows->next) { // Iterate over the rows
|
||||
KotoTrackItem * track_item = (KotoTrackItem*) gtk_list_box_row_get_child(cur_selected_rows->data);
|
||||
selected_tracks = g_list_append(selected_tracks, koto_track_item_get_track(track_item)); // Add the KotoIndexedTrack to our list
|
||||
|
@ -181,7 +224,10 @@ void koto_disc_view_handle_selected_rows_changed(GtkListBox *box, gpointer user_
|
|||
koto_action_bar_toggle_reveal(action_bar, TRUE); // Show the action bar
|
||||
}
|
||||
|
||||
void koto_disc_view_set_album(KotoDiscView *self, KotoIndexedAlbum *album) {
|
||||
void koto_disc_view_set_album(
|
||||
KotoDiscView * self,
|
||||
KotoIndexedAlbum * album
|
||||
) {
|
||||
if (album == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -195,7 +241,10 @@ void koto_disc_view_set_album(KotoDiscView *self, KotoIndexedAlbum *album) {
|
|||
g_list_foreach(koto_indexed_album_get_tracks(self->album), koto_disc_view_list_tracks, self);
|
||||
}
|
||||
|
||||
void koto_disc_view_set_disc_number(KotoDiscView *self, guint disc_number) {
|
||||
void koto_disc_view_set_disc_number(
|
||||
KotoDiscView * self,
|
||||
guint disc_number
|
||||
) {
|
||||
if (disc_number == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -203,20 +252,32 @@ void koto_disc_view_set_disc_number(KotoDiscView *self, guint disc_number) {
|
|||
self->disc_number = GUINT_TO_POINTER(disc_number);
|
||||
|
||||
gchar * disc_label = g_strdup_printf("Disc %u", disc_number);
|
||||
|
||||
|
||||
gtk_label_set_text(GTK_LABEL(self->label), disc_label); // Set the label
|
||||
|
||||
g_free(disc_label);
|
||||
}
|
||||
|
||||
void koto_disc_view_set_disc_label_visible(KotoDiscView *self, gboolean visible) {
|
||||
void koto_disc_view_set_disc_label_visible(
|
||||
KotoDiscView * self,
|
||||
gboolean visible
|
||||
) {
|
||||
(visible) ? gtk_widget_show(self->header) : gtk_widget_hide(self->header);
|
||||
}
|
||||
|
||||
KotoDiscView* koto_disc_view_new(KotoIndexedAlbum *album, guint *disc_number) {
|
||||
return g_object_new(KOTO_TYPE_DISC_VIEW,
|
||||
"disc", disc_number,
|
||||
"album", album,
|
||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
||||
KotoDiscView * koto_disc_view_new(
|
||||
KotoIndexedAlbum * album,
|
||||
guint * disc_number
|
||||
) {
|
||||
return g_object_new(
|
||||
KOTO_TYPE_DISC_VIEW,
|
||||
"disc",
|
||||
disc_number,
|
||||
"album",
|
||||
album,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,10 +28,29 @@ G_BEGIN_DECLS
|
|||
G_DECLARE_FINAL_TYPE(KotoDiscView, koto_disc_view, KOTO, DISC_VIEW, GtkBox)
|
||||
|
||||
KotoDiscView* koto_disc_view_new(KotoIndexedAlbum * album, guint * disc);
|
||||
void koto_disc_view_handle_selected_rows_changed(GtkListBox *box, gpointer user_data);
|
||||
void koto_disc_view_list_tracks(gpointer data, gpointer selfptr);
|
||||
void koto_disc_view_set_album(KotoDiscView *self, KotoIndexedAlbum *album);
|
||||
void koto_disc_view_set_disc_label_visible(KotoDiscView *self, gboolean visible);
|
||||
void koto_disc_view_set_disc_number(KotoDiscView *self, guint disc_number);
|
||||
void koto_disc_view_handle_selected_rows_changed(
|
||||
GtkListBox * box,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_disc_view_list_tracks(
|
||||
gpointer data,
|
||||
gpointer selfptr
|
||||
);
|
||||
|
||||
void koto_disc_view_set_album(
|
||||
KotoDiscView * self,
|
||||
KotoIndexedAlbum * album
|
||||
);
|
||||
|
||||
void koto_disc_view_set_disc_label_visible(
|
||||
KotoDiscView * self,
|
||||
gboolean visible
|
||||
);
|
||||
|
||||
void koto_disc_view_set_disc_number(
|
||||
KotoDiscView * self,
|
||||
guint disc_number
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -32,7 +32,9 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct _KotoPageMusicLocal {
|
||||
GtkBox parent_instance;
|
||||
|
@ -53,11 +55,25 @@ G_DEFINE_TYPE(KotoPageMusicLocal, koto_page_music_local, GTK_TYPE_BOX);
|
|||
KotoPageMusicLocal * music_local_page;
|
||||
|
||||
static void koto_page_music_local_constructed(GObject * obj);
|
||||
static void koto_page_music_local_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_page_music_local_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
|
||||
static void koto_page_music_local_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_page_music_local_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_page_music_local_class_init(KotoPageMusicLocalClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->constructed = koto_page_music_local_constructed;
|
||||
gobject_class->set_property = koto_page_music_local_set_property;
|
||||
|
@ -74,9 +90,15 @@ static void koto_page_music_local_class_init(KotoPageMusicLocalClass *c) {
|
|||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
static void koto_page_music_local_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_page_music_local_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LIB:
|
||||
g_value_set_object(val, self->lib);
|
||||
|
@ -87,9 +109,15 @@ static void koto_page_music_local_get_property(GObject *obj, guint prop_id, GVal
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_page_music_local_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_page_music_local_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LIB:
|
||||
koto_page_music_local_set_library(self, (KotoIndexedLibrary*) g_value_get_object(val));
|
||||
|
@ -133,33 +161,52 @@ static void koto_page_music_local_init(KotoPageMusicLocal *self) {
|
|||
static void koto_page_music_local_constructed(GObject * obj) {
|
||||
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
|
||||
|
||||
G_OBJECT_CLASS(koto_page_music_local_parent_class)->constructed(obj);
|
||||
self->constructed = TRUE;
|
||||
}
|
||||
|
||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist) {
|
||||
void koto_page_music_local_add_artist(
|
||||
KotoPageMusicLocal * self,
|
||||
KotoIndexedArtist * artist
|
||||
) {
|
||||
gchar * artist_name;
|
||||
|
||||
|
||||
g_object_get(artist, "name", &artist_name, NULL);
|
||||
KotoButton * artist_button = koto_button_new_plain(artist_name);
|
||||
|
||||
|
||||
gtk_list_box_prepend(GTK_LIST_BOX(self->artist_list), GTK_WIDGET(artist_button));
|
||||
|
||||
KotoArtistView * artist_view = koto_artist_view_new(); // Create our new artist view
|
||||
|
||||
|
||||
koto_artist_view_add_artist(artist_view, artist); // Add the artist
|
||||
gtk_stack_add_named(GTK_STACK(self->stack), koto_artist_view_get_main(artist_view), artist_name);
|
||||
}
|
||||
|
||||
void koto_page_music_local_go_to_artist_by_name(KotoPageMusicLocal *self, gchar *artist_name) {
|
||||
void koto_page_music_local_go_to_artist_by_name(
|
||||
KotoPageMusicLocal * self,
|
||||
gchar * artist_name
|
||||
) {
|
||||
gtk_stack_set_visible_child_name(GTK_STACK(self->stack), artist_name);
|
||||
}
|
||||
|
||||
void koto_page_music_local_go_to_artist_by_uuid(KotoPageMusicLocal *self, gchar *artist_uuid) {
|
||||
void koto_page_music_local_go_to_artist_by_uuid(
|
||||
KotoPageMusicLocal * self,
|
||||
gchar * artist_uuid
|
||||
) {
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid); // Get the artist
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_ARTIST(artist)) { // No artist for this UUID
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * artist_name = NULL;
|
||||
|
||||
|
||||
g_object_get(
|
||||
artist,
|
||||
"name",
|
||||
|
@ -174,17 +221,26 @@ void koto_page_music_local_go_to_artist_by_uuid(KotoPageMusicLocal *self, gchar
|
|||
koto_page_music_local_go_to_artist_by_name(self, artist_name);
|
||||
}
|
||||
|
||||
void koto_page_music_local_handle_artist_click(GtkListBox *box, GtkListBoxRow *row, gpointer data) {
|
||||
void koto_page_music_local_handle_artist_click(
|
||||
GtkListBox * box,
|
||||
GtkListBoxRow * row,
|
||||
gpointer data
|
||||
) {
|
||||
(void) box;
|
||||
KotoPageMusicLocal * self = (KotoPageMusicLocal*) data;
|
||||
KotoButton * btn = KOTO_BUTTON(gtk_list_box_row_get_child(row));
|
||||
|
||||
gchar * artist_name;
|
||||
|
||||
|
||||
g_object_get(btn, "button-text", &artist_name, NULL);
|
||||
koto_page_music_local_go_to_artist_by_name(self, artist_name);
|
||||
}
|
||||
|
||||
void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibrary *lib) {
|
||||
void koto_page_music_local_set_library(
|
||||
KotoPageMusicLocal * self,
|
||||
KotoIndexedLibrary * lib
|
||||
) {
|
||||
if (lib == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -205,6 +261,7 @@ void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibr
|
|||
|
||||
GHashTable * artists = koto_indexed_library_get_artists(self->lib); // Get the artists
|
||||
|
||||
|
||||
g_hash_table_iter_init(&artist_list_iter, artists);
|
||||
while (g_hash_table_iter_next(&artist_list_iter, &artist_key, &artist_data)) { // For each of the music artists
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, (gchar*) artist_data); // Cast our data as a KotoIndexedArtist
|
||||
|
@ -215,7 +272,11 @@ void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibr
|
|||
}
|
||||
}
|
||||
|
||||
int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *artist2, gpointer user_data) {
|
||||
int koto_page_music_local_sort_artists(
|
||||
GtkListBoxRow * artist1,
|
||||
GtkListBoxRow * artist2,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
KotoButton * artist1_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist1));
|
||||
KotoButton * artist2_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist2));
|
||||
|
@ -223,6 +284,7 @@ int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *ar
|
|||
gchar * artist1_text;
|
||||
gchar * artist2_text;
|
||||
|
||||
|
||||
g_object_get(artist1_btn, "button-text", &artist1_text, NULL);
|
||||
g_object_get(artist2_btn, "button-text", &artist2_text, NULL);
|
||||
|
||||
|
@ -230,8 +292,10 @@ int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *ar
|
|||
}
|
||||
|
||||
KotoPageMusicLocal * koto_page_music_local_new() {
|
||||
return g_object_new(KOTO_TYPE_PAGE_MUSIC_LOCAL,
|
||||
"orientation", GTK_ORIENTATION_HORIZONTAL,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_PAGE_MUSIC_LOCAL,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_HORIZONTAL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,36 @@ G_BEGIN_DECLS
|
|||
G_DECLARE_FINAL_TYPE(KotoPageMusicLocal, koto_page_music_local, KOTO, PAGE_MUSIC_LOCAL, GtkBox)
|
||||
|
||||
KotoPageMusicLocal* koto_page_music_local_new();
|
||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist);
|
||||
void koto_page_music_local_handle_artist_click(GtkListBox *box, GtkListBoxRow *row, gpointer data);
|
||||
void koto_page_music_local_go_to_artist_by_name(KotoPageMusicLocal *self, gchar *artist_name);
|
||||
void koto_page_music_local_go_to_artist_by_uuid(KotoPageMusicLocal *self, gchar *artist_uuid);
|
||||
void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibrary *lib);
|
||||
int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *artist2, gpointer user_data);
|
||||
void koto_page_music_local_add_artist(
|
||||
KotoPageMusicLocal * self,
|
||||
KotoIndexedArtist * artist
|
||||
);
|
||||
|
||||
void koto_page_music_local_handle_artist_click(
|
||||
GtkListBox * box,
|
||||
GtkListBoxRow * row,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_page_music_local_go_to_artist_by_name(
|
||||
KotoPageMusicLocal * self,
|
||||
gchar * artist_name
|
||||
);
|
||||
|
||||
void koto_page_music_local_go_to_artist_by_uuid(
|
||||
KotoPageMusicLocal * self,
|
||||
gchar * artist_uuid
|
||||
);
|
||||
|
||||
void koto_page_music_local_set_library(
|
||||
KotoPageMusicLocal * self,
|
||||
KotoIndexedLibrary * lib
|
||||
);
|
||||
|
||||
int koto_page_music_local_sort_artists(
|
||||
GtkListBoxRow * artist1,
|
||||
GtkListBoxRow * artist2,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -39,7 +39,9 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct _KotoPlaylistPage {
|
||||
GObject parent_instance;
|
||||
|
@ -82,11 +84,24 @@ struct _KotoPlaylistPageClass {
|
|||
|
||||
G_DEFINE_TYPE(KotoPlaylistPage, koto_playlist_page, G_TYPE_OBJECT);
|
||||
|
||||
static void koto_playlist_page_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_playlist_page_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_playlist_page_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_playlist_page_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_playlist_page_class_init(KotoPlaylistPageClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->get_property = koto_playlist_page_get_property;
|
||||
gobject_class->set_property = koto_playlist_page_set_property;
|
||||
|
@ -120,9 +135,13 @@ static void koto_playlist_page_init(KotoPlaylistPage *self) {
|
|||
|
||||
self->playlist_image = koto_cover_art_button_new(220, 220, NULL); // Create our Cover Art Button with no art by default
|
||||
KotoButton * cover_art_button = koto_cover_art_button_get_button(self->playlist_image); // Get the button for the cover art
|
||||
|
||||
|
||||
koto_button_add_click_handler(cover_art_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_playlist_page_handle_cover_art_clicked), self);
|
||||
|
||||
GtkWidget * info_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
|
||||
gtk_widget_set_size_request(info_box, -1, 220);
|
||||
gtk_widget_add_css_class(info_box, "playlist-page-header-info");
|
||||
gtk_widget_set_hexpand(info_box, TRUE);
|
||||
|
@ -176,9 +195,15 @@ static void koto_playlist_page_init(KotoPlaylistPage *self) {
|
|||
g_signal_connect(action_bar, "closed", G_CALLBACK(koto_playlist_page_handle_action_bar_closed), self); // Handle closed action bar
|
||||
}
|
||||
|
||||
static void koto_playlist_page_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_playlist_page_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPlaylistPage * self = KOTO_PLAYLIST_PAGE(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PLAYLIST_UUID:
|
||||
g_value_set_string(val, self->uuid);
|
||||
|
@ -189,8 +214,15 @@ static void koto_playlist_page_get_property(GObject *obj, guint prop_id, GValue
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_playlist_page_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_playlist_page_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPlaylistPage * self = KOTO_PLAYLIST_PAGE(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PLAYLIST_UUID:
|
||||
koto_playlist_page_set_playlist_uuid(self, g_strdup(g_value_get_string(val))); // Call to our playlist UUID set function
|
||||
|
@ -201,7 +233,11 @@ static void koto_playlist_page_set_property(GObject *obj, guint prop_id, const G
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem *item, KotoPlaylistPage *self) {
|
||||
void koto_playlist_page_bind_track_item(
|
||||
GtkListItemFactory * factory,
|
||||
GtkListItem * item,
|
||||
KotoPlaylistPage * self
|
||||
) {
|
||||
(void) factory;
|
||||
|
||||
GtkWidget * track_position_label = gtk_widget_get_first_child(gtk_list_item_get_child(item));
|
||||
|
@ -211,6 +247,7 @@ void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem
|
|||
|
||||
KotoIndexedTrack * track = gtk_list_item_get_item(item); // Get the track UUID from our model
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||
return;
|
||||
}
|
||||
|
@ -219,6 +256,7 @@ void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem
|
|||
gchar * album_uuid = NULL;
|
||||
gchar * artist_uuid = NULL;
|
||||
|
||||
|
||||
g_object_get(
|
||||
track,
|
||||
"parsed-name",
|
||||
|
@ -232,17 +270,20 @@ void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem
|
|||
|
||||
guint track_position = koto_playlist_get_position_of_track(self->playlist, track);
|
||||
|
||||
|
||||
gtk_label_set_label(GTK_LABEL(track_position_label), g_strdup_printf("%u", track_position)); // Set the track position
|
||||
gtk_label_set_label(GTK_LABEL(track_name_label), track_name); // Set our track name
|
||||
|
||||
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||
|
||||
|
||||
if (KOTO_IS_INDEXED_ALBUM(album)) {
|
||||
gtk_label_set_label(GTK_LABEL(track_album_label), koto_indexed_album_get_album_name(album)); // Get the name of the album and set it to the label
|
||||
}
|
||||
|
||||
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid);
|
||||
|
||||
|
||||
if (KOTO_IS_INDEXED_ARTIST(artist)) {
|
||||
gtk_label_set_label(GTK_LABEL(track_artist_label), koto_indexed_artist_get_name(artist)); // Get the name of the artist and set it to the label
|
||||
}
|
||||
|
@ -280,10 +321,14 @@ GtkWidget* koto_playlist_page_get_main(KotoPlaylistPage *self) {
|
|||
return self->main;
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_action_bar_closed(KotoActionBar *bar, gpointer data) {
|
||||
void koto_playlist_page_handle_action_bar_closed(
|
||||
KotoActionBar * bar,
|
||||
gpointer data
|
||||
) {
|
||||
(void) bar;
|
||||
KotoPlaylistPage * self = data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(self->playlist)) { // No playlist set
|
||||
return;
|
||||
}
|
||||
|
@ -292,10 +337,20 @@ void koto_playlist_page_handle_action_bar_closed(KotoActionBar *bar, gpointer da
|
|||
gtk_widget_grab_focus(GTK_WIDGET(main_window)); // Focus on the window
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_cover_art_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_cover_art_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(self->playlist)) { // No playlist set
|
||||
return;
|
||||
}
|
||||
|
@ -303,64 +358,127 @@ void koto_playlist_page_handle_cover_art_clicked(GtkGestureClick *gesture, int n
|
|||
koto_current_playlist_set_playlist(current_playlist, self->playlist);
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_edit_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_edit_button_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
koto_create_modify_playlist_dialog_set_playlist_uuid(playlist_create_modify_dialog, koto_playlist_get_uuid(self->playlist));
|
||||
koto_window_show_dialog(main_window, "create-modify-playlist");
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_playlist_modified(KotoPlaylist *playlist, gpointer user_data) {
|
||||
void koto_playlist_page_handle_playlist_modified(
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gchar * artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(artwork)) { // Have valid artwork
|
||||
koto_cover_art_button_set_art_path(self->playlist_image, artwork); // Update our Koto Cover Art Button
|
||||
}
|
||||
|
||||
gchar * name = koto_playlist_get_name(playlist); // Get the name
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(name)) { // Have valid name
|
||||
gtk_label_set_label(GTK_LABEL(self->name_label), name); // Update the name label
|
||||
}
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_track_album_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_track_album_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self->track_album_button), "active");
|
||||
koto_button_hide_image(self->track_num_button); // Go back to hiding the image
|
||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM);
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_track_artist_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_track_artist_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self->track_artist_button), "active");
|
||||
koto_button_hide_image(self->track_num_button); // Go back to hiding the image
|
||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST);
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_track_name_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_track_name_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self->track_title_button), "active");
|
||||
koto_button_hide_image(self->track_num_button); // Go back to hiding the image
|
||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME);
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_track_num_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_playlist_page_handle_track_num_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
KotoPreferredModelType current_model = koto_playlist_get_current_model(self->playlist);
|
||||
|
||||
|
||||
if (current_model == KOTO_PREFERRED_MODEL_TYPE_DEFAULT) { // Set to newest currently
|
||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST); // Sort reversed (oldest)
|
||||
koto_button_show_image(self->track_num_button, TRUE); // Use inverted value (pan-up-symbolic)
|
||||
|
@ -370,10 +488,16 @@ void koto_playlist_page_handle_track_num_clicked(GtkGestureClick *gesture, int n
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint position, guint n_items, gpointer user_data) {
|
||||
void koto_playlist_page_handle_tracks_selected(
|
||||
GtkSelectionModel * model,
|
||||
guint position,
|
||||
guint n_items,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) position;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
if (n_items == 0) { // No items selected
|
||||
koto_action_bar_toggle_reveal(action_bar, FALSE); // Hide the action bar
|
||||
return;
|
||||
|
@ -385,6 +509,8 @@ void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint p
|
|||
GList * selected_tracks_pos = NULL;
|
||||
|
||||
guint first_track_pos;
|
||||
|
||||
|
||||
if (!gtk_bitset_iter_init_first(&iter, selected_items_bitset, &first_track_pos)) { // Failed to get the first item
|
||||
return;
|
||||
}
|
||||
|
@ -392,6 +518,8 @@ void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint p
|
|||
selected_tracks_pos = g_list_append(selected_tracks_pos, GUINT_TO_POINTER(first_track_pos));
|
||||
|
||||
gboolean have_more_items = TRUE;
|
||||
|
||||
|
||||
while (have_more_items) { // While we are able to get selected items
|
||||
guint track_pos;
|
||||
have_more_items = gtk_bitset_iter_next(&iter, &track_pos);
|
||||
|
@ -401,6 +529,8 @@ void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint p
|
|||
}
|
||||
|
||||
GList * cur_pos_list;
|
||||
|
||||
|
||||
for (cur_pos_list = selected_tracks_pos; cur_pos_list != NULL; cur_pos_list = cur_pos_list->next) { // Iterate over every position that we accumulated
|
||||
KotoIndexedTrack * selected_track = g_list_model_get_item(self->model, GPOINTER_TO_UINT(cur_pos_list->data)); // Get the KotoIndexedTrack in the GListModel for this current position
|
||||
selected_tracks = g_list_append(selected_tracks, selected_track); // Add to selected tracks
|
||||
|
@ -410,7 +540,10 @@ void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint p
|
|||
koto_action_bar_toggle_reveal(action_bar, TRUE); // Show the items
|
||||
}
|
||||
|
||||
void koto_playlist_page_set_playlist_uuid(KotoPlaylistPage *self, gchar *playlist_uuid) {
|
||||
void koto_playlist_page_set_playlist_uuid(
|
||||
KotoPlaylistPage * self,
|
||||
gchar * playlist_uuid
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -429,6 +562,8 @@ void koto_playlist_page_set_playlist_uuid(KotoPlaylistPage *self, gchar *playlis
|
|||
|
||||
self->uuid = g_strdup(playlist_uuid); // Duplicate the playlist UUID
|
||||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->uuid);
|
||||
|
||||
|
||||
self->playlist = playlist;
|
||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_DEFAULT); // TODO: Enable this to be changed
|
||||
koto_playlist_page_update_header(self); // Update our header
|
||||
|
@ -436,7 +571,10 @@ void koto_playlist_page_set_playlist_uuid(KotoPlaylistPage *self, gchar *playlis
|
|||
g_signal_connect(playlist, "modified", G_CALLBACK(koto_playlist_page_handle_playlist_modified), self); // Handle playlist modification
|
||||
}
|
||||
|
||||
void koto_playlist_page_set_playlist_model(KotoPlaylistPage *self, KotoPreferredModelType model) {
|
||||
void koto_playlist_page_set_playlist_model(
|
||||
KotoPlaylistPage * self,
|
||||
KotoPreferredModelType model
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -462,18 +600,27 @@ void koto_playlist_page_set_playlist_model(KotoPlaylistPage *self, KotoPreferred
|
|||
gtk_list_view_set_model(GTK_LIST_VIEW(self->track_list_view), self->selection_model); // Set our multi selection model to our provided model
|
||||
}
|
||||
|
||||
void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListItem *item, gpointer user_data) {
|
||||
void koto_playlist_page_setup_track_item(
|
||||
GtkListItemFactory * factory,
|
||||
GtkListItem * item,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) factory;
|
||||
KotoPlaylistPage * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GtkWidget * item_content = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); // Have a horizontal box for our content
|
||||
|
||||
|
||||
gtk_widget_add_css_class(item_content, "track-list-columned-item");
|
||||
|
||||
GtkWidget * track_number = gtk_label_new(NULL); // Our track number
|
||||
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(track_number), 0);
|
||||
gtk_widget_add_css_class(track_number, "track-column-number");
|
||||
gtk_widget_set_halign(track_number, GTK_ALIGN_END);
|
||||
|
@ -483,6 +630,8 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
|||
gtk_size_group_add_widget(self->track_pos_size_group, track_number);
|
||||
|
||||
GtkWidget * track_name = gtk_label_new(NULL); // Our track name
|
||||
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(track_name), 0);
|
||||
gtk_widget_add_css_class(track_name, "track-column-name");
|
||||
gtk_widget_set_halign(track_name, GTK_ALIGN_START);
|
||||
|
@ -492,6 +641,8 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
|||
gtk_size_group_add_widget(self->track_name_size_group, track_name);
|
||||
|
||||
GtkWidget * track_album = gtk_label_new(NULL); // Our track album
|
||||
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(track_album), 0);
|
||||
gtk_widget_add_css_class(track_album, "track-column-album");
|
||||
gtk_widget_set_halign(track_album, GTK_ALIGN_START);
|
||||
|
@ -502,6 +653,8 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
|||
gtk_size_group_add_widget(self->track_album_size_group, track_album);
|
||||
|
||||
GtkWidget * track_artist = gtk_label_new(NULL); // Our track artist
|
||||
|
||||
|
||||
gtk_label_set_xalign(GTK_LABEL(track_artist), 0);
|
||||
gtk_widget_add_css_class(track_artist, "track-column-artist");
|
||||
gtk_widget_set_halign(track_artist, GTK_ALIGN_START);
|
||||
|
@ -524,6 +677,8 @@ void koto_playlist_page_update_header(KotoPlaylistPage *self) {
|
|||
}
|
||||
|
||||
gboolean ephemeral = TRUE;
|
||||
|
||||
|
||||
g_object_get(
|
||||
self->playlist,
|
||||
"ephemeral",
|
||||
|
@ -535,22 +690,28 @@ void koto_playlist_page_update_header(KotoPlaylistPage *self) {
|
|||
|
||||
gtk_label_set_text(GTK_LABEL(self->name_label), koto_playlist_get_name(self->playlist)); // Set the name label to our playlist name
|
||||
guint track_count = koto_playlist_get_length(self->playlist); // Get the number of tracks
|
||||
|
||||
|
||||
gtk_label_set_text(GTK_LABEL(self->tracks_count_label), g_strdup_printf(track_count != 1 ? "%u tracks" : "%u track", track_count)); // Set the text to "N tracks" where N is the number
|
||||
|
||||
gchar * artwork = koto_playlist_get_artwork(self->playlist);
|
||||
|
||||
|
||||
if (koto_utils_is_string_valid(artwork)) { // Have artwork
|
||||
koto_cover_art_button_set_art_path(self->playlist_image, artwork); // Update our artwork
|
||||
}
|
||||
|
||||
KotoPreferredModelType current_model = koto_playlist_get_current_model(self->playlist); // Get the current model
|
||||
|
||||
|
||||
if (current_model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) {
|
||||
koto_button_show_image(self->track_num_button, TRUE); // Immediately use pan-up-symbolic
|
||||
}
|
||||
}
|
||||
|
||||
KotoPlaylistPage * koto_playlist_page_new(gchar * playlist_uuid) {
|
||||
return g_object_new(KOTO_TYPE_PLAYLIST_PAGE,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_PLAYLIST_PAGE,
|
||||
"uuid",
|
||||
playlist_uuid,
|
||||
NULL
|
||||
|
|
|
@ -30,27 +30,118 @@ G_DECLARE_FINAL_TYPE (KotoPlaylistPage, koto_playlist_page, KOTO, PLAYLIST_PAGE,
|
|||
#define KOTO_IS_PLAYLIST_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYLIST_PAGE))
|
||||
|
||||
KotoPlaylistPage * koto_playlist_page_new(gchar * playlist_uuid);
|
||||
void koto_playlist_page_add_track(KotoPlaylistPage* self, const gchar *track_uuid);
|
||||
|
||||
void koto_playlist_page_add_track(
|
||||
KotoPlaylistPage* self,
|
||||
const gchar * track_uuid
|
||||
);
|
||||
|
||||
void koto_playlist_page_create_tracks_header(KotoPlaylistPage * self);
|
||||
void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem *item, KotoPlaylistPage *self);
|
||||
void koto_playlist_page_remove_track(KotoPlaylistPage *self, const gchar *track_uuid);
|
||||
|
||||
void koto_playlist_page_bind_track_item(
|
||||
GtkListItemFactory * factory,
|
||||
GtkListItem * item,
|
||||
KotoPlaylistPage * self
|
||||
);
|
||||
|
||||
void koto_playlist_page_remove_track(
|
||||
KotoPlaylistPage * self,
|
||||
const gchar * track_uuid
|
||||
);
|
||||
|
||||
GtkWidget * koto_playlist_page_get_main(KotoPlaylistPage * self);
|
||||
void koto_playlist_page_handle_action_bar_closed(KotoActionBar *bar, gpointer data);
|
||||
void koto_playlist_page_handle_cover_art_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_edit_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_playlist_modified(KotoPlaylist *playlist, gpointer user_data);
|
||||
void koto_playlist_page_handle_track_album_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_track_artist_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_track_name_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_track_num_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint position, guint n_items, gpointer user_data);
|
||||
|
||||
void koto_playlist_page_handle_action_bar_closed(
|
||||
KotoActionBar * bar,
|
||||
gpointer data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_cover_art_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_edit_button_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_playlist_modified(
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_track_album_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_track_artist_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_track_name_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_track_num_clicked(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_handle_tracks_selected(
|
||||
GtkSelectionModel * model,
|
||||
guint position,
|
||||
guint n_items,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_hide_popover(KotoPlaylistPage * self);
|
||||
void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListItem *item, gpointer user_data);
|
||||
void koto_playlist_page_set_playlist_uuid(KotoPlaylistPage *self, gchar *playlist_uuid);
|
||||
void koto_playlist_page_set_playlist_model(KotoPlaylistPage *self, KotoPreferredModelType model);
|
||||
|
||||
void koto_playlist_page_setup_track_item(
|
||||
GtkListItemFactory * factory,
|
||||
GtkListItem * item,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_page_set_playlist_uuid(
|
||||
KotoPlaylistPage * self,
|
||||
gchar * playlist_uuid
|
||||
);
|
||||
|
||||
void koto_playlist_page_set_playlist_model(
|
||||
KotoPlaylistPage * self,
|
||||
KotoPreferredModelType model
|
||||
);
|
||||
|
||||
void koto_playlist_page_show_popover(KotoPlaylistPage * self);
|
||||
|
||||
void koto_playlist_page_update_header(KotoPlaylistPage * self);
|
||||
|
||||
void koto_playlist_page_handle_listitem_activate(GtkListView *list, guint position, gpointer user_data);
|
||||
void koto_playlist_page_handle_listitem_activate(
|
||||
GtkListView * list,
|
||||
guint position,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -38,7 +38,9 @@ enum {
|
|||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint playback_engine_signals[N_SIGNALS] = { 0 };
|
||||
static guint playback_engine_signals[N_SIGNALS] = {
|
||||
0
|
||||
};
|
||||
|
||||
extern KotoCartographer * koto_maps;
|
||||
extern KotoCurrentPlaylist * current_playlist;
|
||||
|
@ -56,7 +58,6 @@ struct _KotoPlaybackEngine {
|
|||
GstQuery * position_query;
|
||||
|
||||
KotoIndexedTrack * current_track;
|
||||
NotifyNotification *track_notification;
|
||||
|
||||
gboolean is_muted;
|
||||
gboolean is_repeat_enabled;
|
||||
|
@ -90,6 +91,8 @@ static void koto_playback_engine_class_init(KotoPlaybackEngineClass *c) {
|
|||
c->play_state_changed = NULL;
|
||||
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
|
||||
playback_engine_signals[SIGNAL_IS_PLAYING] = g_signal_new(
|
||||
|
@ -226,6 +229,7 @@ static void koto_playback_engine_init(KotoPlaybackEngine *self) {
|
|||
void koto_playback_engine_backwards(KotoPlaybackEngine * self) {
|
||||
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;
|
||||
}
|
||||
|
@ -244,6 +248,7 @@ void koto_playback_engine_current_playlist_changed() {
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -254,6 +259,7 @@ void koto_playback_engine_current_playlist_changed() {
|
|||
void koto_playback_engine_forwards(KotoPlaybackEngine * self) {
|
||||
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;
|
||||
}
|
||||
|
@ -271,6 +277,8 @@ KotoIndexedTrack* koto_playback_engine_get_current_track(KotoPlaybackEngine *sel
|
|||
|
||||
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine * self) {
|
||||
gint64 duration = 0;
|
||||
|
||||
|
||||
if (gst_element_query(self->player, self->duration_query)) { // Able to query our duration
|
||||
gst_query_parse_duration(self->duration_query, NULL, &duration); // Get the duration
|
||||
duration = duration / GST_SECOND; // Divide by NS to get seconds
|
||||
|
@ -282,6 +290,8 @@ gint64 koto_playback_engine_get_duration(KotoPlaybackEngine *self) {
|
|||
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine * self) {
|
||||
gdouble progress = 0.0;
|
||||
gint64 gstprog = 0;
|
||||
|
||||
|
||||
if (gst_element_query(self->playbin, self->position_query)) { // Able to get our position
|
||||
gst_query_parse_position(self->position_query, NULL, &gstprog); // Get the progress
|
||||
|
||||
|
@ -307,20 +317,28 @@ gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine *self) {
|
|||
(void) self;
|
||||
KotoPlaylist * playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean currently_shuffling = FALSE;
|
||||
|
||||
|
||||
g_object_get(playlist, "is-shuffle-enabled", ¤tly_shuffling, NULL); // Get the current is-shuffle-enabled
|
||||
|
||||
return currently_shuffling;
|
||||
}
|
||||
|
||||
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data) {
|
||||
gboolean koto_playback_engine_monitor_changed(
|
||||
GstBus * bus,
|
||||
GstMessage * msg,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) bus;
|
||||
KotoPlaybackEngine * self = user_data;
|
||||
|
||||
|
||||
switch (GST_MESSAGE_TYPE(msg)) {
|
||||
case GST_MESSAGE_ASYNC_DONE:
|
||||
case GST_MESSAGE_DURATION_CHANGED: { // Duration changed
|
||||
|
@ -380,18 +398,28 @@ void koto_playback_engine_pause(KotoPlaybackEngine *self) {
|
|||
koto_update_mpris_playback_state(GST_STATE_PAUSED);
|
||||
}
|
||||
|
||||
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position) {
|
||||
void koto_playback_engine_set_position(
|
||||
KotoPlaybackEngine * self,
|
||||
int position
|
||||
) {
|
||||
gst_element_seek_simple(self->playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, position * GST_SECOND);
|
||||
}
|
||||
|
||||
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable_repeat) {
|
||||
void koto_playback_engine_set_track_repeat(
|
||||
KotoPlaybackEngine * self,
|
||||
gboolean enable_repeat
|
||||
) {
|
||||
self->is_repeat_enabled = enable_repeat;
|
||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_REPEAT_CHANGE], 0); // Emit our track repeat changed event
|
||||
}
|
||||
|
||||
void koto_playback_engine_set_track_shuffle(KotoPlaybackEngine *self, gboolean enable_shuffle) {
|
||||
void koto_playback_engine_set_track_shuffle(
|
||||
KotoPlaybackEngine * self,
|
||||
gboolean enable_shuffle
|
||||
) {
|
||||
KotoPlaylist * playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||
return;
|
||||
}
|
||||
|
@ -400,13 +428,17 @@ void koto_playback_engine_set_track_shuffle(KotoPlaybackEngine *self, gboolean e
|
|||
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_SHUFFLE_CHANGE], 0); // Emit our track shuffle changed event
|
||||
}
|
||||
|
||||
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid) {
|
||||
void koto_playback_engine_set_track_by_uuid(
|
||||
KotoPlaybackEngine * self,
|
||||
gchar * track_uuid
|
||||
) {
|
||||
if (track_uuid == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid); // Get the track from cartographer
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||
return;
|
||||
}
|
||||
|
@ -414,12 +446,15 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
|||
self->current_track = track;
|
||||
|
||||
gchar * track_file_path = NULL;
|
||||
|
||||
|
||||
g_object_get(track, "path", &track_file_path, NULL); // Get the path to the track
|
||||
|
||||
koto_playback_engine_stop(self); // Stop current track
|
||||
|
||||
gchar * gst_filename = gst_filename_to_uri(track_file_path, NULL); // Get the gst supported file naem
|
||||
|
||||
|
||||
g_object_set(self->playbin, "uri", gst_filename, NULL);
|
||||
g_free(gst_filename); // Free the filename
|
||||
|
||||
|
@ -432,6 +467,7 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
|||
GVariant * metadata = koto_indexed_track_get_metadata_vardict(track); // Get the GVariantBuilder variable dict for the metadata
|
||||
GVariantDict * metadata_dict = g_variant_dict_new(metadata);
|
||||
|
||||
|
||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_CHANGE], 0); // Emit our track change signal
|
||||
koto_update_mpris_info_for_track(self->current_track);
|
||||
|
||||
|
@ -448,6 +484,7 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
|||
|
||||
gchar * icon_name = "audio-x-generic-symbolic";
|
||||
|
||||
|
||||
if (g_variant_dict_contains(metadata_dict, "mpris:artUrl")) { // If we have artwork specified
|
||||
GVariant * art_url_var = g_variant_dict_lookup_value(metadata_dict, "mpris:artUrl", NULL); // Get the GVariant for the art URL
|
||||
const gchar * art_uri = g_variant_get_string(art_url_var, NULL); // Get the string for the artwork
|
||||
|
@ -474,7 +511,10 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playback_engine_set_volume(KotoPlaybackEngine *self, gdouble volume) {
|
||||
void koto_playback_engine_set_volume(
|
||||
KotoPlaybackEngine * self,
|
||||
gdouble volume
|
||||
) {
|
||||
self->volume = volume;
|
||||
g_object_set(self->playbin, "volume", self->volume, NULL);
|
||||
}
|
||||
|
@ -483,6 +523,7 @@ void koto_playback_engine_stop(KotoPlaybackEngine *self) {
|
|||
gst_element_set_state(self->player, GST_STATE_NULL);
|
||||
GstPad * pad = gst_element_get_static_pad(self->player, "sink"); // Get the static pad of the audio element
|
||||
|
||||
|
||||
if (!GST_IS_PAD(pad)) {
|
||||
return;
|
||||
}
|
||||
|
@ -502,6 +543,7 @@ void koto_playback_engine_toggle(KotoPlaybackEngine *self) {
|
|||
gboolean koto_playback_engine_tick_duration(gpointer user_data) {
|
||||
KotoPlaybackEngine * self = user_data;
|
||||
|
||||
|
||||
if (self->is_playing) { // Is playing
|
||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_DURATION], 0); // Emit our 1s track tick
|
||||
} else { // Not playing so exiting timer
|
||||
|
@ -514,6 +556,7 @@ gboolean koto_playback_engine_tick_duration(gpointer user_data) {
|
|||
gboolean koto_playback_engine_tick_track(gpointer user_data) {
|
||||
KotoPlaybackEngine * self = user_data;
|
||||
|
||||
|
||||
if (self->is_playing) { // Is playing
|
||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_TRACK], 0); // Emit our 100ms track tick
|
||||
} else {
|
||||
|
|
|
@ -42,29 +42,72 @@ GType koto_playback_engine_get_type(void) G_GNUC_CONST;
|
|||
**/
|
||||
|
||||
KotoPlaybackEngine * koto_playback_engine_new();
|
||||
|
||||
void koto_playback_engine_backwards(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_current_playlist_changed();
|
||||
|
||||
void koto_playback_engine_forwards(KotoPlaybackEngine * self);
|
||||
|
||||
KotoIndexedTrack * koto_playback_engine_get_current_track(KotoPlaybackEngine * self);
|
||||
|
||||
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine * self);
|
||||
|
||||
GstState koto_playback_engine_get_state(KotoPlaybackEngine * self);
|
||||
|
||||
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine * self);
|
||||
|
||||
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine * self);
|
||||
|
||||
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_mute(KotoPlaybackEngine * self);
|
||||
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data);
|
||||
|
||||
gboolean koto_playback_engine_monitor_changed(
|
||||
GstBus * bus,
|
||||
GstMessage * msg,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playback_engine_pause(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_play(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_toggle(KotoPlaybackEngine * self);
|
||||
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position);
|
||||
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable_repeat);
|
||||
void koto_playback_engine_set_track_shuffle(KotoPlaybackEngine *self, gboolean enable_shuffle);
|
||||
void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *track_uuid);
|
||||
void koto_playback_engine_set_volume(KotoPlaybackEngine *self, gdouble volume);
|
||||
|
||||
void koto_playback_engine_set_position(
|
||||
KotoPlaybackEngine * self,
|
||||
int position
|
||||
);
|
||||
|
||||
void koto_playback_engine_set_track_repeat(
|
||||
KotoPlaybackEngine * self,
|
||||
gboolean enable_repeat
|
||||
);
|
||||
|
||||
void koto_playback_engine_set_track_shuffle(
|
||||
KotoPlaybackEngine * self,
|
||||
gboolean enable_shuffle
|
||||
);
|
||||
|
||||
void koto_playback_engine_set_track_by_uuid(
|
||||
KotoPlaybackEngine * self,
|
||||
gchar * track_uuid
|
||||
);
|
||||
|
||||
void koto_playback_engine_set_volume(
|
||||
KotoPlaybackEngine * self,
|
||||
gdouble volume
|
||||
);
|
||||
|
||||
void koto_playback_engine_stop(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine * self);
|
||||
|
||||
void koto_playback_engine_update_duration(KotoPlaybackEngine * self);
|
||||
|
||||
gboolean koto_playback_engine_tick_duration(gpointer user_data);
|
||||
|
||||
gboolean koto_playback_engine_tick_track(gpointer user_data);
|
||||
|
|
|
@ -63,13 +63,25 @@ void grab_media_keys() {
|
|||
);
|
||||
}
|
||||
|
||||
void handle_media_keys_async_done(GObject *source_object, GAsyncResult *res, gpointer user_data) {
|
||||
void handle_media_keys_async_done(
|
||||
GObject * source_object,
|
||||
GAsyncResult * res,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, NULL); // Ensure we finish our call
|
||||
}
|
||||
|
||||
void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data) {
|
||||
(void) proxy; (void) sender_name; (void) user_data;
|
||||
void handle_media_keys_signal(
|
||||
GDBusProxy * proxy,
|
||||
const gchar * sender_name,
|
||||
const gchar * signal_name,
|
||||
GVariant * parameters,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) proxy;
|
||||
(void) sender_name;
|
||||
(void) user_data;
|
||||
if (g_strcmp0(signal_name, "MediaPlayerKeyPressed") != 0) { // Not MediaPlayerKeyPressed
|
||||
return;
|
||||
}
|
||||
|
@ -77,6 +89,7 @@ void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const
|
|||
gchar * application_name = NULL;
|
||||
gchar * key = NULL;
|
||||
|
||||
|
||||
g_variant_get(parameters, "(ss)", &application_name, &key);
|
||||
|
||||
if (g_strcmp0(application_name, "com.github.joshstrobl.koto") != 0) { // Not for Koto
|
||||
|
@ -100,13 +113,21 @@ void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const
|
|||
}
|
||||
}
|
||||
|
||||
void handle_window_enter(GtkEventControllerFocus *controller, gpointer user_data) {
|
||||
(void) controller; (void) user_data;
|
||||
void handle_window_enter(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) controller;
|
||||
(void) user_data;
|
||||
grab_media_keys(); // Grab our media keys
|
||||
}
|
||||
|
||||
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data) {
|
||||
(void) controller; (void) user_data;
|
||||
void handle_window_leave(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) controller;
|
||||
(void) user_data;
|
||||
release_media_keys(); // Release our media keys
|
||||
}
|
||||
|
||||
|
@ -117,6 +138,7 @@ void release_media_keys() {
|
|||
|
||||
GVariant * params = g_variant_new_string(g_strdup("com.github.joshstrobl.koto"));
|
||||
|
||||
|
||||
g_dbus_proxy_call(
|
||||
media_keys_proxy,
|
||||
"ReleaseMediaPlayerKeys",
|
||||
|
@ -136,6 +158,7 @@ void setup_mediakeys_interface() {
|
|||
GDBusConnection * bus;
|
||||
GError * error = NULL;
|
||||
|
||||
|
||||
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
|
||||
|
||||
if (bus == NULL) { // Failed to get session bus
|
||||
|
@ -170,6 +193,8 @@ void setup_mediakeys_interface() {
|
|||
);
|
||||
|
||||
GtkEventController * focus_controller = gtk_event_controller_focus_new(); // Create a new focus controller
|
||||
|
||||
|
||||
g_signal_connect(focus_controller, "enter", G_CALLBACK(handle_window_enter), NULL);
|
||||
g_signal_connect(focus_controller, "leave", G_CALLBACK(handle_window_leave), NULL);
|
||||
gtk_widget_add_controller(GTK_WIDGET(main_window), focus_controller);
|
||||
|
|
|
@ -22,11 +22,33 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
void grab_media_keys();
|
||||
void handle_media_keys_async_done(GObject *source_object, GAsyncResult *res, gpointer user_data);
|
||||
void handle_media_keys_signal(GDBusProxy *proxy, const gchar *sender_name, const gchar *signal_name, GVariant *parameters, gpointer user_data);
|
||||
void handle_window_enter(GtkEventControllerFocus *controller, gpointer user_data);
|
||||
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data);
|
||||
|
||||
void handle_media_keys_async_done(
|
||||
GObject * source_object,
|
||||
GAsyncResult * res,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void handle_media_keys_signal(
|
||||
GDBusProxy * proxy,
|
||||
const gchar * sender_name,
|
||||
const gchar * signal_name,
|
||||
GVariant * parameters,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void handle_window_enter(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void handle_window_leave(
|
||||
GtkEventControllerFocus * controller,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void release_media_keys();
|
||||
|
||||
void setup_mediakeys_interface();
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -23,10 +23,16 @@
|
|||
GHashTable * supported_mimes_hash = NULL;
|
||||
GList * supported_mimes = NULL;
|
||||
|
||||
gboolean koto_playback_engine_gst_caps_iter(GstCapsFeatures *features, GstStructure *structure, gpointer user_data) {
|
||||
(void) features; (void) user_data;
|
||||
gboolean koto_playback_engine_gst_caps_iter(
|
||||
GstCapsFeatures * features,
|
||||
GstStructure * structure,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) features;
|
||||
(void) user_data;
|
||||
gchar * caps_name = (gchar*) gst_structure_get_name(structure); // Get the name, typically a mimetype
|
||||
|
||||
|
||||
if (g_str_has_prefix(caps_name, "unknown")) { // Is unknown
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -42,9 +48,14 @@ gboolean koto_playback_engine_gst_caps_iter(GstCapsFeatures *features, GstStruct
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void koto_playback_engine_gst_pad_iter(gpointer list_data, gpointer user_data) {
|
||||
void koto_playback_engine_gst_pad_iter(
|
||||
gpointer list_data,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) user_data;
|
||||
GstStaticPadTemplate * templ = list_data;
|
||||
|
||||
|
||||
if (templ->direction == GST_PAD_SINK) { // Is a sink pad
|
||||
GstCaps * capabilities = gst_static_pad_template_get_caps(templ); // Get the capabilities
|
||||
gst_caps_foreach(capabilities, koto_playback_engine_gst_caps_iter, NULL); // Iterate over and add to mimes
|
||||
|
@ -58,6 +69,8 @@ void koto_playback_engine_get_supported_mimetypes() {
|
|||
GList * elements = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER | GST_ELEMENT_FACTORY_TYPE_DEMUXER | GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO, GST_RANK_NONE);
|
||||
|
||||
GList * ele;
|
||||
|
||||
|
||||
for (ele = elements; ele != NULL; ele = ele->next) { // For each of the elements
|
||||
// GList of GstStaticPadTemplate
|
||||
GList * static_pads = (GList*) gst_element_factory_get_static_pad_templates(ele->data); // Get the pads
|
||||
|
|
|
@ -21,8 +21,17 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean koto_bplayback_engine_gst_caps_iter(GstCapsFeatures *features, GstStructure *structure, gpointer user_data);
|
||||
void koto_playback_engine_gst_pad_iter(gpointer list_data, gpointer user_data);
|
||||
gboolean koto_bplayback_engine_gst_caps_iter(
|
||||
GstCapsFeatures * features,
|
||||
GstStructure * structure,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playback_engine_gst_pad_iter(
|
||||
gpointer list_data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playback_engine_get_supported_mimetypes(GList * mimes);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -94,7 +94,12 @@ void handle_method_call(
|
|||
GDBusMethodInvocation * invocation,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) connection; (void) sender; (void) object_path; (void) parameters; (void) invocation; (void) user_data;
|
||||
(void) connection;
|
||||
(void) sender;
|
||||
(void) object_path;
|
||||
(void) parameters;
|
||||
(void) invocation;
|
||||
(void) user_data;
|
||||
|
||||
if (g_strcmp0(interface_name, "org.mpris.MediaPlayer2") == 0) { // Root mediaplayer2 interface
|
||||
if (g_strcmp0(method_name, "Raise") == 0) { // Raise the window
|
||||
|
@ -149,8 +154,15 @@ GVariant* handle_get_property(
|
|||
GError ** error,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) connection; (void) sender; (void) object_path; (void) interface_name; (void) error; (void) user_data;
|
||||
(void) connection;
|
||||
(void) sender;
|
||||
(void) object_path;
|
||||
(void) interface_name;
|
||||
(void) error;
|
||||
(void) user_data;
|
||||
GVariant * ret;
|
||||
|
||||
|
||||
ret = NULL;
|
||||
|
||||
if (g_strcmp0(property_name, "CanQuit") == 0) { // If property is CanQuit
|
||||
|
@ -261,7 +273,12 @@ gboolean handle_set_property(
|
|||
GError ** error,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) connection; (void) sender; (void) interface_name; (void) object_path; (void) error; (void) user_data;
|
||||
(void) connection;
|
||||
(void) sender;
|
||||
(void) interface_name;
|
||||
(void) object_path;
|
||||
(void) error;
|
||||
(void) user_data;
|
||||
|
||||
if (g_strcmp0(property_name, "LoopStatus") == 0) { // Changing LoopStatus
|
||||
koto_playback_engine_set_track_repeat(playback_engine, g_variant_get_boolean(value)); // Set the loop status state
|
||||
|
@ -279,6 +296,7 @@ gboolean handle_set_property(
|
|||
void koto_update_mpris_playback_state(GstState state) {
|
||||
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||
|
||||
|
||||
if (state == GST_STATE_PLAYING) {
|
||||
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Playing"));
|
||||
} else if (state == GST_STATE_PAUSED) {
|
||||
|
@ -287,7 +305,8 @@ void koto_update_mpris_playback_state(GstState state) {
|
|||
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Stopped"));
|
||||
}
|
||||
|
||||
g_dbus_connection_emit_signal(dbus_conn,
|
||||
g_dbus_connection_emit_signal(
|
||||
dbus_conn,
|
||||
NULL,
|
||||
"/org/mpris/MediaPlayer2",
|
||||
"org.freedesktop.DBus.Properties",
|
||||
|
@ -303,18 +322,26 @@ void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
|||
}
|
||||
|
||||
GVariant * metadata = koto_indexed_track_get_metadata_vardict(track); // Get the GVariantBuilder variable dict for the metadata
|
||||
|
||||
|
||||
koto_update_mpris_info_for_track_with_metadata(track, metadata);
|
||||
}
|
||||
|
||||
void koto_update_mpris_info_for_track_with_metadata(KotoIndexedTrack *track, GVariant *metadata) {
|
||||
void koto_update_mpris_info_for_track_with_metadata(
|
||||
KotoIndexedTrack * track,
|
||||
GVariant * metadata
|
||||
) {
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||
|
||||
|
||||
g_variant_builder_add(builder, "{sv}", "Metadata", metadata);
|
||||
|
||||
g_dbus_connection_emit_signal(dbus_conn,
|
||||
g_dbus_connection_emit_signal(
|
||||
dbus_conn,
|
||||
NULL,
|
||||
"/org/mpris/MediaPlayer2",
|
||||
"org.freedesktop.DBus.Properties",
|
||||
|
@ -331,10 +358,16 @@ static const GDBusInterfaceVTable main_mpris_interface_vtable = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
||||
(void) name; (void) user_data;
|
||||
void on_main_mpris_bus_acquired(
|
||||
GDBusConnection * connection,
|
||||
const gchar * name,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) name;
|
||||
(void) user_data;
|
||||
dbus_conn = connection;
|
||||
g_dbus_connection_register_object(dbus_conn,
|
||||
g_dbus_connection_register_object(
|
||||
dbus_conn,
|
||||
"/org/mpris/MediaPlayer2",
|
||||
introspection_data->interfaces[0],
|
||||
&main_mpris_interface_vtable,
|
||||
|
@ -343,7 +376,8 @@ void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name,
|
|||
NULL
|
||||
);
|
||||
|
||||
g_dbus_connection_register_object(dbus_conn,
|
||||
g_dbus_connection_register_object(
|
||||
dbus_conn,
|
||||
"/org/mpris/MediaPlayer2",
|
||||
introspection_data->interfaces[1],
|
||||
&main_mpris_interface_vtable,
|
||||
|
@ -357,7 +391,8 @@ void setup_mpris_interfaces() {
|
|||
introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
||||
g_assert(introspection_data != NULL);
|
||||
|
||||
mpris_bus_id = g_bus_own_name(G_BUS_TYPE_SESSION,
|
||||
mpris_bus_id = g_bus_own_name(
|
||||
G_BUS_TYPE_SESSION,
|
||||
"org.mpris.MediaPlayer2.koto",
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
on_main_mpris_bus_acquired,
|
||||
|
|
|
@ -22,10 +22,50 @@
|
|||
#include "../indexer/structs.h"
|
||||
|
||||
void koto_update_mpris_playback_state(GstState state);
|
||||
|
||||
void koto_update_mpris_info_for_track(KotoIndexedTrack * track);
|
||||
void koto_update_mpris_info_for_track_with_metadata(KotoIndexedTrack *track, GVariant *metadata);
|
||||
void handle_method_call(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data);
|
||||
GVariant* handle_get_property(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GError **error, gpointer user_data);
|
||||
gboolean handle_set_property(GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *property_name, GVariant *value, GError **error, gpointer user_data);
|
||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
||||
|
||||
void koto_update_mpris_info_for_track_with_metadata(
|
||||
KotoIndexedTrack * track,
|
||||
GVariant * metadata
|
||||
);
|
||||
|
||||
void handle_method_call(
|
||||
GDBusConnection * connection,
|
||||
const gchar * sender,
|
||||
const gchar * object_path,
|
||||
const gchar * interface_name,
|
||||
const gchar * method_name,
|
||||
GVariant * parameters,
|
||||
GDBusMethodInvocation * invocation,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
GVariant * handle_get_property(
|
||||
GDBusConnection * connection,
|
||||
const gchar * sender,
|
||||
const gchar * object_path,
|
||||
const gchar * interface_name,
|
||||
const gchar * property_name,
|
||||
GError ** error,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
gboolean handle_set_property(
|
||||
GDBusConnection * connection,
|
||||
const gchar * sender,
|
||||
const gchar * object_path,
|
||||
const gchar * interface_name,
|
||||
const gchar * property_name,
|
||||
GVariant * value,
|
||||
GError ** error,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void on_main_mpris_bus_acquired(
|
||||
GDBusConnection * connection,
|
||||
const gchar * name,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void setup_mpris_interfaces();
|
||||
|
|
|
@ -58,7 +58,10 @@ static void koto_add_remove_track_popover_init(KotoAddRemoveTrackPopover *self)
|
|||
g_signal_connect(koto_maps, "playlist-removed", G_CALLBACK(koto_add_remove_track_popover_handle_playlist_removed), self);
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_add_playlist(KotoAddRemoveTrackPopover *self, KotoPlaylist *playlist) {
|
||||
void koto_add_remove_track_popover_add_playlist(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
KotoPlaylist * playlist
|
||||
) {
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -69,16 +72,21 @@ void koto_add_remove_track_popover_add_playlist(KotoAddRemoveTrackPopover *self,
|
|||
|
||||
gchar * playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID of the playlist
|
||||
|
||||
|
||||
if (GTK_IS_CHECK_BUTTON(g_hash_table_lookup(self->playlist_uuid_to_checkbox, playlist_uuid))) { // Already have a check button for this
|
||||
g_free(playlist_uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
GtkWidget * playlist_button = gtk_check_button_new_with_label(koto_playlist_get_name(playlist)); // Create our GtkCheckButton
|
||||
|
||||
|
||||
g_hash_table_insert(self->checkbox_to_playlist_uuid, playlist_button, playlist_uuid);
|
||||
g_hash_table_insert(self->playlist_uuid_to_checkbox, playlist_uuid, playlist_button);
|
||||
|
||||
gulong playlist_sig_id = g_signal_connect(playlist_button, "toggled", G_CALLBACK(koto_add_remove_track_popover_handle_checkbutton_toggle), self);
|
||||
|
||||
|
||||
g_hash_table_insert(self->checkbox_to_signal_ids, playlist_button, GUINT_TO_POINTER(playlist_sig_id)); // Add our GSignal handler ID
|
||||
|
||||
gtk_list_box_append(GTK_LIST_BOX(self->list_box), playlist_button); // Add the playlist to the list box
|
||||
|
@ -95,7 +103,10 @@ void koto_add_remove_track_popover_clear_tracks(KotoAddRemoveTrackPopover *self)
|
|||
}
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *self, gchar *playlist_uuid) {
|
||||
void koto_add_remove_track_popover_remove_playlist(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
gchar * playlist_uuid
|
||||
) {
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -106,6 +117,7 @@ void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *se
|
|||
|
||||
GtkCheckButton * btn = GTK_CHECK_BUTTON(g_hash_table_lookup(self->playlist_uuid_to_checkbox, playlist_uuid)); // Get the check button
|
||||
|
||||
|
||||
if (GTK_IS_CHECK_BUTTON(btn)) { // Is a check button
|
||||
g_hash_table_remove(self->checkbox_to_playlist_uuid, btn); // Remove uuid based on btn
|
||||
gtk_list_box_remove(GTK_LIST_BOX(self->list_box), GTK_WIDGET(btn)); // Remove the button from the list box
|
||||
|
@ -114,9 +126,13 @@ void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *se
|
|||
g_hash_table_remove(self->playlist_uuid_to_checkbox, playlist_uuid);
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn, gpointer user_data) {
|
||||
void koto_add_remove_track_popover_handle_checkbutton_toggle(
|
||||
GtkCheckButton * btn,
|
||||
gpointer user_data
|
||||
) {
|
||||
KotoAddRemoveTrackPopover * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -126,11 +142,14 @@ void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn
|
|||
|
||||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid); // Get the playlist
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Failed to get the playlist
|
||||
return;
|
||||
}
|
||||
|
||||
GList * pos;
|
||||
|
||||
|
||||
for (pos = self->tracks; pos != NULL; pos = pos->next) { // Iterate over our KotoIndexedTracks
|
||||
KotoIndexedTrack * track = pos->data;
|
||||
|
||||
|
@ -150,10 +169,15 @@ void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn
|
|||
gtk_popover_popdown(GTK_POPOVER(self)); // Temporary to hopefully prevent a bork
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data) {
|
||||
void koto_add_remove_track_popover_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) carto;
|
||||
KotoAddRemoveTrackPopover * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -161,10 +185,15 @@ void koto_add_remove_track_popover_handle_playlist_added(KotoCartographer *carto
|
|||
koto_add_remove_track_popover_add_playlist(self, playlist);
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_handle_playlist_removed(KotoCartographer *carto, gchar *playlist_uuid, gpointer user_data) {
|
||||
void koto_add_remove_track_popover_handle_playlist_removed(
|
||||
KotoCartographer * carto,
|
||||
gchar * playlist_uuid,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) carto;
|
||||
KotoAddRemoveTrackPopover * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -172,7 +201,11 @@ void koto_add_remove_track_popover_handle_playlist_removed(KotoCartographer *car
|
|||
koto_add_remove_track_popover_remove_playlist(self, playlist_uuid);
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_set_pointing_to_widget(KotoAddRemoveTrackPopover *self, GtkWidget *widget, GtkPositionType pos) {
|
||||
void koto_add_remove_track_popover_set_pointing_to_widget(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
GtkWidget * widget,
|
||||
GtkPositionType pos
|
||||
) {
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -183,6 +216,7 @@ void koto_add_remove_track_popover_set_pointing_to_widget(KotoAddRemoveTrackPopo
|
|||
|
||||
GtkWidget* existing_parent = gtk_widget_get_parent(GTK_WIDGET(self));
|
||||
|
||||
|
||||
if (existing_parent != NULL) {
|
||||
g_object_ref(GTK_WIDGET(self)); // Increment widget ref since unparent will do an unref
|
||||
gtk_widget_unparent(GTK_WIDGET(self)); // Unparent the popup
|
||||
|
@ -192,13 +226,17 @@ void koto_add_remove_track_popover_set_pointing_to_widget(KotoAddRemoveTrackPopo
|
|||
gtk_popover_set_position(GTK_POPOVER(self), pos);
|
||||
}
|
||||
|
||||
void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, GList *tracks) {
|
||||
void koto_add_remove_track_popover_set_tracks(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
GList * tracks
|
||||
) {
|
||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gint tracks_len = g_list_length(tracks);
|
||||
|
||||
|
||||
if (tracks_len == 0) { // No tracks
|
||||
return;
|
||||
}
|
||||
|
@ -208,6 +246,7 @@ void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, G
|
|||
GHashTableIter playlists_iter;
|
||||
gpointer uuid, playlist_ptr;
|
||||
|
||||
|
||||
g_hash_table_iter_init(&playlists_iter, playlists); // Init our HashTable iterator
|
||||
|
||||
while (g_hash_table_iter_next(&playlists_iter, &uuid, &playlist_ptr)) { // While we are iterating through our playlists
|
||||
|
|
|
@ -36,13 +36,45 @@ G_DECLARE_FINAL_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, K
|
|||
**/
|
||||
|
||||
KotoAddRemoveTrackPopover * koto_add_remove_track_popover_new();
|
||||
void koto_add_remove_track_popover_add_playlist(KotoAddRemoveTrackPopover *self, KotoPlaylist *playlist);
|
||||
|
||||
void koto_add_remove_track_popover_add_playlist(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_clear_tracks(KotoAddRemoveTrackPopover * self);
|
||||
void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *self, gchar *playlist_uuid);
|
||||
void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn, gpointer user_data);
|
||||
void koto_add_remove_track_popover_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data);
|
||||
void koto_add_remove_track_popover_handle_playlist_removed(KotoCartographer *carto, gchar *playlist_uuid, gpointer user_data);
|
||||
void koto_add_remove_track_popover_set_pointing_to_widget(KotoAddRemoveTrackPopover *self, GtkWidget *widget, GtkPositionType pos);
|
||||
void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, GList *tracks);
|
||||
|
||||
void koto_add_remove_track_popover_remove_playlist(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
gchar * playlist_uuid
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_handle_checkbutton_toggle(
|
||||
GtkCheckButton * btn,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_handle_playlist_added(
|
||||
KotoCartographer * carto,
|
||||
KotoPlaylist * playlist,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_handle_playlist_removed(
|
||||
KotoCartographer * carto,
|
||||
gchar * playlist_uuid,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_set_pointing_to_widget(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
GtkWidget * widget,
|
||||
GtkPositionType pos
|
||||
);
|
||||
|
||||
void koto_add_remove_track_popover_set_tracks(
|
||||
KotoAddRemoveTrackPopover * self,
|
||||
GList * tracks
|
||||
);
|
||||
|
||||
G_END_DECLS
|
|
@ -33,7 +33,9 @@ enum {
|
|||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *dialog_props[N_PROPS] = { NULL, };
|
||||
static GParamSpec * dialog_props[N_PROPS] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
struct _KotoCreateModifyPlaylistDialog {
|
||||
|
@ -51,11 +53,24 @@ G_DEFINE_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist_dialog
|
|||
|
||||
KotoCreateModifyPlaylistDialog * playlist_create_modify_dialog;
|
||||
|
||||
static void koto_create_modify_playlist_dialog_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_create_modify_playlist_dialog_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_create_modify_playlist_dialog_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_create_modify_playlist_dialog_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_create_modify_playlist_dialog_class_init(KotoCreateModifyPlaylistDialogClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_create_modify_playlist_dialog_set_property;
|
||||
gobject_class->get_property = koto_create_modify_playlist_dialog_get_property;
|
||||
|
@ -83,10 +98,14 @@ static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDial
|
|||
gtk_box_append(GTK_BOX(self), self->playlist_image); // Add our image
|
||||
|
||||
GtkDropTarget * target = gtk_drop_target_new(G_TYPE_FILE, GDK_ACTION_COPY);
|
||||
|
||||
|
||||
g_signal_connect(GTK_EVENT_CONTROLLER(target), "drop", G_CALLBACK(koto_create_modify_playlist_dialog_handle_drop), self);
|
||||
gtk_widget_add_controller(self->playlist_image, GTK_EVENT_CONTROLLER(target));
|
||||
|
||||
GtkGesture * image_click_controller = gtk_gesture_click_new(); // Create a click gesture for the image clicking
|
||||
|
||||
|
||||
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(image_click_controller), 1); // Only allow left click
|
||||
g_signal_connect(GTK_EVENT_CONTROLLER(image_click_controller), "pressed", G_CALLBACK(koto_create_modify_playlist_dialog_handle_image_click), self);
|
||||
|
||||
|
@ -105,9 +124,15 @@ static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDial
|
|||
gtk_box_append(GTK_BOX(self), self->create_button); // Add the create button
|
||||
}
|
||||
|
||||
static void koto_create_modify_playlist_dialog_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec){
|
||||
static void koto_create_modify_playlist_dialog_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoCreateModifyPlaylistDialog * self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PLAYLIST_UUID:
|
||||
g_value_set_string(val, (self->playlist_uuid != NULL) ? g_strdup(self->playlist_uuid) : NULL);
|
||||
|
@ -118,9 +143,17 @@ static void koto_create_modify_playlist_dialog_get_property(GObject *obj, guint
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_create_modify_playlist_dialog_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_create_modify_playlist_dialog_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoCreateModifyPlaylistDialog * self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
||||
(void) self; (void) val;
|
||||
|
||||
|
||||
(void) self;
|
||||
(void) val;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_PLAYLIST_UUID:
|
||||
|
@ -132,13 +165,19 @@ static void koto_create_modify_playlist_dialog_set_property(GObject *obj, guint
|
|||
}
|
||||
}
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_chooser_response(GtkNativeDialog *native, int response, gpointer user_data) {
|
||||
void koto_create_modify_playlist_dialog_handle_chooser_response(
|
||||
GtkNativeDialog * native,
|
||||
int response,
|
||||
gpointer user_data
|
||||
) {
|
||||
if (response != GTK_RESPONSE_ACCEPT) { // Not accept
|
||||
g_object_unref(native);
|
||||
return;
|
||||
}
|
||||
|
||||
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -146,6 +185,7 @@ void koto_create_modify_playlist_dialog_handle_chooser_response(GtkNativeDialog
|
|||
GFile * file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
||||
gchar * file_path = g_file_get_path(file); // Get the absolute path
|
||||
|
||||
|
||||
if (file_path != NULL) {
|
||||
self->playlist_image_path = g_strdup(file_path);
|
||||
gtk_image_set_from_file(GTK_IMAGE(self->playlist_image), self->playlist_image_path); // Set the file path
|
||||
|
@ -156,11 +196,15 @@ void koto_create_modify_playlist_dialog_handle_chooser_response(GtkNativeDialog
|
|||
g_object_unref(native);
|
||||
}
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, gpointer user_data) {
|
||||
void koto_create_modify_playlist_dialog_handle_create_click(
|
||||
GtkButton * button,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) button;
|
||||
|
||||
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
||||
return;
|
||||
}
|
||||
|
@ -173,6 +217,7 @@ void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, g
|
|||
KotoPlaylist * playlist = NULL;
|
||||
gboolean modify_existing_playlist = koto_utils_is_string_valid(self->playlist_uuid);
|
||||
|
||||
|
||||
if (modify_existing_playlist) { // Modifying an existing playlist
|
||||
playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->playlist_uuid);
|
||||
} else { // Creating a new playlist
|
||||
|
@ -196,8 +241,16 @@ void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, g
|
|||
koto_window_hide_dialogs(main_window); // Hide the dialogs
|
||||
}
|
||||
|
||||
gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, const GValue *val, double x, double y, gpointer user_data) {
|
||||
(void) target; (void) x; (void) y;
|
||||
gboolean koto_create_modify_playlist_dialog_handle_drop(
|
||||
GtkDropTarget * target,
|
||||
const GValue * val,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) target;
|
||||
(void) x;
|
||||
(void) y;
|
||||
|
||||
if (!G_VALUE_HOLDS(val, G_TYPE_FILE)) { // Not a file
|
||||
return FALSE;
|
||||
|
@ -205,12 +258,15 @@ gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, c
|
|||
|
||||
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||
|
||||
|
||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) { // No dialog
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GFile * dropped_file = g_value_get_object(val); // Get the GValue
|
||||
gchar * file_path = g_file_get_path(dropped_file); // Get the absolute path
|
||||
|
||||
|
||||
g_object_unref(dropped_file); // Unref the file
|
||||
|
||||
if (file_path == NULL) {
|
||||
|
@ -219,6 +275,7 @@ gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, c
|
|||
|
||||
magic_t magic_cookie = magic_open(MAGIC_MIME);
|
||||
|
||||
|
||||
if (magic_cookie == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -229,6 +286,7 @@ gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, c
|
|||
|
||||
const char * mime_type = magic_file(magic_cookie, file_path);
|
||||
|
||||
|
||||
if ((mime_type != NULL) && g_str_has_prefix(mime_type, "image/")) { // Is an image
|
||||
self->playlist_image_path = g_strdup(file_path);
|
||||
gtk_image_set_from_file(GTK_IMAGE(self->playlist_image), self->playlist_image_path); // Set the file path
|
||||
|
@ -241,12 +299,23 @@ cookie_closure:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_image_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data) {
|
||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
||||
void koto_create_modify_playlist_dialog_handle_image_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
) {
|
||||
(void) gesture;
|
||||
(void) n_press;
|
||||
(void) x;
|
||||
(void) y;
|
||||
|
||||
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||
|
||||
GtkFileChooserNative* chooser = koto_utils_create_image_file_chooser("Choose playlist image");
|
||||
|
||||
|
||||
g_signal_connect(chooser, "response", G_CALLBACK(koto_create_modify_playlist_dialog_handle_chooser_response), self);
|
||||
gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); // Show our file chooser
|
||||
}
|
||||
|
@ -262,13 +331,17 @@ void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog *se
|
|||
gtk_button_set_label(GTK_BUTTON(self->create_button), "Create");
|
||||
}
|
||||
|
||||
void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlaylistDialog *self, gchar *playlist_uuid) {
|
||||
void koto_create_modify_playlist_dialog_set_playlist_uuid(
|
||||
KotoCreateModifyPlaylistDialog * self,
|
||||
gchar * playlist_uuid
|
||||
) {
|
||||
if (!koto_utils_is_string_valid(playlist_uuid)) { // Not a valid playlist UUID string
|
||||
return;
|
||||
}
|
||||
|
||||
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid);
|
||||
|
||||
|
||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||
return;
|
||||
}
|
||||
|
@ -279,6 +352,7 @@ void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlayli
|
|||
|
||||
gchar * art = koto_playlist_get_artwork(playlist);
|
||||
|
||||
|
||||
if (!koto_utils_is_string_valid(art)) { // If art is not defined
|
||||
gtk_image_set_from_icon_name(GTK_IMAGE(self->playlist_image), "insert-image-symbolic"); // Reset the image
|
||||
} else {
|
||||
|
@ -292,10 +366,5 @@ void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlayli
|
|||
KotoCreateModifyPlaylistDialog * koto_create_modify_playlist_dialog_new(char * playlist_uuid) {
|
||||
(void) playlist_uuid;
|
||||
|
||||
return g_object_new(KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG,
|
||||
"orientation",
|
||||
GTK_ORIENTATION_VERTICAL,
|
||||
"spacing",
|
||||
40,
|
||||
NULL);
|
||||
return g_object_new(KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG, "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 40, NULL);
|
||||
}
|
|
@ -34,11 +34,39 @@ G_DECLARE_FINAL_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist
|
|||
**/
|
||||
|
||||
KotoCreateModifyPlaylistDialog * koto_create_modify_playlist_dialog_new();
|
||||
void koto_create_modify_playlist_dialog_handle_chooser_response(GtkNativeDialog *native, int response, gpointer user_data);
|
||||
void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, gpointer user_data);
|
||||
gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, const GValue *val, double x, double y, gpointer user_data);
|
||||
void koto_create_modify_playlist_dialog_handle_image_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_chooser_response(
|
||||
GtkNativeDialog * native,
|
||||
int response,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_create_click(
|
||||
GtkButton * button,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
gboolean koto_create_modify_playlist_dialog_handle_drop(
|
||||
GtkDropTarget * target,
|
||||
const GValue * val,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_create_modify_playlist_dialog_handle_image_click(
|
||||
GtkGestureClick * gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog * self);
|
||||
void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlaylistDialog *self, gchar *playlist_uuid);
|
||||
|
||||
void koto_create_modify_playlist_dialog_set_playlist_uuid(
|
||||
KotoCreateModifyPlaylistDialog * self,
|
||||
gchar * playlist_uuid
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -24,7 +24,9 @@ enum {
|
|||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
KotoCurrentPlaylist * current_playlist = NULL;
|
||||
|
||||
|
@ -35,11 +37,24 @@ struct _KotoCurrentPlaylist {
|
|||
|
||||
G_DEFINE_TYPE(KotoCurrentPlaylist, koto_current_playlist, G_TYPE_OBJECT);
|
||||
|
||||
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);
|
||||
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
|
||||
);
|
||||
|
||||
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;
|
||||
|
@ -59,9 +74,15 @@ 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) {
|
||||
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);
|
||||
|
@ -72,9 +93,15 @@ void koto_current_playlist_get_property(GObject *obj, guint prop_id, GValue *val
|
|||
}
|
||||
}
|
||||
|
||||
void koto_current_playlist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
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));
|
||||
|
@ -89,7 +116,10 @@ KotoPlaylist* koto_current_playlist_get_playlist(KotoCurrentPlaylist *self) {
|
|||
return self->current_playlist;
|
||||
}
|
||||
|
||||
void koto_current_playlist_set_playlist(KotoCurrentPlaylist *self, KotoPlaylist *playlist) {
|
||||
void koto_current_playlist_set_playlist(
|
||||
KotoCurrentPlaylist * self,
|
||||
KotoPlaylist * playlist
|
||||
) {
|
||||
if (!KOTO_IS_CURRENT_PLAYLIST(self)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,12 @@ G_DECLARE_FINAL_TYPE(KotoCurrentPlaylist, koto_current_playlist, KOTO, CURRENT_P
|
|||
**/
|
||||
|
||||
KotoCurrentPlaylist * koto_current_playlist_new();
|
||||
|
||||
KotoPlaylist * koto_current_playlist_get_playlist(KotoCurrentPlaylist * self);
|
||||
void koto_current_playlist_set_playlist(KotoCurrentPlaylist *self, KotoPlaylist *playlist);
|
||||
|
||||
void koto_current_playlist_set_playlist(
|
||||
KotoCurrentPlaylist * self,
|
||||
KotoPlaylist * playlist
|
||||
);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -69,21 +69,45 @@ struct _KotoPlaylistClass {
|
|||
GObjectClass parent_class;
|
||||
|
||||
void (* modified) (KotoPlaylist * playlist);
|
||||
void (* track_added) (KotoPlaylist *playlist, gchar *track_uuid);
|
||||
void (* track_added) (
|
||||
KotoPlaylist * playlist,
|
||||
gchar * track_uuid
|
||||
);
|
||||
void (* track_load_finalized) (KotoPlaylist * playlist);
|
||||
void (* track_removed) (KotoPlaylist *playlist, gchar *track_uuid);
|
||||
void (* track_removed) (
|
||||
KotoPlaylist * playlist,
|
||||
gchar * track_uuid
|
||||
);
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoPlaylist, koto_playlist, G_TYPE_OBJECT);
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL };
|
||||
static guint playlist_signals[N_SIGNALS] = { 0 };
|
||||
static GParamSpec * props[N_PROPERTIES] = {
|
||||
NULL
|
||||
};
|
||||
static guint playlist_signals[N_SIGNALS] = {
|
||||
0
|
||||
};
|
||||
|
||||
static void koto_playlist_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);;
|
||||
static void koto_playlist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
static void koto_playlist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
;
|
||||
static void koto_playlist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
);
|
||||
|
||||
static void koto_playlist_class_init(KotoPlaylistClass * c) {
|
||||
GObjectClass * gobject_class;
|
||||
|
||||
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_playlist_set_property;
|
||||
gobject_class->get_property = koto_playlist_get_property;
|
||||
|
@ -181,9 +205,15 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
|||
);
|
||||
}
|
||||
|
||||
static void koto_playlist_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
static void koto_playlist_get_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPlaylist * self = KOTO_PLAYLIST(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
g_value_set_string(val, self->uuid);
|
||||
|
@ -206,9 +236,15 @@ static void koto_playlist_get_property(GObject *obj, guint prop_id, GValue *val,
|
|||
}
|
||||
}
|
||||
|
||||
static void koto_playlist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
static void koto_playlist_set_property(
|
||||
GObject * obj,
|
||||
guint prop_id,
|
||||
const GValue * val,
|
||||
GParamSpec * spec
|
||||
) {
|
||||
KotoPlaylist * self = KOTO_PLAYLIST(obj);
|
||||
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_UUID:
|
||||
koto_playlist_set_uuid(self, g_value_get_string(val));
|
||||
|
@ -245,7 +281,10 @@ static void koto_playlist_init(KotoPlaylist *self) {
|
|||
self->store = g_list_store_new(KOTO_TYPE_INDEXED_TRACK);
|
||||
}
|
||||
|
||||
void koto_playlist_add_to_played_tracks(KotoPlaylist *self, gchar *uuid) {
|
||||
void koto_playlist_add_to_played_tracks(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
) {
|
||||
if (g_queue_index(self->played_tracks, uuid) != -1) { // Already added
|
||||
return;
|
||||
}
|
||||
|
@ -253,18 +292,31 @@ void koto_playlist_add_to_played_tracks(KotoPlaylist *self, gchar *uuid) {
|
|||
g_queue_push_tail(self->played_tracks, uuid); // Add to end
|
||||
}
|
||||
|
||||
void koto_playlist_add_track(KotoPlaylist *self, KotoIndexedTrack *track, gboolean current, gboolean commit_to_table) {
|
||||
void koto_playlist_add_track(
|
||||
KotoPlaylist * self,
|
||||
KotoIndexedTrack * track,
|
||||
gboolean current,
|
||||
gboolean commit_to_table
|
||||
) {
|
||||
koto_playlist_add_track_by_uuid(self, koto_indexed_track_get_uuid(track), current, commit_to_table);
|
||||
}
|
||||
|
||||
void koto_playlist_add_track_by_uuid(KotoPlaylist *self, gchar *uuid, gboolean current, gboolean commit_to_table) {
|
||||
void koto_playlist_add_track_by_uuid(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid,
|
||||
gboolean current,
|
||||
gboolean commit_to_table
|
||||
) {
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, uuid); // Get the track
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GList * found_tracks_uuids = g_queue_find_custom(self->tracks, uuid, koto_playlist_compare_track_uuids);
|
||||
|
||||
|
||||
if (found_tracks_uuids != NULL) { // Is somewhere in the tracks already
|
||||
g_list_free(found_tracks_uuids);
|
||||
return;
|
||||
|
@ -296,8 +348,13 @@ void koto_playlist_add_track_by_uuid(KotoPlaylist *self, gchar *uuid, gboolean c
|
|||
);
|
||||
}
|
||||
|
||||
void koto_playlist_apply_model(KotoPlaylist *self, KotoPreferredModelType preferred_model) {
|
||||
void koto_playlist_apply_model(
|
||||
KotoPlaylist * self,
|
||||
KotoPreferredModelType preferred_model
|
||||
) {
|
||||
GList * sort_user_data = NULL;
|
||||
|
||||
|
||||
sort_user_data = g_list_prepend(sort_user_data, GUINT_TO_POINTER(preferred_model)); // Prepend our preferred model first
|
||||
sort_user_data = g_list_prepend(sort_user_data, self); // Prepend ourself
|
||||
|
||||
|
@ -328,6 +385,7 @@ void koto_playlist_commit(KotoPlaylist *self) {
|
|||
gchar * commit_op_errmsg = NULL;
|
||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
g_warning("Failed to save playlist: %s", commit_op_errmsg);
|
||||
} else { // Successfully saved our playlist
|
||||
|
@ -338,9 +396,13 @@ void koto_playlist_commit(KotoPlaylist *self) {
|
|||
g_free(commit_op_errmsg);
|
||||
}
|
||||
|
||||
void koto_playlist_commit_tracks(gpointer data, gpointer user_data) {
|
||||
void koto_playlist_commit_tracks(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
) {
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, data); // Get the track
|
||||
|
||||
|
||||
if (track == NULL) { // Not a track
|
||||
KotoPlaylist * self = user_data;
|
||||
gchar * playlist_uuid = self->uuid; // Get the playlist UUID
|
||||
|
@ -352,7 +414,10 @@ void koto_playlist_commit_tracks(gpointer data, gpointer user_data) {
|
|||
}
|
||||
}
|
||||
|
||||
gint koto_playlist_compare_track_uuids(gconstpointer a, gconstpointer b) {
|
||||
gint koto_playlist_compare_track_uuids(
|
||||
gconstpointer a,
|
||||
gconstpointer b
|
||||
) {
|
||||
return g_strcmp0(a, b);
|
||||
}
|
||||
|
||||
|
@ -380,7 +445,10 @@ gchar* koto_playlist_get_name(KotoPlaylist *self) {
|
|||
return (self->name == NULL) ? NULL : g_strdup(self->name);
|
||||
}
|
||||
|
||||
gint koto_playlist_get_position_of_track(KotoPlaylist *self, KotoIndexedTrack *track) {
|
||||
gint koto_playlist_get_position_of_track(
|
||||
KotoPlaylist * self,
|
||||
KotoIndexedTrack * track
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST(self)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -396,6 +464,7 @@ gint koto_playlist_get_position_of_track(KotoPlaylist *self, KotoIndexedTrack *t
|
|||
gint position = -1;
|
||||
guint found_pos = 0;
|
||||
|
||||
|
||||
if (g_list_store_find(self->store, track, &found_pos)) { // Found the item
|
||||
position = (gint) found_pos; // Cast our found position from guint to gint
|
||||
}
|
||||
|
@ -407,6 +476,7 @@ gchar* koto_playlist_get_random_track(KotoPlaylist *self) {
|
|||
gchar * track_uuid = NULL;
|
||||
guint tracks_len = g_queue_get_length(self->sorted_tracks);
|
||||
|
||||
|
||||
if (tracks_len == g_queue_get_length(self->played_tracks)) { // Played all tracks
|
||||
track_uuid = g_list_nth_data(self->sorted_tracks->head, 0); // Get the first
|
||||
g_queue_clear(self->played_tracks); // Clear our played tracks
|
||||
|
@ -494,12 +564,14 @@ gchar* koto_playlist_go_to_previous(KotoPlaylist *self) {
|
|||
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, self->current_uuid);
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gint pos_of_song = koto_playlist_get_position_of_track(self, track); // Get the position of the current track based on the current model
|
||||
|
||||
|
||||
if (pos_of_song == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -525,14 +597,23 @@ void koto_playlist_mark_as_finalized(KotoPlaylist *self) {
|
|||
);
|
||||
}
|
||||
|
||||
gint koto_playlist_model_sort_by_uuid(gconstpointer first_item, gconstpointer second_item, gpointer data_list) {
|
||||
gint koto_playlist_model_sort_by_uuid(
|
||||
gconstpointer first_item,
|
||||
gconstpointer second_item,
|
||||
gpointer data_list
|
||||
) {
|
||||
KotoIndexedTrack * first_track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) first_item);
|
||||
KotoIndexedTrack * second_track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) second_item);
|
||||
|
||||
|
||||
return koto_playlist_model_sort_by_track(first_track, second_track, data_list);
|
||||
}
|
||||
|
||||
gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer second_item, gpointer data_list) {
|
||||
gint koto_playlist_model_sort_by_track(
|
||||
gconstpointer first_item,
|
||||
gconstpointer second_item,
|
||||
gpointer data_list
|
||||
) {
|
||||
KotoIndexedTrack * first_track = (KotoIndexedTrack*) first_item;
|
||||
KotoIndexedTrack * second_track = (KotoIndexedTrack*) second_item;
|
||||
|
||||
|
@ -540,6 +621,7 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
|||
KotoPlaylist * self = g_list_nth_data(ptr_list, 0); // First item in the GPtrArray is a pointer to our playlist
|
||||
KotoPreferredModelType model = GPOINTER_TO_UINT(g_list_nth_data(ptr_list, 1)); // Second item in the GPtrArray is a pointer to our KotoPreferredModelType
|
||||
|
||||
|
||||
if (
|
||||
(model == KOTO_PREFERRED_MODEL_TYPE_DEFAULT) || // Newest first model
|
||||
(model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) // Oldest first
|
||||
|
@ -658,35 +740,45 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
|||
return 0;
|
||||
}
|
||||
|
||||
void koto_playlist_remove_from_played_tracks(KotoPlaylist *self, gchar *uuid) {
|
||||
void koto_playlist_remove_from_played_tracks(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
) {
|
||||
g_queue_remove(self->played_tracks, uuid);
|
||||
}
|
||||
|
||||
void koto_playlist_remove_track_by_uuid(KotoPlaylist *self, gchar *uuid) {
|
||||
void koto_playlist_remove_track_by_uuid(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
) {
|
||||
if (!KOTO_IS_PLAYLIST(self)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gint file_index = g_queue_index(self->tracks, uuid); // Get the position of this uuid
|
||||
|
||||
|
||||
if (file_index != -1) { // Have in tracks
|
||||
g_queue_pop_nth(self->tracks, file_index); // Remove nth where it is the file index
|
||||
}
|
||||
|
||||
gint file_index_in_sorted = g_queue_index(self->sorted_tracks, uuid); // Get position in sorted tracks
|
||||
|
||||
|
||||
if (file_index_in_sorted != -1) { // Have in sorted tracks
|
||||
g_queue_pop_nth(self->sorted_tracks, file_index_in_sorted); // Remove nth where it is the index in sorted tracks
|
||||
}
|
||||
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, uuid); // Get the track
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Is not a track
|
||||
return;
|
||||
}
|
||||
|
||||
guint position = 0;
|
||||
|
||||
|
||||
if (g_list_store_find(self->store, track, &position)) { // Got the position
|
||||
g_list_store_remove(self->store, position); // Remove from the store
|
||||
}
|
||||
|
@ -701,13 +793,17 @@ void koto_playlist_remove_track_by_uuid(KotoPlaylist *self, gchar *uuid) {
|
|||
);
|
||||
}
|
||||
|
||||
void koto_playlist_set_artwork(KotoPlaylist *self, const gchar *path) {
|
||||
void koto_playlist_set_artwork(
|
||||
KotoPlaylist * self,
|
||||
const gchar * path
|
||||
) {
|
||||
if (path == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
magic_t cookie = magic_open(MAGIC_MIME); // Create our magic cookie so we can validate if what we are setting is an image
|
||||
|
||||
|
||||
if (cookie == NULL) { // Failed to allocate
|
||||
return;
|
||||
}
|
||||
|
@ -718,6 +814,7 @@ void koto_playlist_set_artwork(KotoPlaylist *self, const gchar *path) {
|
|||
|
||||
const gchar * mime_type = magic_file(cookie, path); // Get the mimetype for this file
|
||||
|
||||
|
||||
if ((mime_type == NULL) || !g_str_has_prefix(mime_type, "image/")) { // Failed to get our mimetype or not an image
|
||||
goto free_cookie;
|
||||
}
|
||||
|
@ -740,7 +837,10 @@ free_cookie:
|
|||
magic_close(cookie); // Close and free the cookie to the cookie monster
|
||||
}
|
||||
|
||||
void koto_playlist_set_name(KotoPlaylist *self, const gchar *name) {
|
||||
void koto_playlist_set_name(
|
||||
KotoPlaylist * self,
|
||||
const gchar * name
|
||||
) {
|
||||
if (name == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -760,19 +860,29 @@ void koto_playlist_set_name(KotoPlaylist *self, const gchar *name) {
|
|||
}
|
||||
}
|
||||
|
||||
void koto_playlist_set_position(KotoPlaylist *self, gint position) {
|
||||
void koto_playlist_set_position(
|
||||
KotoPlaylist * self,
|
||||
gint position
|
||||
) {
|
||||
self->current_position = position;
|
||||
}
|
||||
|
||||
void koto_playlist_set_track_as_current(KotoPlaylist *self, gchar *track_uuid) {
|
||||
void koto_playlist_set_track_as_current(
|
||||
KotoPlaylist * self,
|
||||
gchar * track_uuid
|
||||
) {
|
||||
gint position_of_track = g_queue_index(self->sorted_tracks, track_uuid); // Get the position of the UUID in our tracks
|
||||
|
||||
|
||||
if (position_of_track != -1) { // In tracks
|
||||
self->current_position = position_of_track;
|
||||
}
|
||||
}
|
||||
|
||||
void koto_playlist_set_uuid(KotoPlaylist *self, const gchar *uuid) {
|
||||
void koto_playlist_set_uuid(
|
||||
KotoPlaylist * self,
|
||||
const gchar * uuid
|
||||
) {
|
||||
if (uuid == NULL) { // No actual UUID
|
||||
return;
|
||||
}
|
||||
|
@ -784,10 +894,14 @@ void koto_playlist_set_uuid(KotoPlaylist *self, const gchar *uuid) {
|
|||
self->uuid = g_strdup(uuid); // Set the new UUID
|
||||
}
|
||||
|
||||
void koto_playlist_tracks_queue_push_to_store(gpointer data, gpointer user_data) {
|
||||
void koto_playlist_tracks_queue_push_to_store(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
) {
|
||||
gchar * track_uuid = (gchar*) data;
|
||||
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid);
|
||||
|
||||
|
||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||
return;
|
||||
}
|
||||
|
@ -800,15 +914,19 @@ void koto_playlist_unmap(KotoPlaylist *self) {
|
|||
}
|
||||
|
||||
KotoPlaylist * koto_playlist_new() {
|
||||
return g_object_new(KOTO_TYPE_PLAYLIST,
|
||||
"uuid", g_uuid_string_random(),
|
||||
return g_object_new(
|
||||
KOTO_TYPE_PLAYLIST,
|
||||
"uuid",
|
||||
g_uuid_string_random(),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
KotoPlaylist * koto_playlist_new_with_uuid(const gchar * uuid) {
|
||||
return g_object_new(KOTO_TYPE_PLAYLIST,
|
||||
"uuid", uuid,
|
||||
return g_object_new(
|
||||
KOTO_TYPE_PLAYLIST,
|
||||
"uuid",
|
||||
uuid,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
|
|
@ -49,38 +49,128 @@ GType koto_playlist_get_type(void) G_GNUC_CONST;
|
|||
**/
|
||||
|
||||
KotoPlaylist * koto_playlist_new();
|
||||
|
||||
KotoPlaylist * koto_playlist_new_with_uuid(const gchar * uuid);
|
||||
void koto_playlist_add_to_played_tracks(KotoPlaylist *self, gchar *uuid);
|
||||
void koto_playlist_add_track(KotoPlaylist *self, KotoIndexedTrack *track, gboolean current, gboolean commit_to_table);
|
||||
void koto_playlist_add_track_by_uuid(KotoPlaylist *self, gchar *uuid, gboolean current, gboolean commit_to_table);
|
||||
void koto_playlist_apply_model(KotoPlaylist *self, KotoPreferredModelType preferred_model);
|
||||
|
||||
void koto_playlist_add_to_played_tracks(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
);
|
||||
|
||||
void koto_playlist_add_track(
|
||||
KotoPlaylist * self,
|
||||
KotoIndexedTrack * track,
|
||||
gboolean current,
|
||||
gboolean commit_to_table
|
||||
);
|
||||
|
||||
void koto_playlist_add_track_by_uuid(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid,
|
||||
gboolean current,
|
||||
gboolean commit_to_table
|
||||
);
|
||||
|
||||
void koto_playlist_apply_model(
|
||||
KotoPlaylist * self,
|
||||
KotoPreferredModelType preferred_model
|
||||
);
|
||||
|
||||
void koto_playlist_commit(KotoPlaylist * self);
|
||||
void koto_playlist_commit_tracks(gpointer data, gpointer user_data);
|
||||
gint koto_playlist_compare_track_uuids(gconstpointer a, gconstpointer b);
|
||||
|
||||
void koto_playlist_commit_tracks(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
gint koto_playlist_compare_track_uuids(
|
||||
gconstpointer a,
|
||||
gconstpointer b
|
||||
);
|
||||
|
||||
gchar * koto_playlist_get_artwork(KotoPlaylist * self);
|
||||
|
||||
KotoPreferredModelType koto_playlist_get_current_model(KotoPlaylist * self);
|
||||
|
||||
guint koto_playlist_get_current_position(KotoPlaylist * self);
|
||||
|
||||
guint koto_playlist_get_length(KotoPlaylist * self);
|
||||
|
||||
gboolean koto_playlist_get_is_finalized(KotoPlaylist * self);
|
||||
|
||||
gchar * koto_playlist_get_name(KotoPlaylist * self);
|
||||
gint koto_playlist_get_position_of_track(KotoPlaylist *self, KotoIndexedTrack *track);
|
||||
|
||||
gint koto_playlist_get_position_of_track(
|
||||
KotoPlaylist * self,
|
||||
KotoIndexedTrack * track
|
||||
);
|
||||
|
||||
GListStore * koto_playlist_get_store(KotoPlaylist * self);
|
||||
|
||||
GQueue * koto_playlist_get_tracks(KotoPlaylist * self);
|
||||
|
||||
gchar * koto_playlist_get_uuid(KotoPlaylist * self);
|
||||
|
||||
gchar * koto_playlist_go_to_next(KotoPlaylist * self);
|
||||
|
||||
gchar * koto_playlist_go_to_previous(KotoPlaylist * self);
|
||||
|
||||
void koto_playlist_mark_as_finalized(KotoPlaylist * self);
|
||||
gint koto_playlist_model_sort_by_uuid(gconstpointer first_item, gconstpointer second_item, gpointer data_list);
|
||||
gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer second_item, gpointer model_ptr);
|
||||
void koto_playlist_remove_from_played_tracks(KotoPlaylist *self, gchar *uuid);
|
||||
void koto_playlist_remove_track_by_uuid(KotoPlaylist *self, gchar *uuid);
|
||||
void koto_playlist_set_artwork(KotoPlaylist *self, const gchar *path);
|
||||
|
||||
gint koto_playlist_model_sort_by_uuid(
|
||||
gconstpointer first_item,
|
||||
gconstpointer second_item,
|
||||
gpointer data_list
|
||||
);
|
||||
|
||||
gint koto_playlist_model_sort_by_track(
|
||||
gconstpointer first_item,
|
||||
gconstpointer second_item,
|
||||
gpointer model_ptr
|
||||
);
|
||||
|
||||
void koto_playlist_remove_from_played_tracks(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
);
|
||||
|
||||
void koto_playlist_remove_track_by_uuid(
|
||||
KotoPlaylist * self,
|
||||
gchar * uuid
|
||||
);
|
||||
|
||||
void koto_playlist_set_artwork(
|
||||
KotoPlaylist * self,
|
||||
const gchar * path
|
||||
);
|
||||
|
||||
void koto_playlist_save_state(KotoPlaylist * self);
|
||||
void koto_playlist_set_name(KotoPlaylist *self, const gchar *name);
|
||||
void koto_playlist_set_position(KotoPlaylist *self, gint position);
|
||||
void koto_playlist_set_track_as_current(KotoPlaylist *self, gchar *track_uuid);
|
||||
void koto_playlist_set_uuid(KotoPlaylist *self, const gchar *uuid);
|
||||
void koto_playlist_tracks_queue_push_to_store(gpointer data, gpointer user_data);
|
||||
|
||||
void koto_playlist_set_name(
|
||||
KotoPlaylist * self,
|
||||
const gchar * name
|
||||
);
|
||||
|
||||
void koto_playlist_set_position(
|
||||
KotoPlaylist * self,
|
||||
gint position
|
||||
);
|
||||
|
||||
void koto_playlist_set_track_as_current(
|
||||
KotoPlaylist * self,
|
||||
gchar * track_uuid
|
||||
);
|
||||
|
||||
void koto_playlist_set_uuid(
|
||||
KotoPlaylist * self,
|
||||
const gchar * uuid
|
||||
);
|
||||
|
||||
void koto_playlist_tracks_queue_push_to_store(
|
||||
gpointer data,
|
||||
gpointer user_data
|
||||
);
|
||||
|
||||
void koto_playlist_unmap(KotoPlaylist * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue