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": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Format",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "uncrustify",
|
||||||
|
"args": [
|
||||||
|
"-c",
|
||||||
|
"jsc.cfg",
|
||||||
|
"--no-backup",
|
||||||
|
"**/*.c",
|
||||||
|
"**/*.h"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Meson Configure and Build",
|
"label": "Meson Configure and Build",
|
||||||
"type": "shell",
|
"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
|
# 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.
|
# 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 '*'.
|
# 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.
|
# Add or remove space after pointer star '*', if followed by a word.
|
||||||
#
|
#
|
||||||
# Overrides sp_type_func.
|
# 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.
|
# Add or remove space after pointer caret '^', if followed by a word.
|
||||||
sp_after_ptr_block_caret = ignore # ignore/add/remove/force
|
sp_after_ptr_block_caret = ignore # ignore/add/remove/force
|
||||||
|
|
||||||
# Add or remove space after pointer star '*', if followed by a qualifier.
|
# 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
|
# Add or remove space after a pointer star '*', if followed by a function
|
||||||
# prototype or function definition.
|
# prototype or function definition.
|
||||||
#
|
#
|
||||||
# Overrides sp_after_ptr_star and sp_type_func.
|
# 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
|
# Add or remove space after a pointer star '*', if followed by an open
|
||||||
# parenthesis, as in 'void* (*)().
|
# parenthesis, as in 'void* (*)().
|
||||||
|
@ -1055,7 +1055,7 @@ donot_indent_func_def_close_paren = false # true/false
|
||||||
|
|
||||||
# Whether to collapse empty blocks between '{' and '}'.
|
# Whether to collapse empty blocks between '{' and '}'.
|
||||||
# If true, overrides nl_inside_empty_func
|
# 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 };'.
|
# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'.
|
||||||
nl_assign_leave_one_liners = false # true/false
|
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
|
nl_func_call_paren_empty = ignore # ignore/add/remove/force
|
||||||
|
|
||||||
# Add or remove newline after '(' in a function declaration.
|
# 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.
|
# 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.
|
# Overrides nl_func_decl_start when there is only one parameter.
|
||||||
nl_func_decl_start_single = remove # ignore/add/remove/force
|
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
|
nl_func_def_start_multi_line = true # true/false
|
||||||
|
|
||||||
# Add or remove newline after each ',' in a function declaration.
|
# 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.
|
# 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.
|
# 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 '('
|
# 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.
|
# 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
|
nl_func_def_args_multi_line = true # true/false
|
||||||
|
|
||||||
# Add or remove newline before the ')' in a function declaration.
|
# 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.
|
# 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.
|
# Overrides nl_func_decl_end when there is only one parameter.
|
||||||
nl_func_decl_end_single = remove # ignore/add/remove/force
|
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 ')'
|
# 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.
|
# 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 ')'
|
# 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.
|
# 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
|
nl_return_expr = remove # ignore/add/remove/force
|
||||||
|
|
||||||
# Whether to add a newline after semicolons, except in 'for' statements.
|
# 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
|
# Whether to add a newline after the type in an unnamed temporary
|
||||||
# direct-list-initialization.
|
# direct-list-initialization.
|
||||||
|
@ -1643,7 +1643,7 @@ nl_before_func_class_proto = 0 # unsigned number
|
||||||
nl_before_func_class_def = 0 # unsigned number
|
nl_before_func_class_def = 0 # unsigned number
|
||||||
|
|
||||||
# The number of newlines after a function prototype.
|
# 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
|
# The number of newlines after a function prototype, if not followed by
|
||||||
# another function prototype.
|
# another function prototype.
|
||||||
|
@ -1734,13 +1734,13 @@ nl_after_multiline_comment = false # true/false
|
||||||
nl_after_label_colon = false # true/false
|
nl_after_label_colon = false # true/false
|
||||||
|
|
||||||
# The number of newlines after '}' or ';' of a struct/enum/union definition.
|
# 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.
|
# The number of newlines before a class definition.
|
||||||
nl_before_class = 0 # unsigned number
|
nl_before_class = 0 # unsigned number
|
||||||
|
|
||||||
# The number of newlines after '}' or ';' of a class definition.
|
# 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.
|
# The number of newlines before a namespace.
|
||||||
nl_before_namespace = 0 # unsigned number
|
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.
|
# Add or remove braces on a single-line 'for' statement.
|
||||||
mod_full_brace_for = ignore # ignore/add/remove/force
|
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
|
# Add or remove braces on a single-line 'if' statement. Braces will not be
|
||||||
# removed if the braced statement contains an 'else'.
|
# removed if the braced statement contains an 'else'.
|
||||||
mod_full_brace_if = ignore # ignore/add/remove/force
|
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
|
mod_full_brace_nl_block_rem_mlcond = false # true/false
|
||||||
|
|
||||||
# Add or remove unnecessary parenthesis on 'return' statement.
|
# Add or remove unnecessary parenthesis on 'return' statement.
|
||||||
mod_paren_on_return = ignore # ignore/add/remove/force
|
mod_paren_on_return = ignore # ignore/add/remove/force´
|
||||||
|
|
||||||
# (Pawn) Whether to change optional semicolons to real semicolons.
|
|
||||||
mod_pawn_semicolon = false # true/false
|
|
||||||
|
|
||||||
# Whether to fully parenthesize Boolean expressions in 'while' and 'if'
|
# Whether to fully parenthesize Boolean expressions in 'while' and 'if'
|
||||||
# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'.
|
# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'.
|
||||||
|
|
|
@ -26,52 +26,55 @@
|
||||||
#include "../koto-utils.h"
|
#include "../koto-utils.h"
|
||||||
#include "../koto-window.h"
|
#include "../koto-window.h"
|
||||||
|
|
||||||
extern KotoAddRemoveTrackPopover *koto_add_remove_track_popup;
|
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup;
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoPageMusicLocal *music_local_page;
|
extern KotoPageMusicLocal * music_local_page;
|
||||||
extern KotoPlaybackEngine *playback_engine;
|
extern KotoPlaybackEngine * playback_engine;
|
||||||
extern KotoWindow *main_window;
|
extern KotoWindow * main_window;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIGNAL_CLOSED,
|
SIGNAL_CLOSED,
|
||||||
N_SIGNALS
|
N_SIGNALS
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint actionbar_signals[N_SIGNALS] = { 0 };
|
static guint actionbar_signals[N_SIGNALS] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoActionBar {
|
struct _KotoActionBar {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
GtkActionBar *main;
|
GtkActionBar * main;
|
||||||
|
|
||||||
GtkWidget *center_box_content;
|
GtkWidget * center_box_content;
|
||||||
GtkWidget *start_box_content;
|
GtkWidget * start_box_content;
|
||||||
GtkWidget *stop_box_content;
|
GtkWidget * stop_box_content;
|
||||||
|
|
||||||
KotoButton *close_button;
|
KotoButton * close_button;
|
||||||
GtkWidget *go_to_artist;
|
GtkWidget * go_to_artist;
|
||||||
GtkWidget *playlists;
|
GtkWidget * playlists;
|
||||||
GtkWidget *play_track;
|
GtkWidget * play_track;
|
||||||
GtkWidget *remove_from_playlist;
|
GtkWidget * remove_from_playlist;
|
||||||
|
|
||||||
GList *current_list;
|
GList * current_list;
|
||||||
gchar *current_album_uuid;
|
gchar * current_album_uuid;
|
||||||
gchar *current_playlist_uuid;
|
gchar * current_playlist_uuid;
|
||||||
KotoActionBarRelative relative;
|
KotoActionBarRelative relative;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoActionBarClass {
|
struct _KotoActionBarClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (* closed) (KotoActionBar *self);
|
void (* closed) (KotoActionBar * self);
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoActionBar, koto_action_bar, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoActionBar, koto_action_bar, G_TYPE_OBJECT);
|
||||||
|
|
||||||
KotoActionBar* action_bar;
|
KotoActionBar* action_bar;
|
||||||
|
|
||||||
static void koto_action_bar_class_init(KotoActionBarClass *c) {
|
static void koto_action_bar_class_init(KotoActionBarClass * c) {
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS(c);
|
GObjectClass * gobject_class = G_OBJECT_CLASS(c);
|
||||||
|
|
||||||
|
|
||||||
actionbar_signals[SIGNAL_CLOSED] = g_signal_new(
|
actionbar_signals[SIGNAL_CLOSED] = g_signal_new(
|
||||||
"closed",
|
"closed",
|
||||||
|
@ -86,7 +89,7 @@ static void koto_action_bar_class_init(KotoActionBarClass *c) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_action_bar_init(KotoActionBar *self) {
|
static void koto_action_bar_init(KotoActionBar * self) {
|
||||||
self->main = GTK_ACTION_BAR(gtk_action_bar_new()); // Create a new action bar
|
self->main = GTK_ACTION_BAR(gtk_action_bar_new()); // Create a new action bar
|
||||||
self->current_list = NULL;
|
self->current_list = NULL;
|
||||||
|
|
||||||
|
@ -135,7 +138,7 @@ static void koto_action_bar_init(KotoActionBar *self) {
|
||||||
koto_action_bar_toggle_reveal(self, FALSE); // Hide by default
|
koto_action_bar_toggle_reveal(self, FALSE); // Hide by default
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_action_bar_close(KotoActionBar *self) {
|
void koto_action_bar_close(KotoActionBar * self) {
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +154,7 @@ void koto_action_bar_close(KotoActionBar *self) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkActionBar* koto_action_bar_get_main(KotoActionBar *self) {
|
GtkActionBar * koto_action_bar_get_main(KotoActionBar * self) {
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -159,14 +162,27 @@ GtkActionBar* koto_action_bar_get_main(KotoActionBar *self) {
|
||||||
return self->main;
|
return self->main;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_action_bar_handle_close_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_action_bar_handle_close_button_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
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);
|
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;
|
(void) button;
|
||||||
KotoActionBar *self = data;
|
KotoActionBar * self = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -176,13 +192,16 @@ void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpoin
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack *selected_track = g_list_nth_data(self->current_list, 0); // Get the first item
|
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
|
if (!KOTO_IS_INDEXED_TRACK(selected_track)) { // Not a track
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artist_uuid = NULL;
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
selected_track,
|
selected_track,
|
||||||
"artist-uuid",
|
"artist-uuid",
|
||||||
|
@ -190,13 +209,17 @@ void koto_action_bar_handle_go_to_artist_button_clicked(GtkButton *button, gpoin
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
koto_page_music_local_go_to_artist_by_uuid(music_local_page, artist_uuid); // Go to the artist
|
koto_page_music_local_go_to_artist_by_uuid(music_local_page, artist_uuid); // Go to the artist
|
||||||
koto_window_go_to_page(main_window, "music.local"); // Navigate to the local music stack so we can see the substack page
|
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
|
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;
|
(void) button;
|
||||||
KotoActionBar *self = data;
|
KotoActionBar * self = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -211,9 +234,13 @@ void koto_action_bar_handle_playlists_button_clicked(GtkButton *button, gpointer
|
||||||
gtk_widget_show(GTK_WIDGET(koto_add_remove_track_popup));
|
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;
|
(void) button;
|
||||||
KotoActionBar *self = data;
|
KotoActionBar * self = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -223,7 +250,8 @@ void koto_action_bar_handle_play_track_button_clicked(GtkButton *button, gpointe
|
||||||
goto doclose;
|
goto doclose;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack *track = g_list_nth_data(self->current_list, 0); // Get the first track
|
KotoIndexedTrack * track = g_list_nth_data(self->current_list, 0); // Get the first track
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||||
goto doclose;
|
goto doclose;
|
||||||
|
@ -235,9 +263,13 @@ doclose:
|
||||||
koto_action_bar_close(self);
|
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;
|
(void) button;
|
||||||
KotoActionBar *self = data;
|
KotoActionBar * self = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_ACTION_BAR(self)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -251,15 +283,18 @@ void koto_action_bar_handle_remove_from_playlist_button_clicked(GtkButton *butto
|
||||||
goto doclose;
|
goto doclose;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist *playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->current_playlist_uuid);
|
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->current_playlist_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Not a playlist
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Not a playlist
|
||||||
goto doclose;
|
goto doclose;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *cur_list;
|
GList * cur_list;
|
||||||
|
|
||||||
|
|
||||||
for (cur_list = self->current_list; cur_list != NULL; cur_list = cur_list->next) { // For each KotoIndexedTrack
|
for (cur_list = self->current_list; cur_list != NULL; cur_list = cur_list->next) { // For each KotoIndexedTrack
|
||||||
KotoIndexedTrack *track = cur_list->data;
|
KotoIndexedTrack * track = cur_list->data;
|
||||||
koto_playlist_remove_track_by_uuid(playlist, koto_indexed_track_get_uuid(track)); // Remove this track
|
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);
|
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)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
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));
|
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)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -318,13 +361,18 @@ void koto_action_bar_set_tracks_in_playlist_selection(KotoActionBar *self, gchar
|
||||||
self->current_list = g_list_copy(tracks);
|
self->current_list = g_list_copy(tracks);
|
||||||
|
|
||||||
gboolean single_selected = g_list_length(tracks) == 1;
|
gboolean single_selected = g_list_length(tracks) == 1;
|
||||||
|
|
||||||
|
|
||||||
koto_action_bar_toggle_go_to_artist_visibility(self, single_selected);
|
koto_action_bar_toggle_go_to_artist_visibility(self, single_selected);
|
||||||
koto_action_bar_toggle_play_button_visibility(self, single_selected);
|
koto_action_bar_toggle_play_button_visibility(self, single_selected);
|
||||||
gtk_widget_hide(GTK_WIDGET(self->playlists));
|
gtk_widget_hide(GTK_WIDGET(self->playlists));
|
||||||
gtk_widget_show(GTK_WIDGET(self->remove_from_playlist));
|
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)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
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));
|
(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)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
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));
|
(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)) {
|
if (!KOTO_IS_ACTION_BAR(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +402,7 @@ void koto_action_bar_toggle_reveal(KotoActionBar *self, gboolean state) {
|
||||||
gtk_action_bar_set_revealed(self->main, state);
|
gtk_action_bar_set_revealed(self->main, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoActionBar* koto_action_bar_new() {
|
KotoActionBar * koto_action_bar_new() {
|
||||||
return g_object_new(
|
return g_object_new(
|
||||||
KOTO_TYPE_ACTION_BAR,
|
KOTO_TYPE_ACTION_BAR,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -39,20 +39,67 @@ GType koto_action_bar_get_type(void) G_GNUC_CONST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action Bar Functions
|
* Action Bar Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoActionBar* koto_action_bar_new(void);
|
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_close(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);
|
GtkActionBar * koto_action_bar_get_main(KotoActionBar * self);
|
||||||
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_close_button_clicked(
|
||||||
void koto_action_bar_handle_remove_from_playlist_button_clicked(GtkButton *button, gpointer data);
|
GtkGestureClick * gesture,
|
||||||
void koto_action_bar_set_tracks_in_album_selection(KotoActionBar *self, gchar *album_uuid, GList *tracks);
|
int n_press,
|
||||||
void koto_action_bar_set_tracks_in_playlist_selection(KotoActionBar *self, gchar *playlist_uuid, GList *tracks);
|
double x,
|
||||||
void koto_action_bar_toggle_go_to_artist_visibility(KotoActionBar *self, gboolean visible);
|
double y,
|
||||||
void koto_action_bar_toggle_play_button_visibility(KotoActionBar *self, gboolean visible);
|
gpointer data
|
||||||
void koto_action_bar_toggle_reveal(KotoActionBar *self, gboolean state);
|
);
|
||||||
|
|
||||||
|
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
|
G_END_DECLS
|
|
@ -24,10 +24,10 @@
|
||||||
struct _KotoCoverArtButton {
|
struct _KotoCoverArtButton {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
GtkWidget *art;
|
GtkWidget * art;
|
||||||
GtkWidget *main;
|
GtkWidget * main;
|
||||||
GtkWidget *revealer;
|
GtkWidget * revealer;
|
||||||
KotoButton *play_pause_button;
|
KotoButton * play_pause_button;
|
||||||
|
|
||||||
guint height;
|
guint height;
|
||||||
guint width;
|
guint width;
|
||||||
|
@ -43,12 +43,27 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
static void koto_cover_art_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
NULL,
|
||||||
static void koto_cover_art_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
};
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_cover_art_button_class_init(KotoCoverArtButtonClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->get_property = koto_cover_art_button_get_property;
|
gobject_class->get_property = koto_cover_art_button_get_property;
|
||||||
gobject_class->set_property = koto_cover_art_button_set_property;
|
gobject_class->set_property = koto_cover_art_button_set_property;
|
||||||
|
@ -60,7 +75,7 @@ static void koto_cover_art_button_class_init(KotoCoverArtButtonClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT,
|
G_MAXUINT,
|
||||||
0,
|
0,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_WRITABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_DESIRED_WIDTH] = g_param_spec_uint(
|
props[PROP_DESIRED_WIDTH] = g_param_spec_uint(
|
||||||
|
@ -70,7 +85,7 @@ static void koto_cover_art_button_class_init(KotoCoverArtButtonClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT,
|
G_MAXUINT,
|
||||||
0,
|
0,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_WRITABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ART_PATH] = g_param_spec_string(
|
props[PROP_ART_PATH] = g_param_spec_string(
|
||||||
|
@ -78,20 +93,22 @@ static void koto_cover_art_button_class_init(KotoCoverArtButtonClass *c) {
|
||||||
"Path to art",
|
"Path to art",
|
||||||
"Path to art",
|
"Path to art",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_WRITABLE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_cover_art_button_init(KotoCoverArtButton *self) {
|
static void koto_cover_art_button_init(KotoCoverArtButton * self) {
|
||||||
self->main = gtk_overlay_new(); // Create our overlay container
|
self->main = gtk_overlay_new(); // Create our overlay container
|
||||||
gtk_widget_add_css_class(self->main, "cover-art-button");
|
gtk_widget_add_css_class(self->main, "cover-art-button");
|
||||||
self->revealer = gtk_revealer_new(); // Create a new revealer
|
self->revealer = gtk_revealer_new(); // Create a new revealer
|
||||||
gtk_revealer_set_transition_type(GTK_REVEALER(self->revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
|
gtk_revealer_set_transition_type(GTK_REVEALER(self->revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
|
||||||
gtk_revealer_set_transition_duration(GTK_REVEALER(self->revealer), 400);
|
gtk_revealer_set_transition_duration(GTK_REVEALER(self->revealer), 400);
|
||||||
|
|
||||||
GtkWidget *controls = gtk_center_box_new(); // Create a center box for the controls
|
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);
|
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));
|
gtk_center_box_set_center_widget(GTK_CENTER_BOX(controls), GTK_WIDGET(self->play_pause_button));
|
||||||
|
|
||||||
|
@ -99,13 +116,20 @@ static void koto_cover_art_button_init(KotoCoverArtButton *self) {
|
||||||
koto_cover_art_button_hide_overlay_controls(NULL, self); // Hide by default
|
koto_cover_art_button_hide_overlay_controls(NULL, self); // Hide by default
|
||||||
gtk_overlay_add_overlay(GTK_OVERLAY(self->main), self->revealer); // Add our revealer as the overlay
|
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
|
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, "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);
|
g_signal_connect(motion_controller, "leave", G_CALLBACK(koto_cover_art_button_hide_overlay_controls), self);
|
||||||
gtk_widget_add_controller(self->main, motion_controller);
|
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;
|
(void) val;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
|
@ -115,8 +139,14 @@ 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(
|
||||||
KotoCoverArtButton *self = KOTO_COVER_ART_BUTTON(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoCoverArtButton * self = KOTO_COVER_ART_BUTTON(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ART_PATH:
|
case PROP_ART_PATH:
|
||||||
|
@ -134,13 +164,18 @@ 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;
|
(void) controller;
|
||||||
KotoCoverArtButton* self = data;
|
KotoCoverArtButton* self = data;
|
||||||
|
|
||||||
|
|
||||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), FALSE);
|
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoButton* koto_cover_art_button_get_button(KotoCoverArtButton *self) {
|
KotoButton * koto_cover_art_button_get_button(KotoCoverArtButton * self) {
|
||||||
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -148,7 +183,7 @@ KotoButton* koto_cover_art_button_get_button(KotoCoverArtButton *self) {
|
||||||
return self->play_pause_button;
|
return self->play_pause_button;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_cover_art_button_get_main(KotoCoverArtButton *self) {
|
GtkWidget * koto_cover_art_button_get_main(KotoCoverArtButton * self) {
|
||||||
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -156,13 +191,17 @@ GtkWidget* koto_cover_art_button_get_main(KotoCoverArtButton *self) {
|
||||||
return self->main;
|
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)) {
|
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean defined_artwork = koto_utils_is_string_valid(art_path);
|
gboolean defined_artwork = koto_utils_is_string_valid(art_path);
|
||||||
|
|
||||||
|
|
||||||
if (GTK_IS_IMAGE(self->art)) { // Already have an image
|
if (GTK_IS_IMAGE(self->art)) { // Already have an image
|
||||||
if (!defined_artwork) { // No art path or empty string
|
if (!defined_artwork) { // No art path or empty string
|
||||||
gtk_image_set_from_icon_name(GTK_IMAGE(self->art), "audio-x-generic-symbolic");
|
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)) {
|
if (!KOTO_IS_COVER_ART_BUTTON(self)) {
|
||||||
return;
|
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;
|
(void) controller;
|
||||||
KotoCoverArtButton* self = data;
|
KotoCoverArtButton* self = data;
|
||||||
|
|
||||||
|
|
||||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), TRUE);
|
gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCoverArtButton* koto_cover_art_button_new(guint height, guint width, gchar *art_path) {
|
KotoCoverArtButton * koto_cover_art_button_new(
|
||||||
return g_object_new(KOTO_TYPE_COVER_ART_BUTTON,
|
guint height,
|
||||||
|
guint width,
|
||||||
|
gchar * art_path
|
||||||
|
) {
|
||||||
|
return g_object_new(
|
||||||
|
KOTO_TYPE_COVER_ART_BUTTON,
|
||||||
"desired-height",
|
"desired-height",
|
||||||
height,
|
height,
|
||||||
"desired-width",
|
"desired-width",
|
||||||
|
|
|
@ -27,14 +27,37 @@ G_DECLARE_FINAL_TYPE(KotoCoverArtButton, koto_cover_art_button, KOTO, COVER_ART_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cover Art Functions
|
* Cover Art Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoCoverArtButton* koto_cover_art_button_new(guint height, guint width, gchar *art_path);
|
KotoCoverArtButton * koto_cover_art_button_new(
|
||||||
KotoButton* koto_cover_art_button_get_button(KotoCoverArtButton *self);
|
guint height,
|
||||||
GtkWidget* koto_cover_art_button_get_main(KotoCoverArtButton *self);
|
guint width,
|
||||||
void koto_cover_art_button_hide_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
gchar * art_path
|
||||||
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);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
|
@ -30,36 +30,64 @@ enum {
|
||||||
N_SIGNALS
|
N_SIGNALS
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint cartographer_signals[N_SIGNALS] = { 0 };
|
static guint cartographer_signals[N_SIGNALS] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoCartographer {
|
struct _KotoCartographer {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
GHashTable *albums;
|
GHashTable * albums;
|
||||||
GHashTable *artists;
|
GHashTable * artists;
|
||||||
GHashTable *playlists;
|
GHashTable * playlists;
|
||||||
GHashTable *tracks;
|
GHashTable * tracks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoCartographerClass {
|
struct _KotoCartographerClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (* album_added) (KotoCartographer *cartographer, KotoIndexedAlbum *album);
|
void (* album_added) (
|
||||||
void (* album_removed) (KotoCartographer *cartographer, KotoIndexedAlbum *album);
|
KotoCartographer * cartographer,
|
||||||
void (* artist_added) (KotoCartographer *cartographer, KotoIndexedArtist *artist);
|
KotoIndexedAlbum * album
|
||||||
void (* artist_removed) (KotoCartographer *cartographer, KotoIndexedArtist *artist);
|
);
|
||||||
void (* playlist_added) (KotoCartographer *cartographer, KotoPlaylist *playlist);
|
void (* album_removed) (
|
||||||
void (* playlist_removed) (KotoCartographer *cartographer, KotoPlaylist *playlist);
|
KotoCartographer * cartographer,
|
||||||
void (* track_added) (KotoCartographer *cartographer, KotoIndexedTrack *track);
|
KotoIndexedAlbum * album
|
||||||
void (* track_removed) (KotoCartographer *cartographer, KotoIndexedTrack *track);
|
);
|
||||||
|
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);
|
G_DEFINE_TYPE(KotoCartographer, koto_cartographer, G_TYPE_OBJECT);
|
||||||
|
|
||||||
KotoCartographer *koto_maps = NULL;
|
KotoCartographer * koto_maps = NULL;
|
||||||
|
|
||||||
|
static void koto_cartographer_class_init(KotoCartographerClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
|
|
||||||
static void koto_cartographer_class_init(KotoCartographerClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
|
|
||||||
cartographer_signals[SIGNAL_ALBUM_ADDED] = g_signal_new(
|
cartographer_signals[SIGNAL_ALBUM_ADDED] = g_signal_new(
|
||||||
|
@ -167,15 +195,20 @@ static void koto_cartographer_class_init(KotoCartographerClass *c) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_cartographer_init(KotoCartographer *self) {
|
static void koto_cartographer_init(KotoCartographer * self) {
|
||||||
self->albums = g_hash_table_new(g_str_hash, g_str_equal);
|
self->albums = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
self->artists = g_hash_table_new(g_str_hash, g_str_equal);
|
self->artists = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
self->playlists = g_hash_table_new(g_str_hash, g_str_equal);
|
self->playlists = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
self->tracks = g_hash_table_new(g_str_hash, g_str_equal);
|
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(
|
||||||
gchar *album_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedAlbum * album
|
||||||
|
) {
|
||||||
|
gchar * album_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(album, "uuid", &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
|
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(
|
||||||
gchar *artist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedArtist * artist
|
||||||
|
) {
|
||||||
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "uuid", &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
|
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(
|
||||||
gchar *playlist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoPlaylist * playlist
|
||||||
|
) {
|
||||||
|
gchar * playlist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(playlist, "uuid", &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
|
if ((playlist_uuid == NULL) || koto_cartographer_has_playlist_by_uuid(self, playlist_uuid)) { // Have the playlist or invalid UUID
|
||||||
|
@ -227,8 +270,11 @@ 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(
|
||||||
g_signal_emit(
|
KotoPlaylist * playlist,
|
||||||
|
KotoCartographer * self
|
||||||
|
) {
|
||||||
|
g_signal_emit(
|
||||||
self,
|
self,
|
||||||
cartographer_signals[SIGNAL_PLAYLIST_ADDED],
|
cartographer_signals[SIGNAL_PLAYLIST_ADDED],
|
||||||
0,
|
0,
|
||||||
|
@ -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(
|
||||||
gchar *track_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedTrack * track
|
||||||
|
) {
|
||||||
|
gchar * track_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "uuid", &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
|
if ((track_uuid == NULL) || koto_cartographer_has_track_by_uuid(self, track_uuid)) { // Have the track or invalid UUID
|
||||||
|
@ -254,33 +305,53 @@ 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);
|
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);
|
return g_hash_table_lookup(self->artists, artist_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
GHashTable* koto_cartographer_get_playlists(KotoCartographer *self) {
|
GHashTable * koto_cartographer_get_playlists(KotoCartographer * self) {
|
||||||
return self->playlists;
|
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);
|
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);
|
return g_hash_table_lookup(self->tracks, track_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_cartographer_has_album(KotoCartographer *self, KotoIndexedAlbum *album) {
|
gboolean koto_cartographer_has_album(
|
||||||
gchar *album_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedAlbum * album
|
||||||
|
) {
|
||||||
|
gchar * album_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||||
return koto_cartographer_has_album_by_uuid(self, album_uuid);
|
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) {
|
if (album_uuid == NULL) {
|
||||||
return FALSE;
|
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);
|
return g_hash_table_contains(self->albums, album_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_cartographer_has_artist(KotoCartographer *self, KotoIndexedArtist *artist) {
|
gboolean koto_cartographer_has_artist(
|
||||||
gchar *artist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedArtist * artist
|
||||||
|
) {
|
||||||
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||||
return koto_cartographer_has_artist_by_uuid(self, artist_uuid);
|
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) {
|
if (artist_uuid == NULL) {
|
||||||
return FALSE;
|
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);
|
return g_hash_table_contains(self->artists, artist_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_cartographer_has_playlist(KotoCartographer *self, KotoPlaylist *playlist) {
|
gboolean koto_cartographer_has_playlist(
|
||||||
gchar *playlist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoPlaylist * playlist
|
||||||
|
) {
|
||||||
|
gchar * playlist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
||||||
return koto_cartographer_has_playlist_by_uuid(self, playlist_uuid);
|
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) {
|
if (playlist_uuid == NULL) {
|
||||||
return FALSE;
|
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);
|
return g_hash_table_contains(self->playlists, playlist_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_cartographer_has_track(KotoCartographer *self, KotoIndexedTrack *track) {
|
gboolean koto_cartographer_has_track(
|
||||||
gchar *track_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedTrack * track
|
||||||
|
) {
|
||||||
|
gchar * track_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||||
return koto_cartographer_has_album_by_uuid(self, track_uuid);
|
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) {
|
if (track_uuid == NULL) {
|
||||||
return FALSE;
|
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);
|
return g_hash_table_contains(self->tracks, track_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_cartographer_remove_album(KotoCartographer *self, KotoIndexedAlbum *album) {
|
void koto_cartographer_remove_album(
|
||||||
gchar *album_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedAlbum * album
|
||||||
|
) {
|
||||||
|
gchar * album_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||||
koto_cartographer_remove_album_by_uuid(self, album_uuid);
|
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) {
|
if (album_uuid != NULL) {
|
||||||
g_hash_table_remove(self->albums, album_uuid);
|
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(
|
||||||
gchar *artist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedArtist * artist
|
||||||
|
) {
|
||||||
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||||
koto_cartographer_remove_artist_by_uuid(self, artist_uuid);
|
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) {
|
if (artist_uuid == NULL) {
|
||||||
g_hash_table_remove(self->artists, artist_uuid);
|
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(
|
||||||
gchar *playlist_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoPlaylist * playlist
|
||||||
|
) {
|
||||||
|
gchar * playlist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
g_object_get(playlist, "uuid", &playlist_uuid, NULL);
|
||||||
koto_cartographer_remove_playlist_by_uuid(self, playlist_uuid);
|
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) {
|
if (playlist_uuid != NULL) {
|
||||||
g_hash_table_remove(self->playlists, playlist_uuid);
|
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(
|
||||||
gchar *track_uuid = NULL;
|
KotoCartographer * self,
|
||||||
|
KotoIndexedTrack * track
|
||||||
|
) {
|
||||||
|
gchar * track_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||||
koto_cartographer_remove_track_by_uuid(self, track_uuid);
|
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) {
|
if (track_uuid != NULL) {
|
||||||
g_hash_table_remove(self->tracks, track_uuid);
|
g_hash_table_remove(self->tracks, track_uuid);
|
||||||
|
|
||||||
|
@ -406,6 +533,6 @@ void koto_cartographer_remove_track_by_uuid(KotoCartographer *self, gchar* track
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCartographer* koto_cartographer_new() {
|
KotoCartographer * koto_cartographer_new() {
|
||||||
return g_object_new(KOTO_TYPE_CARTOGRAPHER, NULL);
|
return g_object_new(KOTO_TYPE_CARTOGRAPHER, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_CARTOGRAPHER koto_cartographer_get_type()
|
#define KOTO_TYPE_CARTOGRAPHER koto_cartographer_get_type()
|
||||||
|
|
||||||
|
@ -36,39 +36,135 @@ GType koto_cartographer_get_type(void) G_GNUC_CONST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cartographer Functions
|
* Cartographer Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoCartographer* koto_cartographer_new();
|
KotoCartographer * koto_cartographer_new();
|
||||||
|
|
||||||
void koto_cartographer_add_album(KotoCartographer *self, KotoIndexedAlbum *album);
|
void koto_cartographer_add_album(
|
||||||
void koto_cartographer_add_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
KotoCartographer * self,
|
||||||
void koto_cartographer_add_playlist(KotoCartographer *self, KotoPlaylist *playlist);
|
KotoIndexedAlbum * album
|
||||||
void koto_cartographer_add_track(KotoCartographer *self, KotoIndexedTrack *track);
|
);
|
||||||
|
|
||||||
void koto_cartographer_emit_playlist_added(KotoPlaylist *playlist, KotoCartographer *self);
|
void koto_cartographer_add_artist(
|
||||||
|
KotoCartographer * self,
|
||||||
|
KotoIndexedArtist * artist
|
||||||
|
);
|
||||||
|
|
||||||
KotoIndexedAlbum* koto_cartographer_get_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
void koto_cartographer_add_playlist(
|
||||||
KotoIndexedArtist* koto_cartographer_get_artist_by_uuid(KotoCartographer *self, gchar* artist_uuid);
|
KotoCartographer * self,
|
||||||
KotoPlaylist* koto_cartographer_get_playlist_by_uuid(KotoCartographer *self, gchar* playlist_uuid);
|
KotoPlaylist * playlist
|
||||||
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);
|
void koto_cartographer_add_track(
|
||||||
gboolean koto_cartographer_has_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
KotoCartographer * self,
|
||||||
gboolean koto_cartographer_has_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
KotoIndexedTrack * track
|
||||||
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_emit_playlist_added(
|
||||||
void koto_cartographer_remove_album_by_uuid(KotoCartographer *self, gchar* album_uuid);
|
KotoPlaylist * playlist,
|
||||||
void koto_cartographer_remove_artist(KotoCartographer *self, KotoIndexedArtist *artist);
|
KotoCartographer * self
|
||||||
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);
|
KotoIndexedAlbum * koto_cartographer_get_album_by_uuid(
|
||||||
void koto_cartographer_remove_track(KotoCartographer *self, KotoIndexedTrack *track);
|
KotoCartographer * self,
|
||||||
void koto_cartographer_remove_track_by_uuid(KotoCartographer *self, gchar* track_uuid);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
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
|
G_END_DECLS
|
||||||
|
|
36
src/db/db.c
36
src/db/db.c
|
@ -26,8 +26,8 @@ int KOTO_DB_SUCCESS = 0;
|
||||||
int KOTO_DB_NEW = 1;
|
int KOTO_DB_NEW = 1;
|
||||||
int KOTO_DB_FAIL = 2;
|
int KOTO_DB_FAIL = 2;
|
||||||
|
|
||||||
sqlite3 *koto_db = NULL;
|
sqlite3 * koto_db = NULL;
|
||||||
gchar *db_filepath = NULL;
|
gchar * db_filepath = NULL;
|
||||||
gboolean created_new_db = FALSE;
|
gboolean created_new_db = FALSE;
|
||||||
|
|
||||||
void close_db() {
|
void close_db() {
|
||||||
|
@ -35,14 +35,15 @@ void close_db() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_db_tables() {
|
int create_db_tables() {
|
||||||
char *tables_creation_queries = "CREATE TABLE IF NOT EXISTS artists(id string UNIQUE PRIMARY KEY, path string, type int, name string, art_path string);"
|
char * tables_creation_queries = "CREATE TABLE IF NOT EXISTS artists(id string UNIQUE PRIMARY KEY, path string, type int, name string, art_path string);"
|
||||||
"CREATE TABLE IF NOT EXISTS albums(id string UNIQUE PRIMARY KEY, path string, artist_id string, name string, art_path string, FOREIGN KEY(artist_id) REFERENCES artists(id) ON DELETE CASCADE);"
|
"CREATE TABLE IF NOT EXISTS albums(id string UNIQUE PRIMARY KEY, path string, artist_id string, name string, art_path string, FOREIGN KEY(artist_id) REFERENCES artists(id) ON DELETE CASCADE);"
|
||||||
"CREATE TABLE IF NOT EXISTS tracks(id string UNIQUE PRIMARY KEY, path string, type int, artist_id string, album_id string, file_name string, name string, disc int, position int, FOREIGN KEY(artist_id) REFERENCES artists(id) ON DELETE CASCADE);"
|
"CREATE TABLE IF NOT EXISTS tracks(id string UNIQUE PRIMARY KEY, path string, type int, artist_id string, album_id string, file_name string, name string, disc int, position int, FOREIGN KEY(artist_id) REFERENCES artists(id) ON DELETE CASCADE);"
|
||||||
"CREATE TABLE IF NOT EXISTS playlist_meta(id string UNIQUE PRIMARY KEY, name string, art_path string, preferred_model int);"
|
"CREATE TABLE IF NOT EXISTS playlist_meta(id string UNIQUE PRIMARY KEY, name string, art_path string, preferred_model int);"
|
||||||
"CREATE TABLE IF NOT EXISTS playlist_tracks(position INTEGER PRIMARY KEY AUTOINCREMENT, playlist_id string, track_id string, current int, FOREIGN KEY(playlist_id) REFERENCES playlist_meta(id), FOREIGN KEY(track_id) REFERENCES tracks(id) ON DELETE CASCADE);";
|
"CREATE TABLE IF NOT EXISTS playlist_tracks(position INTEGER PRIMARY KEY AUTOINCREMENT, playlist_id string, track_id string, current int, FOREIGN KEY(playlist_id) REFERENCES playlist_meta(id), FOREIGN KEY(track_id) REFERENCES tracks(id) ON DELETE CASCADE);";
|
||||||
|
|
||||||
|
gchar * create_tables_errmsg = NULL;
|
||||||
|
int rc = sqlite3_exec(koto_db, tables_creation_queries, 0, 0, &create_tables_errmsg);
|
||||||
|
|
||||||
gchar *create_tables_errmsg = NULL;
|
|
||||||
int rc = sqlite3_exec(koto_db, tables_creation_queries, 0,0, &create_tables_errmsg);
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_critical("Failed to create required tables: %s", create_tables_errmsg);
|
g_critical("Failed to create required tables: %s", create_tables_errmsg);
|
||||||
|
@ -52,9 +53,10 @@ int create_db_tables() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int enable_foreign_keys() {
|
int enable_foreign_keys() {
|
||||||
gchar *enable_foreign_keys_err = NULL;
|
gchar * enable_foreign_keys_err = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, "PRAGMA foreign_keys = ON;", 0, 0, &enable_foreign_keys_err);
|
int rc = sqlite3_exec(koto_db, "PRAGMA foreign_keys = ON;", 0, 0, &enable_foreign_keys_err);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -63,10 +65,10 @@ int enable_foreign_keys() {
|
||||||
return (rc == SQLITE_OK) ? KOTO_DB_SUCCESS : KOTO_DB_FAIL;
|
return (rc == SQLITE_OK) ? KOTO_DB_SUCCESS : KOTO_DB_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* get_db_path() {
|
gchar * get_db_path() {
|
||||||
if (db_filepath == NULL) {
|
if (db_filepath == NULL) {
|
||||||
const gchar *data_home = g_get_user_data_dir();
|
const gchar * data_home = g_get_user_data_dir();
|
||||||
gchar *data_dir = g_build_path(G_DIR_SEPARATOR_S, data_home, "com.github.joshstrobl.koto", NULL);
|
gchar * data_dir = g_build_path(G_DIR_SEPARATOR_S, data_home, "com.github.joshstrobl.koto", NULL);
|
||||||
db_filepath = g_build_filename(g_strdup(data_dir), "db", NULL); // Build out our path using XDG_DATA_HOME (e.g. .local/share/) + our namespace + db as the file name
|
db_filepath = g_build_filename(g_strdup(data_dir), "db", NULL); // Build out our path using XDG_DATA_HOME (e.g. .local/share/) + our namespace + db as the file name
|
||||||
g_free(data_dir);
|
g_free(data_dir);
|
||||||
}
|
}
|
||||||
|
@ -78,15 +80,17 @@ int have_existing_db() {
|
||||||
struct stat db_stat;
|
struct stat db_stat;
|
||||||
int success = stat(get_db_path(), &db_stat);
|
int success = stat(get_db_path(), &db_stat);
|
||||||
|
|
||||||
|
|
||||||
return ((success == 0) && S_ISREG(db_stat.st_mode)) ? 0 : 1;
|
return ((success == 0) && S_ISREG(db_stat.st_mode)) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_db() {
|
int open_db() {
|
||||||
int ret = KOTO_DB_SUCCESS; // Default to last return being SUCCESS
|
int ret = KOTO_DB_SUCCESS; // Default to last return being SUCCESS
|
||||||
|
|
||||||
|
|
||||||
if (have_existing_db() == 1) { // If we do not have an existing DB
|
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_home = g_get_user_data_dir();
|
||||||
const gchar *data_dir = g_path_get_dirname(db_filepath);
|
const gchar * data_dir = g_path_get_dirname(db_filepath);
|
||||||
mkdir(data_home, 0755);
|
mkdir(data_home, 0755);
|
||||||
mkdir(data_dir, 0755);
|
mkdir(data_dir, 0755);
|
||||||
chown(data_dir, getuid(), getgid());
|
chown(data_dir, getuid(), getgid());
|
||||||
|
@ -102,7 +106,7 @@ int open_db() {
|
||||||
return KOTO_DB_FAIL;
|
return KOTO_DB_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_db_tables() != KOTO_DB_SUCCESS) {// Failed to create our database tables
|
if (create_db_tables() != KOTO_DB_SUCCESS) { // Failed to create our database tables
|
||||||
return KOTO_DB_FAIL;
|
return KOTO_DB_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,13 @@ extern int KOTO_DB_FAIL;
|
||||||
extern gboolean created_new_db;
|
extern gboolean created_new_db;
|
||||||
|
|
||||||
void close_db();
|
void close_db();
|
||||||
|
|
||||||
int create_db_tables();
|
int create_db_tables();
|
||||||
gchar* get_db_path();
|
|
||||||
|
gchar * get_db_path();
|
||||||
|
|
||||||
int enable_foreign_keys();
|
int enable_foreign_keys();
|
||||||
|
|
||||||
int have_existing_db();
|
int have_existing_db();
|
||||||
|
|
||||||
int open_db();
|
int open_db();
|
||||||
|
|
|
@ -25,19 +25,19 @@
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "koto-utils.h"
|
#include "koto-utils.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
struct _KotoIndexedAlbum {
|
struct _KotoIndexedAlbum {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gchar *uuid;
|
gchar * uuid;
|
||||||
gchar *path;
|
gchar * path;
|
||||||
|
|
||||||
gchar *name;
|
gchar * name;
|
||||||
gchar *art_path;
|
gchar * art_path;
|
||||||
gchar *artist_uuid;
|
gchar * artist_uuid;
|
||||||
GList *tracks;
|
GList * tracks;
|
||||||
|
|
||||||
gboolean has_album_art;
|
gboolean has_album_art;
|
||||||
gboolean do_initial_index;
|
gboolean do_initial_index;
|
||||||
|
@ -56,13 +56,28 @@ enum {
|
||||||
N_PROPERTIES
|
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_class_init(KotoIndexedAlbumClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_indexed_album_set_property;
|
gobject_class->set_property = koto_indexed_album_set_property;
|
||||||
gobject_class->get_property = koto_indexed_album_get_property;
|
gobject_class->get_property = koto_indexed_album_get_property;
|
||||||
|
@ -72,7 +87,7 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"UUID to Album in database",
|
"UUID to Album in database",
|
||||||
"UUID to Album in database",
|
"UUID to Album in database",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_DO_INITIAL_INDEX] = g_param_spec_boolean(
|
props[PROP_DO_INITIAL_INDEX] = g_param_spec_boolean(
|
||||||
|
@ -80,7 +95,7 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"Do an initial indexing operating instead of pulling from the database",
|
"Do an initial indexing operating instead of pulling from the database",
|
||||||
"Do an initial indexing operating instead of pulling from the database",
|
"Do an initial indexing operating instead of pulling from the database",
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_PATH] = g_param_spec_string(
|
props[PROP_PATH] = g_param_spec_string(
|
||||||
|
@ -88,7 +103,7 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"Path",
|
"Path",
|
||||||
"Path to Album",
|
"Path to Album",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ALBUM_NAME] = g_param_spec_string(
|
props[PROP_ALBUM_NAME] = g_param_spec_string(
|
||||||
|
@ -96,7 +111,7 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"Name",
|
"Name",
|
||||||
"Name of Album",
|
"Name of Album",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ART_PATH] = g_param_spec_string(
|
props[PROP_ART_PATH] = g_param_spec_string(
|
||||||
|
@ -104,7 +119,7 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"Path to Artwork",
|
"Path to Artwork",
|
||||||
"Path to Artwork",
|
"Path to Artwork",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ARTIST_UUID] = g_param_spec_string(
|
props[PROP_ARTIST_UUID] = g_param_spec_string(
|
||||||
|
@ -112,23 +127,28 @@ static void koto_indexed_album_class_init(KotoIndexedAlbumClass *c) {
|
||||||
"UUID of Artist associated with Album",
|
"UUID of Artist associated with Album",
|
||||||
"UUID of Artist associated with Album",
|
"UUID of Artist associated with Album",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_indexed_album_init(KotoIndexedAlbum *self) {
|
static void koto_indexed_album_init(KotoIndexedAlbum * self) {
|
||||||
self->has_album_art = FALSE;
|
self->has_album_art = FALSE;
|
||||||
self->tracks = NULL;
|
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
|
if (track == NULL) { // Not a file
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *track_uuid;
|
gchar * track_uuid;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "uuid", &track_uuid, NULL);
|
g_object_get(track, "uuid", &track_uuid, NULL);
|
||||||
|
|
||||||
if (g_list_index(self->tracks, track_uuid) == -1) {
|
if (g_list_index(self->tracks, track_uuid) == -1) {
|
||||||
|
@ -136,12 +156,12 @@ void koto_indexed_album_add_track(KotoIndexedAlbum *self, KotoIndexedTrack *trac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_album_commit(KotoIndexedAlbum *self) {
|
void koto_indexed_album_commit(KotoIndexedAlbum * self) {
|
||||||
if (self->art_path == NULL) { // If art_path isn't defined when committing
|
if (self->art_path == NULL) { // If art_path isn't defined when committing
|
||||||
koto_indexed_album_set_album_art(self, ""); // Set to an empty string
|
koto_indexed_album_set_album_art(self, ""); // Set to an empty string
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"INSERT INTO albums(id, path, artist_id, name, art_path)"
|
"INSERT INTO albums(id, path, artist_id, name, art_path)"
|
||||||
"VALUES('%s', quote(\"%s\"), '%s', quote(\"%s\"), quote(\"%s\"))"
|
"VALUES('%s', quote(\"%s\"), '%s', quote(\"%s\"), quote(\"%s\"))"
|
||||||
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, name=excluded.name, art_path=excluded.art_path;",
|
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, name=excluded.name, art_path=excluded.art_path;",
|
||||||
|
@ -152,9 +172,10 @@ void koto_indexed_album_commit(KotoIndexedAlbum *self) {
|
||||||
self->art_path
|
self->art_path
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_op_errmsg = NULL;
|
gchar * commit_op_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to write our album to the database: %s", commit_op_errmsg);
|
g_warning("Failed to write our album to the database: %s", commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
@ -163,9 +184,10 @@ void koto_indexed_album_commit(KotoIndexedAlbum *self) {
|
||||||
g_free(commit_op_errmsg);
|
g_free(commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
void koto_indexed_album_find_album_art(KotoIndexedAlbum * self) {
|
||||||
magic_t magic_cookie = magic_open(MAGIC_MIME);
|
magic_t magic_cookie = magic_open(MAGIC_MIME);
|
||||||
|
|
||||||
|
|
||||||
if (magic_cookie == NULL) {
|
if (magic_cookie == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -175,13 +197,15 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *dir = opendir(self->path); // Attempt to open our directory
|
DIR * dir = opendir(self->path); // Attempt to open our directory
|
||||||
|
|
||||||
|
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent *entry;
|
struct dirent * entry;
|
||||||
|
|
||||||
|
|
||||||
while ((entry = readdir(dir))) {
|
while ((entry = readdir(dir))) {
|
||||||
if (entry->d_type != DT_REG) { // Not a regular file
|
if (entry->d_type != DT_REG) { // Not a regular file
|
||||||
|
@ -192,9 +216,9 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
||||||
continue; // Skip
|
continue; // Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *full_path = g_strdup_printf("%s%s%s", self->path, G_DIR_SEPARATOR_S, entry->d_name);
|
gchar * full_path = g_strdup_printf("%s%s%s", self->path, G_DIR_SEPARATOR_S, entry->d_name);
|
||||||
|
|
||||||
const char *mime_type = magic_file(magic_cookie, full_path);
|
const char * mime_type = magic_file(magic_cookie, full_path);
|
||||||
|
|
||||||
if (mime_type == NULL) { // Failed to get the mimetype
|
if (mime_type == NULL) { // Failed to get the mimetype
|
||||||
g_free(full_path);
|
g_free(full_path);
|
||||||
|
@ -202,8 +226,8 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_str_has_prefix(mime_type, "image/") && !self->has_album_art) { // Is an image file and doesn't have album art yet
|
if (g_str_has_prefix(mime_type, "image/") && !self->has_album_art) { // Is an image file and doesn't have album art yet
|
||||||
gchar *album_art_no_ext = g_strdup(koto_utils_get_filename_without_extension(entry->d_name)); // Get the name of the file without the extension
|
gchar * album_art_no_ext = g_strdup(koto_utils_get_filename_without_extension(entry->d_name)); // Get the name of the file without the extension
|
||||||
gchar *lower_art = g_strdup(g_utf8_strdown(album_art_no_ext, -1)); // Lowercase
|
gchar * lower_art = g_strdup(g_utf8_strdown(album_art_no_ext, -1)); // Lowercase
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(g_strrstr(lower_art, "Small") == NULL) && // Not Small
|
(g_strrstr(lower_art, "Small") == NULL) && // Not Small
|
||||||
|
@ -226,7 +250,11 @@ void koto_indexed_album_find_album_art(KotoIndexedAlbum *self) {
|
||||||
magic_close(magic_cookie);
|
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
|
if (magic_cookie == NULL) { // No cookie provided
|
||||||
magic_cookie = magic_open(MAGIC_MIME);
|
magic_cookie = magic_open(MAGIC_MIME);
|
||||||
}
|
}
|
||||||
|
@ -244,20 +272,22 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *dir = opendir(path); // Attempt to open our directory
|
DIR * dir = opendir(path); // Attempt to open our directory
|
||||||
|
|
||||||
|
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent *entry;
|
struct dirent * entry;
|
||||||
|
|
||||||
|
|
||||||
while ((entry = readdir(dir))) {
|
while ((entry = readdir(dir))) {
|
||||||
if (g_str_has_prefix(entry->d_name, ".")) { // Reference to parent dir, self, or a hidden item
|
if (g_str_has_prefix(entry->d_name, ".")) { // Reference to parent dir, self, or a hidden item
|
||||||
continue; // Skip
|
continue; // Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *full_path = g_strdup_printf("%s%s%s", path, G_DIR_SEPARATOR_S, entry->d_name);
|
gchar * full_path = g_strdup_printf("%s%s%s", path, G_DIR_SEPARATOR_S, entry->d_name);
|
||||||
|
|
||||||
if (entry->d_type == DT_DIR) { // If this is a directory
|
if (entry->d_type == DT_DIR) { // If this is a directory
|
||||||
koto_indexed_album_find_tracks(self, magic_cookie, full_path); // Recursively find tracks
|
koto_indexed_album_find_tracks(self, magic_cookie, full_path); // Recursively find tracks
|
||||||
|
@ -269,7 +299,7 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
||||||
continue; // SKIP
|
continue; // SKIP
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *mime_type = magic_file(magic_cookie, full_path);
|
const char * mime_type = magic_file(magic_cookie, full_path);
|
||||||
|
|
||||||
if (mime_type == NULL) { // Failed to get the mimetype
|
if (mime_type == NULL) { // Failed to get the mimetype
|
||||||
g_free(full_path);
|
g_free(full_path);
|
||||||
|
@ -277,19 +307,19 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_str_has_prefix(mime_type, "audio/") || g_str_has_prefix(mime_type, "video/ogg")) { // Is an audio file or ogg because it is special
|
if (g_str_has_prefix(mime_type, "audio/") || g_str_has_prefix(mime_type, "video/ogg")) { // Is an audio file or ogg because it is special
|
||||||
gchar *appended_slash_to_path = g_strdup_printf("%s%s", g_strdup(self->path), G_DIR_SEPARATOR_S);
|
gchar * appended_slash_to_path = g_strdup_printf("%s%s", g_strdup(self->path), G_DIR_SEPARATOR_S);
|
||||||
gchar **possible_cd_split = g_strsplit(full_path, appended_slash_to_path, -1); // Split based on the album path
|
gchar ** possible_cd_split = g_strsplit(full_path, appended_slash_to_path, -1); // Split based on the album path
|
||||||
guint *cd = (guint*) 1;
|
guint * cd = (guint*) 1;
|
||||||
|
|
||||||
gchar *track_with_cd_sep = g_strdup(possible_cd_split[1]); // Duplicate
|
gchar * track_with_cd_sep = g_strdup(possible_cd_split[1]); // Duplicate
|
||||||
gchar **split_on_cd = g_strsplit(track_with_cd_sep, G_DIR_SEPARATOR_S, -1); // Split based on separator (e.g. / )
|
gchar ** split_on_cd = g_strsplit(track_with_cd_sep, G_DIR_SEPARATOR_S, -1); // Split based on separator (e.g. / )
|
||||||
|
|
||||||
if (g_strv_length(split_on_cd) > 1) {
|
if (g_strv_length(split_on_cd) > 1) {
|
||||||
gchar *cdd = g_strdup(split_on_cd[0]);
|
gchar * cdd = g_strdup(split_on_cd[0]);
|
||||||
gchar **cd_sep = g_strsplit(g_utf8_strdown(cdd, -1), "cd", -1);
|
gchar ** cd_sep = g_strsplit(g_utf8_strdown(cdd, -1), "cd", -1);
|
||||||
|
|
||||||
if (g_strv_length(cd_sep) > 1) {
|
if (g_strv_length(cd_sep) > 1) {
|
||||||
gchar *pos_str = g_strdup(cd_sep[1]);
|
gchar * pos_str = g_strdup(cd_sep[1]);
|
||||||
cd = (guint*) g_ascii_strtoull(pos_str, NULL, 10); // Attempt to convert
|
cd = (guint*) g_ascii_strtoull(pos_str, NULL, 10); // Attempt to convert
|
||||||
g_free(pos_str);
|
g_free(pos_str);
|
||||||
}
|
}
|
||||||
|
@ -304,7 +334,7 @@ void koto_indexed_album_find_tracks(KotoIndexedAlbum *self, magic_t magic_cookie
|
||||||
g_strfreev(possible_cd_split);
|
g_strfreev(possible_cd_split);
|
||||||
g_free(appended_slash_to_path);
|
g_free(appended_slash_to_path);
|
||||||
|
|
||||||
KotoIndexedTrack *track = koto_indexed_track_new(self, full_path, cd);
|
KotoIndexedTrack * track = koto_indexed_track_new(self, full_path, cd);
|
||||||
|
|
||||||
if (track != NULL) { // Is a file
|
if (track != NULL) { // Is a file
|
||||||
koto_indexed_album_add_track(self, track); // Add our file
|
koto_indexed_album_add_track(self, track); // Add our file
|
||||||
|
@ -315,8 +345,14 @@ 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(
|
||||||
KotoIndexedAlbum *self = KOTO_INDEXED_ALBUM(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedAlbum * self = KOTO_INDEXED_ALBUM(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -343,8 +379,14 @@ 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(
|
||||||
KotoIndexedAlbum *self = KOTO_INDEXED_ALBUM(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedAlbum * self = KOTO_INDEXED_ALBUM(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -372,7 +414,7 @@ static void koto_indexed_album_set_property(GObject *obj, guint prop_id, const G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_indexed_album_get_album_art(KotoIndexedAlbum *self) {
|
gchar * koto_indexed_album_get_album_art(KotoIndexedAlbum * self) {
|
||||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return g_strdup("");
|
return g_strdup("");
|
||||||
}
|
}
|
||||||
|
@ -380,7 +422,7 @@ gchar* koto_indexed_album_get_album_art(KotoIndexedAlbum *self) {
|
||||||
return g_strdup((self->has_album_art && koto_utils_is_string_valid(self->art_path)) ? self->art_path : "");
|
return g_strdup((self->has_album_art && koto_utils_is_string_valid(self->art_path)) ? self->art_path : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *koto_indexed_album_get_album_name(KotoIndexedAlbum *self) {
|
gchar * koto_indexed_album_get_album_name(KotoIndexedAlbum * self) {
|
||||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +434,7 @@ gchar *koto_indexed_album_get_album_name(KotoIndexedAlbum *self) {
|
||||||
return g_strdup(self->name); // Return duplicate of the name
|
return g_strdup(self->name); // Return duplicate of the name
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_indexed_album_get_album_uuid(KotoIndexedAlbum *self) {
|
gchar * koto_indexed_album_get_album_uuid(KotoIndexedAlbum * self) {
|
||||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -404,7 +446,7 @@ gchar* koto_indexed_album_get_album_uuid(KotoIndexedAlbum *self) {
|
||||||
return g_strdup(self->uuid); // Return a duplicate of the UUID
|
return g_strdup(self->uuid); // Return a duplicate of the UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
GList* koto_indexed_album_get_tracks(KotoIndexedAlbum *self) {
|
GList * koto_indexed_album_get_tracks(KotoIndexedAlbum * self) {
|
||||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -412,7 +454,10 @@ GList* koto_indexed_album_get_tracks(KotoIndexedAlbum *self) {
|
||||||
return self->tracks; // Return
|
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
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -430,7 +475,10 @@ void koto_indexed_album_set_album_art(KotoIndexedAlbum *self, const gchar *album
|
||||||
self->has_album_art = TRUE;
|
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
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -439,12 +487,17 @@ void koto_indexed_album_remove_file(KotoIndexedAlbum *self, KotoIndexedTrack *tr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *track_uuid;
|
gchar * track_uuid;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "parsed-name", &track_uuid, NULL);
|
g_object_get(track, "parsed-name", &track_uuid, NULL);
|
||||||
self->tracks = g_list_remove(self->tracks, track_uuid);
|
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
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -460,7 +513,10 @@ void koto_indexed_album_set_album_name(KotoIndexedAlbum *self, const gchar *albu
|
||||||
self->name = g_strdup(album_name);
|
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
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -476,7 +532,7 @@ void koto_indexed_album_set_artist_uuid(KotoIndexedAlbum *self, const gchar *art
|
||||||
self->artist_uuid = g_strdup(artist_uuid);
|
self->artist_uuid = g_strdup(artist_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum *self) {
|
void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum * self) {
|
||||||
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -485,17 +541,23 @@ void koto_indexed_album_set_as_current_playlist(KotoIndexedAlbum *self) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist *new_album_playlist = koto_playlist_new(); // Create a new playlist
|
KotoPlaylist * new_album_playlist = koto_playlist_new(); // Create a new playlist
|
||||||
|
|
||||||
|
|
||||||
g_object_set(new_album_playlist, "ephemeral", TRUE, NULL); // Set as ephemeral / temporary
|
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.
|
// The following section effectively reverses our tracks, so the first is now last.
|
||||||
// It then adds them in reverse order, since our playlist add function will prepend to our queue
|
// It then adds them in reverse order, since our playlist add function will prepend to our queue
|
||||||
// This enables the preservation and defaulting of "newest" first everywhere else, while in albums preserving the rightful order of the album
|
// 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
|
// 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
|
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
|
reversed_tracks = g_list_reverse(reversed_tracks); // Actually reverse it
|
||||||
|
|
||||||
GList *t;
|
GList * t;
|
||||||
|
|
||||||
|
|
||||||
for (t = reversed_tracks; t != NULL; t = t->next) { // For each of the tracks
|
for (t = reversed_tracks; t != NULL; t = t->next) { // For each of the tracks
|
||||||
gchar* track_uuid = t->data;
|
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
|
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,10 +570,15 @@ 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
|
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;
|
(void) user_data;
|
||||||
KotoIndexedTrack *track1 = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) track1_uuid);
|
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);
|
KotoIndexedTrack * track2 = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) track2_uuid);
|
||||||
|
|
||||||
|
|
||||||
if ((track1 == NULL) && (track2 == NULL)) { // Neither tracks actually exist
|
if ((track1 == NULL) && (track2 == NULL)) { // Neither tracks actually exist
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -521,8 +588,9 @@ gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer tra
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint *track1_disc = (guint*) 1;
|
guint * track1_disc = (guint*) 1;
|
||||||
guint *track2_disc = (guint*) 2;
|
guint * track2_disc = (guint*) 2;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track1, "cd", &track1_disc, NULL);
|
g_object_get(track1, "cd", &track1_disc, NULL);
|
||||||
g_object_get(track2, "cd", &track2_disc, NULL);
|
g_object_get(track2, "cd", &track2_disc, NULL);
|
||||||
|
@ -533,15 +601,16 @@ gint koto_indexed_album_sort_tracks(gconstpointer track1_uuid, gconstpointer tra
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint16 *track1_pos;
|
guint16 * track1_pos;
|
||||||
guint16 *track2_pos;
|
guint16 * track2_pos;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track1, "position", &track1_pos, NULL);
|
g_object_get(track1, "position", &track1_pos, NULL);
|
||||||
g_object_get(track2, "position", &track2_pos, NULL);
|
g_object_get(track2, "position", &track2_pos, NULL);
|
||||||
|
|
||||||
if (track1_pos == track2_pos) { // Identical positions (like reported as 0)
|
if (track1_pos == track2_pos) { // Identical positions (like reported as 0)
|
||||||
gchar *track1_name;
|
gchar * track1_name;
|
||||||
gchar *track2_name;
|
gchar * track2_name;
|
||||||
|
|
||||||
g_object_get(track1, "parsed-name", &track1_name, NULL);
|
g_object_get(track1, "parsed-name", &track1_name, NULL);
|
||||||
g_object_get(track2, "parsed-name", &track2_name, NULL);
|
g_object_get(track2, "parsed-name", &track2_name, 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
|
if (!KOTO_IS_INDEXED_ALBUM(self)) { // Not an album
|
||||||
return;
|
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
|
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(
|
||||||
gchar *artist_uuid = NULL;
|
KotoIndexedArtist * artist,
|
||||||
|
const gchar * path
|
||||||
|
) {
|
||||||
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||||
|
|
||||||
KotoIndexedAlbum* album = g_object_new(KOTO_TYPE_INDEXED_ALBUM,
|
KotoIndexedAlbum* album = g_object_new(
|
||||||
"artist-uuid", artist_uuid,
|
KOTO_TYPE_INDEXED_ALBUM,
|
||||||
"uuid", g_strdup(g_uuid_string_random()),
|
"artist-uuid",
|
||||||
"do-initial-index", TRUE,
|
artist_uuid,
|
||||||
"path", path,
|
"uuid",
|
||||||
|
g_strdup(g_uuid_string_random()),
|
||||||
|
"do-initial-index",
|
||||||
|
TRUE,
|
||||||
|
"path",
|
||||||
|
path,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
koto_indexed_album_commit(album);
|
koto_indexed_album_commit(album);
|
||||||
koto_indexed_album_find_tracks(album, NULL, NULL); // Scan for tracks now that we committed to the database (hopefully)
|
koto_indexed_album_find_tracks(album, NULL, NULL); // Scan for tracks now that we committed to the database (hopefully)
|
||||||
|
|
||||||
return album;
|
return album;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedAlbum* koto_indexed_album_new_with_uuid(KotoIndexedArtist *artist, const gchar *uuid) {
|
KotoIndexedAlbum * koto_indexed_album_new_with_uuid(
|
||||||
gchar *artist_uuid = NULL;
|
KotoIndexedArtist * artist,
|
||||||
|
const gchar * uuid
|
||||||
|
) {
|
||||||
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
g_object_get(artist, "uuid", &artist_uuid, NULL);
|
||||||
|
|
||||||
return g_object_new(KOTO_TYPE_INDEXED_ALBUM,
|
return g_object_new(
|
||||||
"artist-uuid", artist,
|
KOTO_TYPE_INDEXED_ALBUM,
|
||||||
"uuid", g_strdup(uuid),
|
"artist-uuid",
|
||||||
"do-initial-index", FALSE,
|
artist,
|
||||||
|
"uuid",
|
||||||
|
g_strdup(uuid),
|
||||||
|
"do-initial-index",
|
||||||
|
FALSE,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,16 @@
|
||||||
#include "../db/db.h"
|
#include "../db/db.h"
|
||||||
#include "../koto-utils.h"
|
#include "../koto-utils.h"
|
||||||
|
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
struct _KotoIndexedArtist {
|
struct _KotoIndexedArtist {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gchar *uuid;
|
gchar * uuid;
|
||||||
gchar *path;
|
gchar * path;
|
||||||
|
|
||||||
gboolean has_artist_art;
|
gboolean has_artist_art;
|
||||||
gchar *artist_name;
|
gchar * artist_name;
|
||||||
GList *albums;
|
GList * albums;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoIndexedArtist, koto_indexed_artist, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoIndexedArtist, koto_indexed_artist, G_TYPE_OBJECT);
|
||||||
|
@ -43,13 +43,28 @@ enum {
|
||||||
N_PROPERTIES
|
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_class_init(KotoIndexedArtistClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_indexed_artist_set_property;
|
gobject_class->set_property = koto_indexed_artist_set_property;
|
||||||
gobject_class->get_property = koto_indexed_artist_get_property;
|
gobject_class->get_property = koto_indexed_artist_get_property;
|
||||||
|
@ -59,7 +74,7 @@ static void koto_indexed_artist_class_init(KotoIndexedArtistClass *c) {
|
||||||
"UUID to Artist in database",
|
"UUID to Artist in database",
|
||||||
"UUID to Artist in database",
|
"UUID to Artist in database",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_PATH] = g_param_spec_string(
|
props[PROP_PATH] = g_param_spec_string(
|
||||||
|
@ -67,7 +82,7 @@ static void koto_indexed_artist_class_init(KotoIndexedArtistClass *c) {
|
||||||
"Path",
|
"Path",
|
||||||
"Path to Artist",
|
"Path to Artist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ARTIST_NAME] = g_param_spec_string(
|
props[PROP_ARTIST_NAME] = g_param_spec_string(
|
||||||
|
@ -75,19 +90,19 @@ static void koto_indexed_artist_class_init(KotoIndexedArtistClass *c) {
|
||||||
"Name",
|
"Name",
|
||||||
"Name of Artist",
|
"Name of Artist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_artist_commit(KotoIndexedArtist *self) {
|
void koto_indexed_artist_commit(KotoIndexedArtist * self) {
|
||||||
if ((self->uuid == NULL) || strcmp(self->uuid, "")) { // UUID not set
|
if ((self->uuid == NULL) || strcmp(self->uuid, "")) { // UUID not set
|
||||||
self->uuid = g_strdup(g_uuid_string_random());
|
self->uuid = g_strdup(g_uuid_string_random());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Support multiple types instead of just local music artist
|
// TODO: Support multiple types instead of just local music artist
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"INSERT INTO artists(id,path,type,name,art_path)"
|
"INSERT INTO artists(id,path,type,name,art_path)"
|
||||||
"VALUES ('%s', quote(\"%s\"), 0, quote(\"%s\"), NULL)"
|
"VALUES ('%s', quote(\"%s\"), 0, quote(\"%s\"), NULL)"
|
||||||
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, type=excluded.type, name=excluded.name, art_path=excluded.art_path;",
|
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, type=excluded.type, name=excluded.name, art_path=excluded.art_path;",
|
||||||
|
@ -96,9 +111,10 @@ void koto_indexed_artist_commit(KotoIndexedArtist *self) {
|
||||||
self->artist_name
|
self->artist_name
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_opt_errmsg = NULL;
|
gchar * commit_opt_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_opt_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_opt_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to write our artist to the database: %s", commit_opt_errmsg);
|
g_warning("Failed to write our artist to the database: %s", commit_opt_errmsg);
|
||||||
}
|
}
|
||||||
|
@ -107,13 +123,19 @@ void koto_indexed_artist_commit(KotoIndexedArtist *self) {
|
||||||
g_free(commit_opt_errmsg);
|
g_free(commit_opt_errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_indexed_artist_init(KotoIndexedArtist *self) {
|
static void koto_indexed_artist_init(KotoIndexedArtist * self) {
|
||||||
self->has_artist_art = FALSE;
|
self->has_artist_art = FALSE;
|
||||||
self->albums = NULL; // Create a new GList
|
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(
|
||||||
KotoIndexedArtist *self = KOTO_INDEXED_ARTIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedArtist * self = KOTO_INDEXED_ARTIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -131,8 +153,14 @@ 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(
|
||||||
KotoIndexedArtist *self = KOTO_INDEXED_ARTIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedArtist * self = KOTO_INDEXED_ARTIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -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
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -160,14 +191,15 @@ void koto_indexed_artist_add_album(KotoIndexedArtist *self, gchar *album_uuid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *uuid = g_strdup(album_uuid); // Duplicate our UUID
|
gchar * uuid = g_strdup(album_uuid); // Duplicate our UUID
|
||||||
|
|
||||||
|
|
||||||
if (g_list_index(self->albums, uuid) == -1) {
|
if (g_list_index(self->albums, uuid) == -1) {
|
||||||
self->albums = g_list_append(self->albums, uuid); // Push to end of list
|
self->albums = g_list_append(self->albums, uuid); // Push to end of list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GList* koto_indexed_artist_get_albums(KotoIndexedArtist *self) {
|
GList * koto_indexed_artist_get_albums(KotoIndexedArtist * self) {
|
||||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +207,7 @@ GList* koto_indexed_artist_get_albums(KotoIndexedArtist *self) {
|
||||||
return g_list_copy(self->albums);
|
return g_list_copy(self->albums);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_indexed_artist_get_name(KotoIndexedArtist *self) {
|
gchar * koto_indexed_artist_get_name(KotoIndexedArtist * self) {
|
||||||
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return g_strdup("");
|
return g_strdup("");
|
||||||
}
|
}
|
||||||
|
@ -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
|
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
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -192,12 +227,17 @@ void koto_indexed_artist_remove_album(KotoIndexedArtist *self, KotoIndexedAlbum
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *album_uuid;
|
gchar * album_uuid;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||||
self->albums = g_list_remove(self->albums, album_uuid);
|
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
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return;
|
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]);
|
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
|
if (!KOTO_IS_INDEXED_ARTIST(self)) { // Not an artist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -231,21 +274,28 @@ void koto_indexed_artist_set_artist_name(KotoIndexedArtist *self, gchar *artist_
|
||||||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_ARTIST_NAME]);
|
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_ARTIST_NAME]);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedArtist* koto_indexed_artist_new(gchar *path) {
|
KotoIndexedArtist * koto_indexed_artist_new(gchar * path) {
|
||||||
KotoIndexedArtist* artist = g_object_new(KOTO_TYPE_INDEXED_ARTIST,
|
KotoIndexedArtist* artist = g_object_new(
|
||||||
"uuid", g_uuid_string_random(),
|
KOTO_TYPE_INDEXED_ARTIST,
|
||||||
"path", path,
|
"uuid",
|
||||||
"name", g_path_get_basename(path),
|
g_uuid_string_random(),
|
||||||
|
"path",
|
||||||
|
path,
|
||||||
|
"name",
|
||||||
|
g_path_get_basename(path),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
koto_indexed_artist_commit(artist); // Commit the artist immediately to the database
|
koto_indexed_artist_commit(artist); // Commit the artist immediately to the database
|
||||||
return artist;
|
return artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedArtist* koto_indexed_artist_new_with_uuid(const gchar *uuid) {
|
KotoIndexedArtist * koto_indexed_artist_new_with_uuid(const gchar * uuid) {
|
||||||
return g_object_new(KOTO_TYPE_INDEXED_ARTIST,
|
return g_object_new(
|
||||||
"uuid", g_strdup(uuid),
|
KOTO_TYPE_INDEXED_ARTIST,
|
||||||
|
"uuid",
|
||||||
|
g_strdup(uuid),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,14 +26,14 @@
|
||||||
#include "../koto-utils.h"
|
#include "../koto-utils.h"
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
struct _KotoIndexedLibrary {
|
struct _KotoIndexedLibrary {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gchar *path;
|
gchar * path;
|
||||||
magic_t magic_cookie;
|
magic_t magic_cookie;
|
||||||
GHashTable *music_artists;
|
GHashTable * music_artists;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoIndexedLibrary, koto_indexed_library, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoIndexedLibrary, koto_indexed_library, G_TYPE_OBJECT);
|
||||||
|
@ -44,13 +44,28 @@ enum {
|
||||||
N_PROPERTIES
|
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_class_init(KotoIndexedLibraryClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_indexed_library_set_property;
|
gobject_class->set_property = koto_indexed_library_set_property;
|
||||||
gobject_class->get_property = koto_indexed_library_get_property;
|
gobject_class->get_property = koto_indexed_library_get_property;
|
||||||
|
@ -60,26 +75,31 @@ static void koto_indexed_library_class_init(KotoIndexedLibraryClass *c) {
|
||||||
"Path",
|
"Path",
|
||||||
"Path to Music",
|
"Path to Music",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_UTF8); // Ensure our id3v2 text encoding is UTF-8
|
taglib_id3v2_set_default_text_encoding(TagLib_ID3v2_UTF8); // Ensure our id3v2 text encoding is UTF-8
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_indexed_library_init(KotoIndexedLibrary *self) {
|
static void koto_indexed_library_init(KotoIndexedLibrary * self) {
|
||||||
self->music_artists = g_hash_table_new(g_str_hash, g_str_equal);
|
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
|
if (artist == NULL) { // No artist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
koto_indexed_library_get_artists(self); // Call to generate if needed
|
koto_indexed_library_get_artists(self); // Call to generate if needed
|
||||||
|
|
||||||
gchar *artist_name;
|
gchar * artist_name;
|
||||||
gchar *artist_uuid;
|
gchar * artist_uuid;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "name", &artist_name, "uuid", &artist_uuid, NULL);
|
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
|
if (g_hash_table_contains(self->music_artists, artist_name)) { // Already have the artist
|
||||||
|
@ -90,24 +110,28 @@ 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)
|
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) {
|
if (artist_name == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
koto_indexed_library_get_artists(self); // Call to generate if needed
|
koto_indexed_library_get_artists(self); // Call to generate if needed
|
||||||
|
|
||||||
gchar *artist_uuid = g_hash_table_lookup(self->music_artists, artist_name); // Get the UUID from our music artists
|
gchar * artist_uuid = g_hash_table_lookup(self->music_artists, artist_name); // Get the UUID from our music artists
|
||||||
|
|
||||||
|
|
||||||
if (artist_uuid != NULL) {
|
if (artist_uuid != NULL) {
|
||||||
KotoIndexedArtist *artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid); // Return any artist from cartographer
|
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid); // Return any artist from cartographer
|
||||||
return artist;
|
return artist;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GHashTable* koto_indexed_library_get_artists(KotoIndexedLibrary *self) {
|
GHashTable * koto_indexed_library_get_artists(KotoIndexedLibrary * self) {
|
||||||
if (self->music_artists == NULL) { // Not a HashTable
|
if (self->music_artists == NULL) { // Not a HashTable
|
||||||
self->music_artists = g_hash_table_new(g_str_hash, g_str_equal);
|
self->music_artists = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
}
|
}
|
||||||
|
@ -115,21 +139,32 @@ GHashTable* koto_indexed_library_get_artists(KotoIndexedLibrary *self) {
|
||||||
return self->music_artists;
|
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) {
|
if (artist == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
koto_indexed_library_get_artists(self); // Call to generate if needed
|
koto_indexed_library_get_artists(self); // Call to generate if needed
|
||||||
|
|
||||||
gchar *artist_name;
|
gchar * artist_name;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "name", &artist_name, NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
|
|
||||||
g_hash_table_remove(self->music_artists, artist_name); // Remove the artist
|
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(
|
||||||
KotoIndexedLibrary *self = KOTO_INDEXED_LIBRARY(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedLibrary * self = KOTO_INDEXED_LIBRARY(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PATH:
|
case PROP_PATH:
|
||||||
|
@ -141,8 +176,14 @@ 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(
|
||||||
KotoIndexedLibrary *self = KOTO_INDEXED_LIBRARY(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedLibrary * self = KOTO_INDEXED_LIBRARY(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PATH:
|
case PROP_PATH:
|
||||||
|
@ -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) {
|
if (path == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -172,25 +216,37 @@ 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_artists(
|
||||||
(void) num_columns; (void) column_names; // Don't need any of the params
|
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;
|
KotoIndexedLibrary * library = (KotoIndexedLibrary*) data;
|
||||||
gchar *artist_uuid = g_strdup(koto_utils_unquote_string(fields[0])); // First column is UUID
|
gchar * artist_uuid = g_strdup(koto_utils_unquote_string(fields[0])); // First column is UUID
|
||||||
gchar *artist_path = g_strdup(koto_utils_unquote_string(fields[1])); // Second column is path
|
gchar * artist_path = g_strdup(koto_utils_unquote_string(fields[1])); // Second column is path
|
||||||
gchar *artist_name = g_strdup(koto_utils_unquote_string(fields[3])); // Fourth column is artist name
|
gchar * artist_name = g_strdup(koto_utils_unquote_string(fields[3])); // Fourth column is artist name
|
||||||
|
|
||||||
KotoIndexedArtist *artist = koto_indexed_artist_new_with_uuid(artist_uuid); // Create our artist with the UUID
|
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
|
g_object_set(
|
||||||
"name", artist_name, // Set name
|
artist,
|
||||||
NULL);
|
"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_cartographer_add_artist(koto_maps, artist); // Add the artist to our global cartographer
|
||||||
koto_indexed_library_add_artist(library, artist);
|
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
|
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
|
if (albums_rc != SQLITE_OK) { // Failed to get our albums
|
||||||
g_critical("Failed to read our albums: %s", sqlite3_errmsg(koto_db));
|
g_critical("Failed to read our albums: %s", sqlite3_errmsg(koto_db));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -203,29 +259,42 @@ int process_artists(void *data, int num_columns, char **fields, char **column_na
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_albums(void *data, int num_columns, char **fields, char **column_names) {
|
int process_albums(
|
||||||
(void) num_columns; (void) column_names; // Don't need these
|
void * data,
|
||||||
|
int num_columns,
|
||||||
|
char ** fields,
|
||||||
|
char ** column_names
|
||||||
|
) {
|
||||||
|
(void) num_columns;
|
||||||
|
(void) column_names; // Don't need these
|
||||||
|
|
||||||
KotoIndexedArtist *artist = (KotoIndexedArtist*) data;
|
KotoIndexedArtist * artist = (KotoIndexedArtist*) data;
|
||||||
|
|
||||||
gchar *album_uuid = g_strdup(koto_utils_unquote_string(fields[0]));
|
gchar * album_uuid = g_strdup(koto_utils_unquote_string(fields[0]));
|
||||||
gchar *path = g_strdup(koto_utils_unquote_string(fields[1]));
|
gchar * path = g_strdup(koto_utils_unquote_string(fields[1]));
|
||||||
gchar *artist_uuid = g_strdup(koto_utils_unquote_string(fields[2]));
|
gchar * artist_uuid = g_strdup(koto_utils_unquote_string(fields[2]));
|
||||||
gchar *album_name = g_strdup(koto_utils_unquote_string(fields[3]));
|
gchar * album_name = g_strdup(koto_utils_unquote_string(fields[3]));
|
||||||
gchar *album_art = (fields[4] != NULL) ? g_strdup(koto_utils_unquote_string(fields[4])) : NULL;
|
gchar * album_art = (fields[4] != NULL) ? g_strdup(koto_utils_unquote_string(fields[4])) : NULL;
|
||||||
|
|
||||||
KotoIndexedAlbum *album = koto_indexed_album_new_with_uuid(artist, album_uuid); // Create our album
|
KotoIndexedAlbum * album = koto_indexed_album_new_with_uuid(artist, album_uuid); // Create our album
|
||||||
|
|
||||||
g_object_set(album,
|
|
||||||
"path", path, // Set the path
|
g_object_set(
|
||||||
"name", album_name, // Set name
|
album,
|
||||||
"art-path", album_art, // Set art path if any
|
"path",
|
||||||
NULL);
|
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_cartographer_add_album(koto_maps, album); // Add the album to our global cartographer
|
||||||
koto_indexed_artist_add_album(artist, album_uuid); // Add the album
|
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
|
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
|
if (tracks_rc != SQLITE_OK) { // Failed to get our tracks
|
||||||
g_critical("Failed to read our tracks: %s", sqlite3_errmsg(koto_db));
|
g_critical("Failed to read our tracks: %s", sqlite3_errmsg(koto_db));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -243,20 +312,31 @@ int process_albums(void *data, int num_columns, char **fields, char **column_nam
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_playlists(void *data, int num_columns, char **fields, char **column_names) {
|
int process_playlists(
|
||||||
(void) data; (void) num_columns; (void) column_names; // Don't need any of the params
|
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
|
||||||
|
|
||||||
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_name(playlist, playlist_name); // Add the playlist name
|
||||||
koto_playlist_set_artwork(playlist, playlist_art_path); // Add the playlist art path
|
koto_playlist_set_artwork(playlist, playlist_art_path); // Add the playlist art path
|
||||||
|
|
||||||
koto_cartographer_add_playlist(koto_maps, playlist); // Add to cartographer
|
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
|
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
|
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));
|
g_critical("Failed to read our playlist tracks: %s", sqlite3_errmsg(koto_db));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -271,15 +351,23 @@ int process_playlists(void *data, int num_columns, char **fields, char **column_
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_playlists_tracks(void *data, int num_columns, char **fields, char **column_names) {
|
int process_playlists_tracks(
|
||||||
(void) data; (void) num_columns; (void) column_names; // Don't need these
|
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 * playlist_uuid = g_strdup(koto_utils_unquote_string(fields[1]));
|
||||||
gchar *track_uuid = g_strdup(koto_utils_unquote_string(fields[2]));
|
gchar * track_uuid = g_strdup(koto_utils_unquote_string(fields[2]));
|
||||||
gboolean current = g_strcmp0(koto_utils_unquote_string(fields[3]), "0");
|
gboolean current = g_strcmp0(koto_utils_unquote_string(fields[3]), "0");
|
||||||
|
|
||||||
KotoPlaylist *playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid); // Get the playlist
|
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
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid); // Get the track
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
goto freeforret;
|
goto freeforret;
|
||||||
|
@ -294,29 +382,29 @@ freeforret:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int process_tracks(void *data, int num_columns, char **fields, char **column_names) {
|
int process_tracks(
|
||||||
(void) num_columns; (void) column_names; // Don't need these
|
void * data,
|
||||||
|
int num_columns,
|
||||||
|
char ** fields,
|
||||||
|
char ** column_names
|
||||||
|
) {
|
||||||
|
(void) num_columns;
|
||||||
|
(void) column_names; // Don't need these
|
||||||
|
|
||||||
KotoIndexedAlbum *album = (KotoIndexedAlbum*) data;
|
KotoIndexedAlbum * album = (KotoIndexedAlbum*) data;
|
||||||
gchar *track_uuid = g_strdup(koto_utils_unquote_string(fields[0]));
|
gchar * track_uuid = g_strdup(koto_utils_unquote_string(fields[0]));
|
||||||
gchar *path = g_strdup(koto_utils_unquote_string(fields[1]));
|
gchar * path = g_strdup(koto_utils_unquote_string(fields[1]));
|
||||||
gchar *artist_uuid = g_strdup(koto_utils_unquote_string(fields[3]));
|
gchar * artist_uuid = g_strdup(koto_utils_unquote_string(fields[3]));
|
||||||
gchar *album_uuid = g_strdup(koto_utils_unquote_string(fields[4]));
|
gchar * album_uuid = g_strdup(koto_utils_unquote_string(fields[4]));
|
||||||
gchar *file_name = g_strdup(koto_utils_unquote_string(fields[5]));
|
gchar * file_name = g_strdup(koto_utils_unquote_string(fields[5]));
|
||||||
gchar *name = g_strdup(koto_utils_unquote_string(fields[6]));
|
gchar * name = g_strdup(koto_utils_unquote_string(fields[6]));
|
||||||
guint *disc_num = (guint*) g_ascii_strtoull(fields[7], NULL, 10);
|
guint * disc_num = (guint*) g_ascii_strtoull(fields[7], NULL, 10);
|
||||||
guint *position = (guint*) g_ascii_strtoull(fields[8], NULL, 10);
|
guint * position = (guint*) g_ascii_strtoull(fields[8], NULL, 10);
|
||||||
|
|
||||||
KotoIndexedTrack *track = koto_indexed_track_new_with_uuid(track_uuid); // Create our file
|
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,
|
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);
|
||||||
"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_cartographer_add_track(koto_maps, track); // Add the track to cartographer
|
||||||
koto_indexed_album_add_track(album, track); // Add the track
|
koto_indexed_album_add_track(album, track); // Add the track
|
||||||
|
@ -331,8 +419,10 @@ int process_tracks(void *data, int num_columns, char **fields, char **column_nam
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_from_db(KotoIndexedLibrary *self) {
|
void read_from_db(KotoIndexedLibrary * self) {
|
||||||
int artists_rc = sqlite3_exec(koto_db, "SELECT * FROM artists", process_artists, self, NULL); // Process our artists
|
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
|
if (artists_rc != SQLITE_OK) { // Failed to get our artists
|
||||||
g_critical("Failed to read our artists: %s", sqlite3_errmsg(koto_db));
|
g_critical("Failed to read our artists: %s", sqlite3_errmsg(koto_db));
|
||||||
return;
|
return;
|
||||||
|
@ -341,16 +431,19 @@ void read_from_db(KotoIndexedLibrary *self) {
|
||||||
g_hash_table_foreach(self->music_artists, output_artists, NULL);
|
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
|
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
|
if (playlist_rc != SQLITE_OK) { // Failed to get our playlists
|
||||||
g_critical("Failed to read our playlists: %s", sqlite3_errmsg(koto_db));
|
g_critical("Failed to read our playlists: %s", sqlite3_errmsg(koto_db));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_indexing(KotoIndexedLibrary *self) {
|
void start_indexing(KotoIndexedLibrary * self) {
|
||||||
struct stat library_stat;
|
struct stat library_stat;
|
||||||
int success = stat(self->path, &library_stat);
|
int success = stat(self->path, &library_stat);
|
||||||
|
|
||||||
|
|
||||||
if (success != 0) { // Failed to read the library path
|
if (success != 0) { // Failed to read the library path
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -376,38 +469,48 @@ void start_indexing(KotoIndexedLibrary *self) {
|
||||||
g_hash_table_foreach(self->music_artists, output_artists, NULL);
|
g_hash_table_foreach(self->music_artists, output_artists, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedLibrary* koto_indexed_library_new(const gchar *path) {
|
KotoIndexedLibrary * koto_indexed_library_new(const gchar * path) {
|
||||||
return g_object_new(KOTO_TYPE_INDEXED_LIBRARY,
|
return g_object_new(
|
||||||
"path", path,
|
KOTO_TYPE_INDEXED_LIBRARY,
|
||||||
|
"path",
|
||||||
|
path,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
void index_folder(
|
||||||
|
KotoIndexedLibrary * self,
|
||||||
|
gchar * path,
|
||||||
|
guint depth
|
||||||
|
) {
|
||||||
depth++;
|
depth++;
|
||||||
|
|
||||||
DIR *dir = opendir(path); // Attempt to open our directory
|
DIR * dir = opendir(path); // Attempt to open our directory
|
||||||
|
|
||||||
|
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dirent *entry;
|
struct dirent * entry;
|
||||||
|
|
||||||
|
|
||||||
while ((entry = readdir(dir))) {
|
while ((entry = readdir(dir))) {
|
||||||
if (g_str_has_prefix(entry->d_name, ".")) { // A reference to parent dir, self, or a hidden item
|
if (g_str_has_prefix(entry->d_name, ".")) { // A reference to parent dir, self, or a hidden item
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *full_path = g_strdup_printf("%s%s%s", path, G_DIR_SEPARATOR_S, entry->d_name);
|
gchar * full_path = g_strdup_printf("%s%s%s", path, G_DIR_SEPARATOR_S, entry->d_name);
|
||||||
|
|
||||||
if (entry->d_type == DT_DIR) { // Directory
|
if (entry->d_type == DT_DIR) { // Directory
|
||||||
if (depth == 1) { // If we are following FOLDER/ARTIST/ALBUM then this would be artist
|
if (depth == 1) { // If we are following FOLDER/ARTIST/ALBUM then this would be artist
|
||||||
KotoIndexedArtist *artist = koto_indexed_artist_new(full_path); // Attempt to get the artist
|
KotoIndexedArtist * artist = koto_indexed_artist_new(full_path); // Attempt to get the artist
|
||||||
gchar *artist_name;
|
gchar * artist_name;
|
||||||
|
|
||||||
g_object_get(artist,
|
g_object_get(
|
||||||
"name", &artist_name,
|
artist,
|
||||||
|
"name",
|
||||||
|
&artist_name,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -416,17 +519,17 @@ void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
||||||
index_folder(self, full_path, depth); // Index this directory
|
index_folder(self, full_path, depth); // Index this directory
|
||||||
g_free(artist_name);
|
g_free(artist_name);
|
||||||
} else if (depth == 2) { // If we are following FOLDER/ARTIST/ALBUM then this would be album
|
} else if (depth == 2) { // If we are following FOLDER/ARTIST/ALBUM then this would be album
|
||||||
gchar *artist_name = g_path_get_basename(path); // Get the last entry from our path which is probably the artist
|
gchar * artist_name = g_path_get_basename(path); // Get the last entry from our path which is probably the artist
|
||||||
KotoIndexedArtist *artist = koto_indexed_library_get_artist(self, artist_name); // Get the artist
|
KotoIndexedArtist * artist = koto_indexed_library_get_artist(self, artist_name); // Get the artist
|
||||||
|
|
||||||
if (artist == NULL) {
|
if (artist == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedAlbum *album = koto_indexed_album_new(artist, full_path);
|
KotoIndexedAlbum * album = koto_indexed_album_new(artist, full_path);
|
||||||
koto_cartographer_add_album(koto_maps, album); // Add our album to the cartographer
|
koto_cartographer_add_album(koto_maps, album); // Add our album to the cartographer
|
||||||
|
|
||||||
gchar *album_uuid = NULL;
|
gchar * album_uuid = NULL;
|
||||||
g_object_get(album, "uuid", &album_uuid, NULL);
|
g_object_get(album, "uuid", &album_uuid, NULL);
|
||||||
koto_indexed_artist_add_album(artist, album_uuid); // Add the album
|
koto_indexed_artist_add_album(artist, album_uuid); // Add the album
|
||||||
g_free(artist_name);
|
g_free(artist_name);
|
||||||
|
@ -439,35 +542,46 @@ void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth) {
|
||||||
closedir(dir); // Close the directory
|
closedir(dir); // Close the directory
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_artists(gpointer artist_key, gpointer artist_ptr, gpointer data) {
|
void output_artists(
|
||||||
(void) artist_ptr; (void) data;
|
gpointer artist_key,
|
||||||
KotoIndexedArtist *artist = koto_cartographer_get_artist_by_uuid(koto_maps, (gchar*) 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) {
|
if (artist == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artist_name;
|
gchar * artist_name;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "name", &artist_name, NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
g_debug("Artist: %s", artist_name);
|
g_debug("Artist: %s", artist_name);
|
||||||
|
|
||||||
GList *albums = koto_indexed_artist_get_albums(artist); // Get the albums for this artist
|
GList * albums = koto_indexed_artist_get_albums(artist); // Get the albums for this artist
|
||||||
|
|
||||||
|
|
||||||
if (albums != NULL) {
|
if (albums != NULL) {
|
||||||
g_debug("Length of Albums: %d", g_list_length(albums));
|
g_debug("Length of Albums: %d", g_list_length(albums));
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *a;
|
GList * a;
|
||||||
|
|
||||||
|
|
||||||
for (a = albums; a != NULL; a = a->next) {
|
for (a = albums; a != NULL; a = a->next) {
|
||||||
gchar *album_uuid = a->data;
|
gchar * album_uuid = a->data;
|
||||||
KotoIndexedAlbum *album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||||
|
|
||||||
if (album == NULL) {
|
if (album == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artwork = koto_indexed_album_get_album_art(album);
|
gchar * artwork = koto_indexed_album_get_album_art(album);
|
||||||
gchar *album_name;
|
gchar * album_name;
|
||||||
g_object_get(album, "name", &album_name, NULL);
|
g_object_get(album, "name", &album_name, NULL);
|
||||||
g_debug("Album Art: %s", artwork);
|
g_debug("Album Art: %s", artwork);
|
||||||
g_debug("Album Name: %s", album_name);
|
g_debug("Album Name: %s", album_name);
|
||||||
|
@ -476,24 +590,25 @@ 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;
|
(void) user_data;
|
||||||
|
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) data);
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) data);
|
||||||
|
|
||||||
|
|
||||||
if (track == NULL) {
|
if (track == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *filepath;
|
gchar * filepath;
|
||||||
gchar *parsed_name;
|
gchar * parsed_name;
|
||||||
guint *pos;
|
guint * pos;
|
||||||
|
|
||||||
g_object_get(track,
|
|
||||||
"path", &filepath,
|
g_object_get(track, "path", &filepath, "parsed-name", &parsed_name, "position", &pos, NULL);
|
||||||
"parsed-name", &parsed_name,
|
|
||||||
"position", &pos,
|
|
||||||
NULL);
|
|
||||||
g_debug("File Path: %s", filepath);
|
g_debug("File Path: %s", filepath);
|
||||||
g_debug("Parsed Name: %s", parsed_name);
|
g_debug("Parsed Name: %s", parsed_name);
|
||||||
g_debug("Position: %d", GPOINTER_TO_INT(pos));
|
g_debug("Position: %d", GPOINTER_TO_INT(pos));
|
||||||
|
|
|
@ -23,18 +23,18 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_INDEXED_LIBRARY koto_indexed_library_get_type()
|
#define KOTO_TYPE_INDEXED_LIBRARY koto_indexed_library_get_type()
|
||||||
G_DECLARE_FINAL_TYPE(KotoIndexedLibrary, koto_indexed_library, KOTO, INDEXED_LIBRARY, GObject);
|
G_DECLARE_FINAL_TYPE(KotoIndexedLibrary, koto_indexed_library, KOTO, INDEXED_LIBRARY, GObject);
|
||||||
#define KOTO_IS_INDEXED_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_LIBRARY))
|
#define KOTO_IS_INDEXED_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_LIBRARY))
|
||||||
|
|
||||||
#define KOTO_TYPE_INDEXED_ARTIST koto_indexed_artist_get_type()
|
#define KOTO_TYPE_INDEXED_ARTIST koto_indexed_artist_get_type()
|
||||||
G_DECLARE_FINAL_TYPE (KotoIndexedArtist, koto_indexed_artist, KOTO, INDEXED_ARTIST, GObject);
|
G_DECLARE_FINAL_TYPE(KotoIndexedArtist, koto_indexed_artist, KOTO, INDEXED_ARTIST, GObject);
|
||||||
#define KOTO_IS_INDEXED_ARTIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_ARTIST))
|
#define KOTO_IS_INDEXED_ARTIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_ARTIST))
|
||||||
|
|
||||||
#define KOTO_TYPE_INDEXED_ALBUM koto_indexed_album_get_type()
|
#define KOTO_TYPE_INDEXED_ALBUM koto_indexed_album_get_type()
|
||||||
G_DECLARE_FINAL_TYPE (KotoIndexedAlbum, koto_indexed_album, KOTO, INDEXED_ALBUM, GObject);
|
G_DECLARE_FINAL_TYPE(KotoIndexedAlbum, koto_indexed_album, KOTO, INDEXED_ALBUM, GObject);
|
||||||
#define KOTO_IS_INDEXED_ALBUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_ALBUM))
|
#define KOTO_IS_INDEXED_ALBUM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_INDEXED_ALBUM))
|
||||||
|
|
||||||
#define KOTO_TYPE_INDEXED_TRACK koto_indexed_track_get_type()
|
#define KOTO_TYPE_INDEXED_TRACK koto_indexed_track_get_type()
|
||||||
|
@ -43,84 +43,258 @@ G_DECLARE_FINAL_TYPE(KotoIndexedTrack, koto_indexed_track, KOTO, INDEXED_TRACK,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Library Functions
|
* Library Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoIndexedLibrary* koto_indexed_library_new(const gchar *path);
|
KotoIndexedLibrary * koto_indexed_library_new(const gchar * path);
|
||||||
|
|
||||||
void koto_indexed_library_add_artist(KotoIndexedLibrary *self, KotoIndexedArtist *artist);
|
void koto_indexed_library_add_artist(
|
||||||
KotoIndexedArtist* koto_indexed_library_get_artist(KotoIndexedLibrary *self, gchar* artist_name);
|
KotoIndexedLibrary * self,
|
||||||
GHashTable* koto_indexed_library_get_artists(KotoIndexedLibrary *self);
|
KotoIndexedArtist * artist
|
||||||
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);
|
KotoIndexedArtist * koto_indexed_library_get_artist(
|
||||||
int process_albums(void *data, int num_columns, char **fields, char **column_names);
|
KotoIndexedLibrary * self,
|
||||||
int process_playlists(void *data, int num_columns, char **fields, char **column_names);
|
gchar* artist_name
|
||||||
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);
|
GHashTable * koto_indexed_library_get_artists(KotoIndexedLibrary * self);
|
||||||
void start_indexing(KotoIndexedLibrary *self);
|
|
||||||
void index_folder(KotoIndexedLibrary *self, gchar *path, guint depth);
|
void koto_indexed_library_remove_artist(
|
||||||
void output_track(gpointer data, gpointer user_data);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Artist Functions
|
* Artist Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoIndexedArtist* koto_indexed_artist_new(gchar *path);
|
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);
|
KotoIndexedArtist * koto_indexed_artist_new_with_uuid(const gchar * uuid);
|
||||||
void koto_indexed_artist_commit(KotoIndexedArtist *self);
|
|
||||||
guint koto_indexed_artist_find_album_with_name(gconstpointer *album_data, gconstpointer *album_name_data);
|
void koto_indexed_artist_add_album(
|
||||||
GList* koto_indexed_artist_get_albums(KotoIndexedArtist *self);
|
KotoIndexedArtist * self,
|
||||||
gchar* koto_indexed_artist_get_name(KotoIndexedArtist *self);
|
gchar * album_uuid
|
||||||
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_commit(KotoIndexedArtist * self);
|
||||||
void koto_indexed_artist_update_path(KotoIndexedArtist *self, gchar *new_path);
|
|
||||||
void output_artists(gpointer artist_key, gpointer artist_ptr, gpointer 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
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Album Functions
|
* Album Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoIndexedAlbum* koto_indexed_album_new(KotoIndexedArtist *artist, const gchar *path);
|
KotoIndexedAlbum * koto_indexed_album_new(
|
||||||
KotoIndexedAlbum* koto_indexed_album_new_with_uuid(KotoIndexedArtist *artist, const gchar *uuid);
|
KotoIndexedArtist * artist,
|
||||||
|
const gchar * path
|
||||||
|
);
|
||||||
|
|
||||||
void koto_indexed_album_add_track(KotoIndexedAlbum *self, KotoIndexedTrack *track);
|
KotoIndexedAlbum * koto_indexed_album_new_with_uuid(
|
||||||
void koto_indexed_album_commit(KotoIndexedAlbum *self);
|
KotoIndexedArtist * artist,
|
||||||
void koto_indexed_album_find_album_art(KotoIndexedAlbum *self);
|
const gchar * uuid
|
||||||
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);
|
void koto_indexed_album_add_track(
|
||||||
gchar* koto_indexed_album_get_album_uuid(KotoIndexedAlbum *self);
|
KotoIndexedAlbum * self,
|
||||||
GList* koto_indexed_album_get_tracks(KotoIndexedAlbum *self);
|
KotoIndexedTrack * track
|
||||||
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_commit(KotoIndexedAlbum * self);
|
||||||
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_find_album_art(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_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_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
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File / Track Functions
|
* File / Track Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoIndexedTrack* koto_indexed_track_new(KotoIndexedAlbum *album, const gchar *path, guint *cd);
|
KotoIndexedTrack * koto_indexed_track_new(
|
||||||
KotoIndexedTrack* koto_indexed_track_new_with_uuid(const gchar *uuid);
|
KotoIndexedAlbum * album,
|
||||||
|
const gchar * path,
|
||||||
|
guint * cd
|
||||||
|
);
|
||||||
|
|
||||||
void koto_indexed_track_commit(KotoIndexedTrack *self);
|
KotoIndexedTrack * koto_indexed_track_new_with_uuid(const gchar * uuid);
|
||||||
GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self);
|
|
||||||
gchar* koto_indexed_track_get_uuid(KotoIndexedTrack *self);
|
void koto_indexed_track_commit(KotoIndexedTrack * self);
|
||||||
void koto_indexed_track_parse_name(KotoIndexedTrack *self);
|
|
||||||
void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *playlist_uuid);
|
GVariant * koto_indexed_track_get_metadata_vardict(KotoIndexedTrack * self);
|
||||||
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);
|
gchar * koto_indexed_track_get_uuid(KotoIndexedTrack * self);
|
||||||
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_parse_name(KotoIndexedTrack * self);
|
||||||
void koto_indexed_track_set_position(KotoIndexedTrack *self, guint pos);
|
|
||||||
void koto_indexed_track_update_metadata(KotoIndexedTrack *self);
|
void koto_indexed_track_remove_from_playlist(
|
||||||
void koto_indexed_track_update_path(KotoIndexedTrack *self, const gchar *new_path);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -22,21 +22,21 @@
|
||||||
#include "structs.h"
|
#include "structs.h"
|
||||||
#include "koto-utils.h"
|
#include "koto-utils.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
struct _KotoIndexedTrack {
|
struct _KotoIndexedTrack {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gchar *artist_uuid;
|
gchar * artist_uuid;
|
||||||
gchar *album_uuid;
|
gchar * album_uuid;
|
||||||
gchar *uuid;
|
gchar * uuid;
|
||||||
gchar *path;
|
gchar * path;
|
||||||
|
|
||||||
gchar *file_name;
|
gchar * file_name;
|
||||||
gchar *parsed_name;
|
gchar * parsed_name;
|
||||||
guint *cd;
|
guint * cd;
|
||||||
guint *position;
|
guint * position;
|
||||||
guint *playback_position;
|
guint * playback_position;
|
||||||
|
|
||||||
gboolean acquired_metadata_from_id3;
|
gboolean acquired_metadata_from_id3;
|
||||||
gboolean do_initial_index;
|
gboolean do_initial_index;
|
||||||
|
@ -59,13 +59,28 @@ enum {
|
||||||
N_PROPERTIES
|
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_class_init(KotoIndexedTrackClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_indexed_track_set_property;
|
gobject_class->set_property = koto_indexed_track_set_property;
|
||||||
gobject_class->get_property = koto_indexed_track_get_property;
|
gobject_class->get_property = koto_indexed_track_get_property;
|
||||||
|
@ -75,7 +90,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"UUID to Artist associated with the File",
|
"UUID to Artist associated with the File",
|
||||||
"UUID to Artist associated with the File",
|
"UUID to Artist associated with the File",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ALBUM_UUID] = g_param_spec_string(
|
props[PROP_ALBUM_UUID] = g_param_spec_string(
|
||||||
|
@ -83,7 +98,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"UUID to Album associated with the File",
|
"UUID to Album associated with the File",
|
||||||
"UUID to Album associated with the File",
|
"UUID to Album associated with the File",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_UUID] = g_param_spec_string(
|
props[PROP_UUID] = g_param_spec_string(
|
||||||
|
@ -91,7 +106,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"UUID to File in database",
|
"UUID to File in database",
|
||||||
"UUID to File in database",
|
"UUID to File in database",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_DO_INITIAL_INDEX] = g_param_spec_boolean(
|
props[PROP_DO_INITIAL_INDEX] = g_param_spec_boolean(
|
||||||
|
@ -99,7 +114,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"Do an initial indexing operating instead of pulling from the database",
|
"Do an initial indexing operating instead of pulling from the database",
|
||||||
"Do an initial indexing operating instead of pulling from the database",
|
"Do an initial indexing operating instead of pulling from the database",
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_PATH] = g_param_spec_string(
|
props[PROP_PATH] = g_param_spec_string(
|
||||||
|
@ -107,7 +122,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"Path",
|
"Path",
|
||||||
"Path to File",
|
"Path to File",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_FILE_NAME] = g_param_spec_string(
|
props[PROP_FILE_NAME] = g_param_spec_string(
|
||||||
|
@ -115,7 +130,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"Name of File",
|
"Name of File",
|
||||||
"Name of File",
|
"Name of File",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_PARSED_NAME] = g_param_spec_string(
|
props[PROP_PARSED_NAME] = g_param_spec_string(
|
||||||
|
@ -123,7 +138,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
"Parsed Name of File",
|
"Parsed Name of File",
|
||||||
"Parsed Name of File",
|
"Parsed Name of File",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_CD] = g_param_spec_uint(
|
props[PROP_CD] = g_param_spec_uint(
|
||||||
|
@ -133,7 +148,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT16,
|
G_MAXUINT16,
|
||||||
1,
|
1,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_POSITION] = g_param_spec_uint(
|
props[PROP_POSITION] = g_param_spec_uint(
|
||||||
|
@ -143,7 +158,7 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT16,
|
G_MAXUINT16,
|
||||||
0,
|
0,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_PLAYBACK_POSITION] = g_param_spec_uint(
|
props[PROP_PLAYBACK_POSITION] = g_param_spec_uint(
|
||||||
|
@ -153,18 +168,24 @@ static void koto_indexed_track_class_init(KotoIndexedTrackClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT16,
|
G_MAXUINT16,
|
||||||
0,
|
0,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_indexed_track_init(KotoIndexedTrack *self) {
|
static void koto_indexed_track_init(KotoIndexedTrack * self) {
|
||||||
self->acquired_metadata_from_id3 = FALSE;
|
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(
|
||||||
KotoIndexedTrack *self = KOTO_INDEXED_TRACK(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedTrack * self = KOTO_INDEXED_TRACK(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ARTIST_UUID:
|
case PROP_ARTIST_UUID:
|
||||||
|
@ -200,8 +221,14 @@ 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(
|
||||||
KotoIndexedTrack *self = KOTO_INDEXED_TRACK(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoIndexedTrack * self = KOTO_INDEXED_TRACK(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ARTIST_UUID:
|
case PROP_ARTIST_UUID:
|
||||||
|
@ -244,7 +271,7 @@ static void koto_indexed_track_set_property(GObject *obj, guint prop_id, const G
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void koto_indexed_track_commit(KotoIndexedTrack *self) {
|
void koto_indexed_track_commit(KotoIndexedTrack * self) {
|
||||||
if ((self->artist_uuid == NULL) || (strcmp(self->artist_uuid, "") == 0)) { // No valid required artist UUID
|
if ((self->artist_uuid == NULL) || (strcmp(self->artist_uuid, "") == 0)) { // No valid required artist UUID
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +280,7 @@ void koto_indexed_track_commit(KotoIndexedTrack *self) {
|
||||||
g_object_set(self, "album-uuid", "", NULL); // Set to an empty string
|
g_object_set(self, "album-uuid", "", NULL); // Set to an empty string
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"INSERT INTO tracks(id, path, type, artist_id, album_id, file_name, name, disc, position)"
|
"INSERT INTO tracks(id, path, type, artist_id, album_id, file_name, name, disc, position)"
|
||||||
"VALUES('%s', quote(\"%s\"), 0, '%s', '%s', quote(\"%s\"), quote(\"%s\"), %d, %d)"
|
"VALUES('%s', quote(\"%s\"), 0, '%s', '%s', quote(\"%s\"), quote(\"%s\"), %d, %d)"
|
||||||
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, type=excluded.type, album_id=excluded.album_id, file_name=excluded.file_name, name=excluded.file_name, disc=excluded.disc, position=excluded.position;",
|
"ON CONFLICT(id) DO UPDATE SET path=excluded.path, type=excluded.type, album_id=excluded.album_id, file_name=excluded.file_name, name=excluded.file_name, disc=excluded.disc, position=excluded.position;",
|
||||||
|
@ -267,9 +294,10 @@ void koto_indexed_track_commit(KotoIndexedTrack *self) {
|
||||||
GPOINTER_TO_INT((int*) self->position)
|
GPOINTER_TO_INT((int*) self->position)
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_op_errmsg = NULL;
|
gchar * commit_op_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to write our file to the database: %s", commit_op_errmsg);
|
g_warning("Failed to write our file to the database: %s", commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
@ -278,28 +306,24 @@ void koto_indexed_track_commit(KotoIndexedTrack *self) {
|
||||||
g_free(commit_op_errmsg);
|
g_free(commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self) {
|
GVariant * koto_indexed_track_get_metadata_vardict(KotoIndexedTrack * self) {
|
||||||
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT);
|
||||||
|
|
||||||
gchar *album_art_path = NULL;
|
gchar * album_art_path = NULL;
|
||||||
gchar *album_name = NULL;
|
gchar * album_name = NULL;
|
||||||
gchar *artist_name = NULL;
|
gchar * artist_name = NULL;
|
||||||
|
|
||||||
KotoIndexedArtist *artist = koto_cartographer_get_artist_by_uuid(koto_maps, self->artist_uuid);
|
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);
|
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,
|
g_object_get(album, "art-path", &album_art_path, "name", &album_name, NULL);
|
||||||
"name", &artist_name,
|
|
||||||
NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
|
|
||||||
g_variant_builder_add(builder, "{sv}", "mpris:trackid", g_variant_new_string(self->uuid));
|
g_variant_builder_add(builder, "{sv}", "mpris:trackid", g_variant_new_string(self->uuid));
|
||||||
|
|
||||||
|
@ -311,8 +335,8 @@ GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self) {
|
||||||
g_variant_builder_add(builder, "{sv}", "xesam:album", g_variant_new_string(album_name));
|
g_variant_builder_add(builder, "{sv}", "xesam:album", g_variant_new_string(album_name));
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(artist_name)) { // Valid artist name
|
if (koto_utils_is_string_valid(artist_name)) { // Valid artist name
|
||||||
GVariant *artist_name_variant;
|
GVariant * artist_name_variant;
|
||||||
GVariantBuilder *artist_list_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
|
GVariantBuilder * artist_list_builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
|
||||||
g_variant_builder_add(artist_list_builder, "s", artist_name);
|
g_variant_builder_add(artist_list_builder, "s", artist_name);
|
||||||
artist_name_variant = g_variant_new("as", artist_list_builder);
|
artist_name_variant = g_variant_new("as", artist_list_builder);
|
||||||
g_variant_builder_unref(artist_list_builder);
|
g_variant_builder_unref(artist_list_builder);
|
||||||
|
@ -326,12 +350,13 @@ GVariant* koto_indexed_track_get_metadata_vardict(KotoIndexedTrack *self) {
|
||||||
g_variant_builder_add(builder, "{sv}", "xesam:url", g_variant_new_string(self->path));
|
g_variant_builder_add(builder, "{sv}", "xesam:url", g_variant_new_string(self->path));
|
||||||
g_variant_builder_add(builder, "{sv}", "xesam:trackNumber", g_variant_new_uint64(GPOINTER_TO_UINT(self->position)));
|
g_variant_builder_add(builder, "{sv}", "xesam:trackNumber", g_variant_new_uint64(GPOINTER_TO_UINT(self->position)));
|
||||||
|
|
||||||
GVariant *metadata_ret = g_variant_builder_end(builder);
|
GVariant * metadata_ret = g_variant_builder_end(builder);
|
||||||
|
|
||||||
|
|
||||||
return metadata_ret;
|
return metadata_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_indexed_track_get_uuid(KotoIndexedTrack *self) {
|
gchar * koto_indexed_track_get_uuid(KotoIndexedTrack * self) {
|
||||||
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -339,18 +364,20 @@ gchar* koto_indexed_track_get_uuid(KotoIndexedTrack *self) {
|
||||||
return self->uuid; // Do not return a duplicate since otherwise comparison refs fail due to pointer positions being different
|
return self->uuid; // Do not return a duplicate since otherwise comparison refs fail due to pointer positions being different
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
void koto_indexed_track_parse_name(KotoIndexedTrack * self) {
|
||||||
gchar *copied_file_name = g_strdelimit(g_strdup(self->file_name), "_", ' '); // Replace _ with whitespace for starters
|
gchar * copied_file_name = g_strdelimit(g_strdup(self->file_name), "_", ' '); // Replace _ with whitespace for starters
|
||||||
|
|
||||||
|
KotoIndexedArtist * artist = NULL;
|
||||||
|
|
||||||
|
|
||||||
KotoIndexedArtist *artist = NULL;
|
|
||||||
artist = koto_cartographer_get_artist_by_uuid(koto_maps, self->artist_uuid);
|
artist = koto_cartographer_get_artist_by_uuid(koto_maps, self->artist_uuid);
|
||||||
|
|
||||||
if (artist != NULL) { // If we have artist
|
if (artist != NULL) { // If we have artist
|
||||||
gchar *artist_name = NULL;
|
gchar * artist_name = NULL;
|
||||||
g_object_get(artist, "name", &artist_name, NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
|
|
||||||
if (artist_name != NULL && (strcmp(artist_name, "") != 0)) {
|
if (artist_name != NULL && (strcmp(artist_name, "") != 0)) {
|
||||||
gchar **split = g_strsplit(copied_file_name, artist_name, -1); // Split whenever we encounter the artist
|
gchar ** split = g_strsplit(copied_file_name, artist_name, -1); // Split whenever we encounter the artist
|
||||||
copied_file_name = g_strjoinv("", split); // Remove the artist
|
copied_file_name = g_strjoinv("", split); // Remove the artist
|
||||||
g_strfreev(split);
|
g_strfreev(split);
|
||||||
|
|
||||||
|
@ -360,13 +387,16 @@ void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *file_without_ext = koto_utils_get_filename_without_extension(copied_file_name);
|
gchar * file_without_ext = koto_utils_get_filename_without_extension(copied_file_name);
|
||||||
|
|
||||||
|
|
||||||
g_free(copied_file_name);
|
g_free(copied_file_name);
|
||||||
|
|
||||||
gchar **split = g_regex_split_simple("^([\\d]+)", file_without_ext, G_REGEX_JAVASCRIPT_COMPAT, 0);
|
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
|
if (g_strv_length(split) > 1) { // Has positional info at the beginning of the file
|
||||||
gchar *num = split[1];
|
gchar * num = split[1];
|
||||||
|
|
||||||
g_free(file_without_ext); // Free the prior name
|
g_free(file_without_ext); // Free the prior name
|
||||||
file_without_ext = g_strdup(split[2]); // Set to our second item which is the rest of the song name without the prefixed numbers
|
file_without_ext = g_strdup(split[2]); // Set to our second item which is the rest of the song name without the prefixed numbers
|
||||||
|
@ -396,19 +426,24 @@ void koto_indexed_track_parse_name(KotoIndexedTrack *self) {
|
||||||
g_free(file_without_ext);
|
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)) {
|
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"DELETE FROM playlist_tracks WHERE track_id='%s' AND playlist_id='%s'",
|
"DELETE FROM playlist_tracks WHERE track_id='%s' AND playlist_id='%s'",
|
||||||
self->uuid,
|
self->uuid,
|
||||||
playlist_uuid
|
playlist_uuid
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_op_errmsg = NULL;
|
gchar * commit_op_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to remove track from playlist: %s", commit_op_errmsg);
|
g_warning("Failed to remove track from playlist: %s", commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
@ -417,12 +452,16 @@ void koto_indexed_track_remove_from_playlist(KotoIndexedTrack *self, gchar *play
|
||||||
g_free(commit_op_errmsg);
|
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)) {
|
if (!KOTO_IS_INDEXED_TRACK(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"INSERT INTO playlist_tracks(playlist_id, track_id, current)"
|
"INSERT INTO playlist_tracks(playlist_id, track_id, current)"
|
||||||
"VALUES('%s', '%s', quote(\"%d\"))",
|
"VALUES('%s', '%s', quote(\"%d\"))",
|
||||||
playlist_uuid,
|
playlist_uuid,
|
||||||
|
@ -430,9 +469,10 @@ void koto_indexed_track_save_to_playlist(KotoIndexedTrack *self, gchar *playlist
|
||||||
current
|
current
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_op_errmsg = NULL;
|
gchar * commit_op_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to save track to playlist: %s", commit_op_errmsg);
|
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);
|
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) {
|
if (new_file_name == NULL) {
|
||||||
return;
|
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
|
if (cd == 0) { // No change really
|
||||||
return;
|
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]);
|
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) {
|
if (new_parsed_name == NULL) {
|
||||||
return;
|
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]);
|
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
|
if (pos == 0) { // No position change really
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -497,24 +549,28 @@ void koto_indexed_track_set_position(KotoIndexedTrack *self, guint pos) {
|
||||||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_POSITION]);
|
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_POSITION]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_indexed_track_update_metadata(KotoIndexedTrack *self) {
|
void koto_indexed_track_update_metadata(KotoIndexedTrack * self) {
|
||||||
TagLib_File *t_file = taglib_file_new(self->path); // Get a taglib file for this file
|
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
|
|
||||||
koto_indexed_track_set_parsed_name(self, taglib_tag_title(tag)); // Set the title of the file
|
|
||||||
koto_indexed_track_set_position(self, (uint) taglib_tag_track(tag)); // Get the track, convert to uint and cast as a pointer
|
|
||||||
koto_indexed_track_set_file_name(self, g_path_get_basename(self->path)); // Update our file name
|
|
||||||
} else {
|
|
||||||
koto_indexed_track_set_file_name(self, g_path_get_basename(self->path)); // Update our file name
|
|
||||||
}
|
|
||||||
|
|
||||||
taglib_tag_free_strings(); // Free strings
|
if ((t_file != NULL) && taglib_file_is_valid(t_file)) { // If we got the taglib file and it is valid
|
||||||
taglib_file_free(t_file); // Free the file
|
self->acquired_metadata_from_id3 = TRUE;
|
||||||
|
TagLib_Tag * tag = taglib_file_tag(t_file); // Get our tag
|
||||||
|
koto_indexed_track_set_parsed_name(self, taglib_tag_title(tag)); // Set the title of the file
|
||||||
|
koto_indexed_track_set_position(self, (uint) taglib_tag_track(tag)); // Get the track, convert to uint and cast as a pointer
|
||||||
|
koto_indexed_track_set_file_name(self, g_path_get_basename(self->path)); // Update our file name
|
||||||
|
} else {
|
||||||
|
koto_indexed_track_set_file_name(self, g_path_get_basename(self->path)); // Update our file name
|
||||||
|
}
|
||||||
|
|
||||||
|
taglib_tag_free_strings(); // Free strings
|
||||||
|
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) {
|
if (new_path == NULL) {
|
||||||
return;
|
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]);
|
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(
|
||||||
gchar *artist_uuid;
|
KotoIndexedAlbum * album,
|
||||||
gchar *album_uuid;
|
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
|
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,
|
KotoIndexedTrack * track = g_object_new(
|
||||||
"artist-uuid", artist_uuid,
|
KOTO_TYPE_INDEXED_TRACK,
|
||||||
"album-uuid", album_uuid,
|
"artist-uuid",
|
||||||
"do-initial-index", TRUE,
|
artist_uuid,
|
||||||
"uuid", g_uuid_string_random(),
|
"album-uuid",
|
||||||
"path", path,
|
album_uuid,
|
||||||
"cd", cd,
|
"do-initial-index",
|
||||||
|
TRUE,
|
||||||
|
"uuid",
|
||||||
|
g_uuid_string_random(),
|
||||||
|
"path",
|
||||||
|
path,
|
||||||
|
"cd",
|
||||||
|
cd,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
koto_indexed_track_commit(track); // Immediately commit to the database
|
koto_indexed_track_commit(track); // Immediately commit to the database
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack* koto_indexed_track_new_with_uuid(const gchar *uuid) {
|
KotoIndexedTrack * koto_indexed_track_new_with_uuid(const gchar * uuid) {
|
||||||
return g_object_new(KOTO_TYPE_INDEXED_TRACK,
|
return g_object_new(
|
||||||
"uuid", g_strdup(uuid),
|
KOTO_TYPE_INDEXED_TRACK,
|
||||||
|
"uuid",
|
||||||
|
g_strdup(uuid),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct _PixbufSize {
|
||||||
|
|
||||||
typedef struct _PixbufSize PixbufSize;
|
typedef struct _PixbufSize PixbufSize;
|
||||||
|
|
||||||
static PixbufSize *pixbuf_sizes = NULL;
|
static PixbufSize * pixbuf_sizes = NULL;
|
||||||
static guint pixbuf_sizes_allocated = 0;
|
static guint pixbuf_sizes_allocated = 0;
|
||||||
|
|
||||||
static void init_pixbuf_sizes() {
|
static void init_pixbuf_sizes() {
|
||||||
|
@ -62,24 +62,26 @@ enum {
|
||||||
N_BTN_PROPERTIES
|
N_BTN_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *btn_props[N_BTN_PROPERTIES] = { NULL, };
|
static GParamSpec * btn_props[N_BTN_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoButton {
|
struct _KotoButton {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
guint pix_size;
|
guint pix_size;
|
||||||
|
|
||||||
GtkWidget *button_pic;
|
GtkWidget * button_pic;
|
||||||
GtkWidget *badge_label;
|
GtkWidget * badge_label;
|
||||||
GtkWidget *button_label;
|
GtkWidget * button_label;
|
||||||
|
|
||||||
GtkGesture *left_click_gesture;
|
GtkGesture * left_click_gesture;
|
||||||
GtkGesture *right_click_gesture;
|
GtkGesture * right_click_gesture;
|
||||||
|
|
||||||
gchar *image_file_path;
|
gchar * image_file_path;
|
||||||
gchar *badge_text;
|
gchar * badge_text;
|
||||||
gchar *icon_name;
|
gchar * icon_name;
|
||||||
gchar *alt_icon_name;
|
gchar * alt_icon_name;
|
||||||
gchar *text;
|
gchar * text;
|
||||||
|
|
||||||
KotoButtonImagePosition image_position;
|
KotoButtonImagePosition image_position;
|
||||||
gboolean use_from_file;
|
gboolean use_from_file;
|
||||||
|
@ -92,12 +94,26 @@ struct _KotoButtonClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoButton, koto_button, GTK_TYPE_BOX);
|
G_DEFINE_TYPE(KotoButton, koto_button, GTK_TYPE_BOX);
|
||||||
|
|
||||||
static void koto_button_constructed(GObject *obj);
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_button_class_init(KotoButtonClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->constructed = koto_button_constructed;
|
gobject_class->constructed = koto_button_constructed;
|
||||||
gobject_class->set_property = koto_button_set_property;
|
gobject_class->set_property = koto_button_set_property;
|
||||||
|
@ -110,7 +126,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_TINY),
|
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_TINY),
|
||||||
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_GODLIKE),
|
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_GODLIKE),
|
||||||
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_SMALL),
|
koto_get_pixbuf_size(KOTO_BUTTON_PIXBUF_SIZE_SMALL),
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_TEXT] = g_param_spec_string(
|
btn_props[PROP_TEXT] = g_param_spec_string(
|
||||||
|
@ -118,7 +134,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"Button Text",
|
"Button Text",
|
||||||
"Text of Button",
|
"Text of Button",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_BADGE_TEXT] = g_param_spec_string(
|
btn_props[PROP_BADGE_TEXT] = g_param_spec_string(
|
||||||
|
@ -126,7 +142,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"Badge Text",
|
"Badge Text",
|
||||||
"Text of Badge",
|
"Text of Badge",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_USE_FROM_FILE] = g_param_spec_boolean(
|
btn_props[PROP_USE_FROM_FILE] = g_param_spec_boolean(
|
||||||
|
@ -134,7 +150,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"Use from a file / file name",
|
"Use from a file / file name",
|
||||||
"Use from a file / file name",
|
"Use from a file / file name",
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_IMAGE_FILE_PATH] = g_param_spec_string(
|
btn_props[PROP_IMAGE_FILE_PATH] = g_param_spec_string(
|
||||||
|
@ -142,7 +158,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"File path to image",
|
"File path to image",
|
||||||
"File path to image",
|
"File path to image",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_ICON_NAME] = g_param_spec_string(
|
btn_props[PROP_ICON_NAME] = g_param_spec_string(
|
||||||
|
@ -150,7 +166,7 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"Icon Name",
|
"Icon Name",
|
||||||
"Name of Icon",
|
"Name of Icon",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
btn_props[PROP_ALT_ICON_NAME] = g_param_spec_string(
|
btn_props[PROP_ALT_ICON_NAME] = g_param_spec_string(
|
||||||
|
@ -158,13 +174,13 @@ static void koto_button_class_init(KotoButtonClass *c) {
|
||||||
"Name of an Alternate Icon",
|
"Name of an Alternate Icon",
|
||||||
"Name of an Alternate Icon",
|
"Name of an Alternate Icon",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_BTN_PROPERTIES, btn_props);
|
g_object_class_install_properties(gobject_class, N_BTN_PROPERTIES, btn_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_button_init(KotoButton *self) {
|
static void koto_button_init(KotoButton * self) {
|
||||||
self->currently_showing_alt = FALSE;
|
self->currently_showing_alt = FALSE;
|
||||||
self->image_position = KOTO_BUTTON_IMAGE_POS_LEFT;
|
self->image_position = KOTO_BUTTON_IMAGE_POS_LEFT;
|
||||||
|
|
||||||
|
@ -178,16 +194,24 @@ static void koto_button_init(KotoButton *self) {
|
||||||
gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(self->right_click_gesture)); // Add our right click gesture
|
gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(self->right_click_gesture)); // Add our right click gesture
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_button_constructed(GObject *obj) {
|
static void koto_button_constructed(GObject * obj) {
|
||||||
KotoButton *self = KOTO_BUTTON(obj);
|
KotoButton * self = KOTO_BUTTON(obj);
|
||||||
GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
GtkStyleContext * style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
||||||
|
|
||||||
|
|
||||||
gtk_style_context_add_class(style, "koto-button");
|
gtk_style_context_add_class(style, "koto-button");
|
||||||
|
|
||||||
G_OBJECT_CLASS (koto_button_parent_class)->constructed (obj);
|
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(
|
||||||
KotoButton *self = KOTO_BUTTON(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoButton * self = KOTO_BUTTON(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_IMAGE_FILE_PATH:
|
case PROP_IMAGE_FILE_PATH:
|
||||||
|
@ -217,8 +241,14 @@ 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(
|
||||||
KotoButton *self = KOTO_BUTTON(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoButton * self = KOTO_BUTTON(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PIX_SIZE:
|
case PROP_PIX_SIZE:
|
||||||
|
@ -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)) {
|
if (!KOTO_IS_BUTTON(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +304,7 @@ void koto_button_add_click_handler(KotoButton *self, KotoButtonClickType button,
|
||||||
g_signal_connect((button == KOTO_BUTTON_CLICK_TYPE_PRIMARY) ? self->left_click_gesture : self->right_click_gesture, "pressed", handler, user_data);
|
g_signal_connect((button == KOTO_BUTTON_CLICK_TYPE_PRIMARY) ? self->left_click_gesture : self->right_click_gesture, "pressed", handler, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_button_flip(KotoButton *self) {
|
void koto_button_flip(KotoButton * self) {
|
||||||
if (!KOTO_IS_BUTTON(self)) {
|
if (!KOTO_IS_BUTTON(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -277,13 +312,16 @@ void koto_button_flip(KotoButton *self) {
|
||||||
koto_button_show_image(self, !self->currently_showing_alt);
|
koto_button_show_image(self, !self->currently_showing_alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_button_hide_image(KotoButton *self) {
|
void koto_button_hide_image(KotoButton * self) {
|
||||||
if (GTK_IS_WIDGET(self->button_pic)) { // Is a widget
|
if (GTK_IS_WIDGET(self->button_pic)) { // Is a widget
|
||||||
gtk_widget_hide(self->button_pic);
|
gtk_widget_hide(self->button_pic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
if ((text == NULL) || (strcmp(text, "") == 0)) { // If the text is empty
|
||||||
self->badge_text = g_strdup("");
|
self->badge_text = g_strdup("");
|
||||||
} else {
|
} 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]);
|
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
|
if (!KOTO_IS_BUTTON(self)) { // Not a button
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -324,8 +365,13 @@ void koto_button_set_file_path(KotoButton *self, gchar *file_path) {
|
||||||
koto_button_show_image(self, FALSE);
|
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(
|
||||||
gchar *copied_icon_name = g_strdup(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 (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
|
if ((self->alt_icon_name != NULL) && strcmp(icon_name, self->alt_icon_name) != 0) { // If the icons are different
|
||||||
|
@ -342,9 +388,11 @@ void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean hide_image = FALSE;
|
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
|
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;
|
hide_image = TRUE;
|
||||||
} else if (!for_alt && ((self->icon_name == NULL) || (strcmp(self->icon_name,"") == 0))) { // Not for alt, no icon
|
} else if (!for_alt && ((self->icon_name == NULL) || (strcmp(self->icon_name, "") == 0))) { // Not for alt, no icon
|
||||||
hide_image = TRUE;
|
hide_image = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]);
|
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
|
if (self->image_position == pos) { // Is a different position that currently
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -375,7 +426,10 @@ void koto_button_set_image_position(KotoButton *self, KotoButtonImagePosition po
|
||||||
self->image_position = pos;
|
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) {
|
if (size == self->pix_size) {
|
||||||
return;
|
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]);
|
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) {
|
if (text == NULL) {
|
||||||
return;
|
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]);
|
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)) {
|
if (!KOTO_IS_BUTTON(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -446,7 +506,7 @@ void koto_button_show_image(KotoButton *self, gboolean use_alt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
self->currently_showing_alt = use_alt;
|
self->currently_showing_alt = use_alt;
|
||||||
gchar *name = use_alt ? self->alt_icon_name : self->icon_name;
|
gchar * name = use_alt ? self->alt_icon_name : self->icon_name;
|
||||||
|
|
||||||
if (GTK_IS_IMAGE(self->button_pic)) {
|
if (GTK_IS_IMAGE(self->button_pic)) {
|
||||||
gtk_image_set_from_icon_name(GTK_IMAGE(self->button_pic), name); // Just update the existing iamge
|
gtk_image_set_from_icon_name(GTK_IMAGE(self->button_pic), name); // Just update the existing iamge
|
||||||
|
@ -461,7 +521,7 @@ void koto_button_show_image(KotoButton *self, gboolean use_alt) {
|
||||||
gtk_widget_show(self->button_pic); // Ensure we actually are showing the image
|
gtk_widget_show(self->button_pic); // Ensure we actually are showing the image
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_button_unflatten(KotoButton *self) {
|
void koto_button_unflatten(KotoButton * self) {
|
||||||
if (!KOTO_IS_BUTTON(self)) {
|
if (!KOTO_IS_BUTTON(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -469,26 +529,44 @@ void koto_button_unflatten(KotoButton *self) {
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(self), "flat");
|
gtk_widget_remove_css_class(GTK_WIDGET(self), "flat");
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoButton* koto_button_new_plain(gchar *label) {
|
KotoButton * koto_button_new_plain(gchar * label) {
|
||||||
return g_object_new(KOTO_TYPE_BUTTON,
|
return g_object_new(
|
||||||
"button-text", label,
|
KOTO_TYPE_BUTTON,
|
||||||
|
"button-text",
|
||||||
|
label,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, gchar *alt_icon_name, KotoButtonPixbufSize size) {
|
KotoButton * koto_button_new_with_icon(
|
||||||
return g_object_new(KOTO_TYPE_BUTTON,
|
gchar * label,
|
||||||
"button-text", label,
|
gchar * icon_name,
|
||||||
"icon-name", icon_name,
|
gchar * alt_icon_name,
|
||||||
"alt-icon-name", alt_icon_name,
|
KotoButtonPixbufSize size
|
||||||
"pixbuf-size", koto_get_pixbuf_size(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
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoButton *koto_button_new_with_file(gchar *label, gchar *file_path, KotoButtonPixbufSize size) {
|
KotoButton * koto_button_new_with_file(
|
||||||
return g_object_new(KOTO_TYPE_BUTTON,
|
gchar * label,
|
||||||
"button-text", label,
|
gchar * file_path,
|
||||||
|
KotoButtonPixbufSize size
|
||||||
|
) {
|
||||||
|
return g_object_new(
|
||||||
|
KOTO_TYPE_BUTTON,
|
||||||
|
"button-text",
|
||||||
|
label,
|
||||||
"use-from-file",
|
"use-from-file",
|
||||||
TRUE,
|
TRUE,
|
||||||
"image-file-path",
|
"image-file-path",
|
||||||
|
|
|
@ -46,26 +46,78 @@ typedef enum {
|
||||||
#define NUM_BUILTIN_SIZES 7
|
#define NUM_BUILTIN_SIZES 7
|
||||||
|
|
||||||
#define KOTO_TYPE_BUTTON (koto_button_get_type())
|
#define KOTO_TYPE_BUTTON (koto_button_get_type())
|
||||||
G_DECLARE_FINAL_TYPE (KotoButton, koto_button, KOTO, BUTTON, GtkBox)
|
G_DECLARE_FINAL_TYPE(KotoButton, koto_button, KOTO, BUTTON, GtkBox)
|
||||||
#define KOTO_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_BUTTON))
|
#define KOTO_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_BUTTON))
|
||||||
|
|
||||||
guint koto_get_pixbuf_size(KotoButtonPixbufSize size);
|
guint koto_get_pixbuf_size(KotoButtonPixbufSize size);
|
||||||
|
|
||||||
KotoButton* koto_button_new_plain(gchar *label);
|
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(
|
||||||
void koto_button_flip(KotoButton *self);
|
gchar * label,
|
||||||
void koto_button_hide_image(KotoButton *self);
|
gchar * icon_name,
|
||||||
void koto_button_set_badge_text(KotoButton *self, gchar *text);
|
gchar * alt_icon_name,
|
||||||
void koto_button_set_file_path(KotoButton *self, gchar *file_path);
|
KotoButtonPixbufSize size
|
||||||
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);
|
KotoButton * koto_button_new_with_file(
|
||||||
void koto_button_set_pixbuf_size(KotoButton *self, guint size);
|
gchar * label,
|
||||||
void koto_button_set_text(KotoButton *self, gchar *text);
|
gchar * file_path,
|
||||||
void koto_button_show_image(KotoButton *self, gboolean use_alt);
|
KotoButtonPixbufSize size
|
||||||
void koto_button_unflatten(KotoButton *self);
|
);
|
||||||
|
|
||||||
|
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_unflatten(KotoButton * self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -22,25 +22,20 @@
|
||||||
|
|
||||||
struct _KotoDialogContainer {
|
struct _KotoDialogContainer {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
KotoButton *close_button;
|
KotoButton * close_button;
|
||||||
GtkWidget *dialogs;
|
GtkWidget * dialogs;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoDialogContainer, koto_dialog_container, GTK_TYPE_BOX);
|
G_DEFINE_TYPE(KotoDialogContainer, koto_dialog_container, GTK_TYPE_BOX);
|
||||||
|
|
||||||
static void koto_dialog_container_class_init(KotoDialogContainerClass *c) {
|
static void koto_dialog_container_class_init(KotoDialogContainerClass * c) {
|
||||||
(void) c;
|
(void) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_dialog_container_init(KotoDialogContainer *self) {
|
static void koto_dialog_container_init(KotoDialogContainer * self) {
|
||||||
gtk_widget_add_css_class(GTK_WIDGET(self), "koto-dialog-container");
|
gtk_widget_add_css_class(GTK_WIDGET(self), "koto-dialog-container");
|
||||||
|
|
||||||
g_object_set(GTK_WIDGET(self),
|
g_object_set(GTK_WIDGET(self), "hexpand", TRUE, "vexpand", TRUE, NULL);
|
||||||
"hexpand",
|
|
||||||
TRUE,
|
|
||||||
"vexpand",
|
|
||||||
TRUE,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
self->close_button = koto_button_new_with_icon(NULL, "window-close-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_LARGE);
|
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);
|
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
|
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
|
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -68,12 +67,21 @@ 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
|
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 koto_dialog_container_handle_close_click(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
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);
|
koto_dialog_container_hide((KotoDialogContainer*) user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_dialog_container_hide(KotoDialogContainer *self) {
|
void koto_dialog_container_hide(KotoDialogContainer * self) {
|
||||||
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +89,10 @@ void koto_dialog_container_hide(KotoDialogContainer *self) {
|
||||||
gtk_widget_hide(GTK_WIDGET(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
|
if (!KOTO_IS_DIALOG_CONTAINER(self)) { // Not a dialog container
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -90,8 +101,9 @@ void koto_dialog_container_show_dialog(KotoDialogContainer *self, gchar *dialog_
|
||||||
gtk_widget_show(GTK_WIDGET(self)); // Ensure we show self
|
gtk_widget_show(GTK_WIDGET(self)); // Ensure we show self
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoDialogContainer* koto_dialog_container_new() {
|
KotoDialogContainer * koto_dialog_container_new() {
|
||||||
return g_object_new(KOTO_TYPE_DIALOG_CONTAINER,
|
return g_object_new(
|
||||||
|
KOTO_TYPE_DIALOG_CONTAINER,
|
||||||
"orientation",
|
"orientation",
|
||||||
GTK_ORIENTATION_VERTICAL,
|
GTK_ORIENTATION_VERTICAL,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -23,7 +23,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_DIALOG_CONTAINER koto_dialog_container_get_type()
|
#define KOTO_TYPE_DIALOG_CONTAINER koto_dialog_container_get_type()
|
||||||
G_DECLARE_FINAL_TYPE(KotoDialogContainer, koto_dialog_container, KOTO, DIALOG_CONTAINER, GtkBox);
|
G_DECLARE_FINAL_TYPE(KotoDialogContainer, koto_dialog_container, KOTO, DIALOG_CONTAINER, GtkBox);
|
||||||
|
@ -31,12 +31,29 @@ G_DECLARE_FINAL_TYPE(KotoDialogContainer, koto_dialog_container, KOTO, DIALOG_CO
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions
|
* Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoDialogContainer* koto_dialog_container_new();
|
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(
|
||||||
void koto_dialog_container_hide(KotoDialogContainer *self);
|
KotoDialogContainer * self,
|
||||||
void koto_dialog_container_show_dialog(KotoDialogContainer *self, gchar *dialog_name);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -30,22 +30,24 @@ enum {
|
||||||
N_EXP_PROPERTIES
|
N_EXP_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *expander_props[N_EXP_PROPERTIES] = { NULL, };
|
static GParamSpec * expander_props[N_EXP_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoExpander {
|
struct _KotoExpander {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
gboolean constructed;
|
gboolean constructed;
|
||||||
GtkWidget *header;
|
GtkWidget * header;
|
||||||
KotoButton *header_button;
|
KotoButton * header_button;
|
||||||
|
|
||||||
gchar *icon_name;
|
gchar * icon_name;
|
||||||
gchar *label;
|
gchar * label;
|
||||||
|
|
||||||
KotoButton *header_secondary_button;
|
KotoButton * header_secondary_button;
|
||||||
KotoButton *header_expand_button;
|
KotoButton * header_expand_button;
|
||||||
|
|
||||||
GtkWidget *revealer;
|
GtkWidget * revealer;
|
||||||
GtkWidget *content;
|
GtkWidget * content;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoExpanderClass {
|
struct _KotoExpanderClass {
|
||||||
|
@ -54,11 +56,24 @@ struct _KotoExpanderClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoExpander, koto_expander, GTK_TYPE_BOX);
|
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_get_property(
|
||||||
static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
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);
|
||||||
|
|
||||||
|
|
||||||
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->set_property = koto_expander_set_property;
|
||||||
gobject_class->get_property = koto_expander_get_property;
|
gobject_class->get_property = koto_expander_get_property;
|
||||||
|
|
||||||
|
@ -67,7 +82,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) {
|
||||||
"Icon Name",
|
"Icon Name",
|
||||||
"Name of the icon to use in the Expander",
|
"Name of the icon to use in the Expander",
|
||||||
"emblem-favorite-symbolic",
|
"emblem-favorite-symbolic",
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
expander_props[PROP_HEADER_LABEL] = g_param_spec_string(
|
expander_props[PROP_HEADER_LABEL] = g_param_spec_string(
|
||||||
|
@ -75,7 +90,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) {
|
||||||
"Label",
|
"Label",
|
||||||
"Label for the Expander",
|
"Label for the Expander",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
expander_props[PROP_HEADER_SECONDARY_BUTTON] = g_param_spec_object(
|
expander_props[PROP_HEADER_SECONDARY_BUTTON] = g_param_spec_object(
|
||||||
|
@ -83,7 +98,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) {
|
||||||
"Secondary Button",
|
"Secondary Button",
|
||||||
"Secondary Button to be placed next to Expander button",
|
"Secondary Button to be placed next to Expander button",
|
||||||
KOTO_TYPE_BUTTON,
|
KOTO_TYPE_BUTTON,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
expander_props[PROP_CONTENT] = g_param_spec_object(
|
expander_props[PROP_CONTENT] = g_param_spec_object(
|
||||||
|
@ -91,14 +106,20 @@ static void koto_expander_class_init(KotoExpanderClass *c) {
|
||||||
"Content",
|
"Content",
|
||||||
"Content inside the Expander",
|
"Content inside the Expander",
|
||||||
GTK_TYPE_WIDGET,
|
GTK_TYPE_WIDGET,
|
||||||
G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_EXP_PROPERTIES, expander_props);
|
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(
|
||||||
KotoExpander *self = KOTO_EXPANDER(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoExpander * self = KOTO_EXPANDER(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_HEADER_ICON_NAME:
|
case PROP_HEADER_ICON_NAME:
|
||||||
|
@ -108,10 +129,10 @@ static void koto_expander_get_property(GObject *obj, guint prop_id, GValue *val,
|
||||||
g_value_set_string(val, self->label);
|
g_value_set_string(val, self->label);
|
||||||
break;
|
break;
|
||||||
case PROP_HEADER_SECONDARY_BUTTON:
|
case PROP_HEADER_SECONDARY_BUTTON:
|
||||||
g_value_set_object(val, (GObject *) self->header_secondary_button);
|
g_value_set_object(val, (GObject*) self->header_secondary_button);
|
||||||
break;
|
break;
|
||||||
case PROP_CONTENT:
|
case PROP_CONTENT:
|
||||||
g_value_set_object(val, (GObject *) self->content);
|
g_value_set_object(val, (GObject*) self->content);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||||
|
@ -119,48 +140,58 @@ 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(
|
||||||
KotoExpander *self = KOTO_EXPANDER(obj);
|
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);
|
|
||||||
|
|
||||||
if (GTK_IS_WIDGET(new_button)) { // Created our widget successfully
|
if (!GTK_IS_WIDGET(self->header_button)) { // Header Button is not a widget
|
||||||
self->header_button = new_button;
|
KotoButton * new_button = koto_button_new_with_icon(NULL, "emblem-favorite-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||||
gtk_widget_set_hexpand(GTK_WIDGET(self->header_button), TRUE);
|
|
||||||
gtk_box_prepend(GTK_BOX(self->header), GTK_WIDGET(self->header_button));
|
if (GTK_IS_WIDGET(new_button)) { // Created our widget successfully
|
||||||
}
|
self->header_button = new_button;
|
||||||
|
gtk_widget_set_hexpand(GTK_WIDGET(self->header_button), TRUE);
|
||||||
|
gtk_box_prepend(GTK_BOX(self->header), GTK_WIDGET(self->header_button));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_HEADER_ICON_NAME:
|
case PROP_HEADER_ICON_NAME:
|
||||||
g_return_if_fail(GTK_IS_WIDGET(self->header_button));
|
g_return_if_fail(GTK_IS_WIDGET(self->header_button));
|
||||||
koto_button_set_icon_name(self->header_button, g_strdup(g_value_get_string(val)), FALSE);
|
koto_button_set_icon_name(self->header_button, g_strdup(g_value_get_string(val)), FALSE);
|
||||||
break;
|
break;
|
||||||
case PROP_HEADER_LABEL:
|
case PROP_HEADER_LABEL:
|
||||||
g_return_if_fail(GTK_IS_WIDGET(self->header_button));
|
g_return_if_fail(GTK_IS_WIDGET(self->header_button));
|
||||||
koto_button_set_text(self->header_button, g_strdup(g_value_get_string(val)));
|
koto_button_set_text(self->header_button, g_strdup(g_value_get_string(val)));
|
||||||
break;
|
break;
|
||||||
case PROP_HEADER_SECONDARY_BUTTON:
|
case PROP_HEADER_SECONDARY_BUTTON:
|
||||||
koto_expander_set_secondary_button(self, (KotoButton*) g_value_get_object(val));
|
koto_expander_set_secondary_button(self, (KotoButton*) g_value_get_object(val));
|
||||||
break;
|
break;
|
||||||
case PROP_CONTENT:
|
case PROP_CONTENT:
|
||||||
koto_expander_set_content(self, (GtkWidget*) g_value_get_object(val));
|
koto_expander_set_content(self, (GtkWidget*) g_value_get_object(val));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_expander_init(KotoExpander *self) {
|
static void koto_expander_init(KotoExpander * self) {
|
||||||
GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
GtkStyleContext * style = gtk_widget_get_style_context(GTK_WIDGET(self));
|
||||||
|
|
||||||
|
|
||||||
gtk_style_context_add_class(style, "expander");
|
gtk_style_context_add_class(style, "expander");
|
||||||
gtk_widget_set_hexpand((GTK_WIDGET(self)), TRUE);
|
gtk_widget_set_hexpand((GTK_WIDGET(self)), TRUE);
|
||||||
|
|
||||||
self->header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
|
self->header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
|
||||||
|
|
||||||
GtkStyleContext *header_style = gtk_widget_get_style_context(self->header);
|
GtkStyleContext * header_style = gtk_widget_get_style_context(self->header);
|
||||||
|
|
||||||
|
|
||||||
gtk_style_context_add_class(header_style, "expander-header");
|
gtk_style_context_add_class(header_style, "expander-header");
|
||||||
|
|
||||||
self->revealer = gtk_revealer_new();
|
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);
|
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) {
|
if (!self->constructed) {
|
||||||
return;
|
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]);
|
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) {
|
if (!self->constructed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -213,34 +250,62 @@ void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content) {
|
||||||
g_object_notify_by_pspec(G_OBJECT(self), expander_props[PROP_CONTENT]);
|
g_object_notify_by_pspec(G_OBJECT(self), expander_props[PROP_CONTENT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_expander_get_content(KotoExpander *self) {
|
GtkWidget * koto_expander_get_content(KotoExpander * self) {
|
||||||
return self->content;
|
return self->content;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_expander_toggle_content(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_expander_toggle_content(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
|
int n_press,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
gpointer data
|
||||||
|
) {
|
||||||
|
(void) gesture;
|
||||||
|
(void) n_press;
|
||||||
|
(void) x;
|
||||||
|
(void) y;
|
||||||
KotoExpander* self = data;
|
KotoExpander* self = data;
|
||||||
|
|
||||||
|
|
||||||
koto_button_flip(KOTO_BUTTON(self->header_expand_button));
|
koto_button_flip(KOTO_BUTTON(self->header_expand_button));
|
||||||
GtkRevealer* rev = GTK_REVEALER(self->revealer);
|
GtkRevealer* rev = GTK_REVEALER(self->revealer);
|
||||||
|
|
||||||
|
|
||||||
gtk_revealer_set_reveal_child(rev, !gtk_revealer_get_reveal_child(rev)); // Invert our values
|
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) {
|
KotoExpander * koto_expander_new(
|
||||||
return g_object_new(KOTO_TYPE_EXPANDER,
|
gchar * primary_icon_name,
|
||||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
gchar * primary_label_text
|
||||||
"icon-name", primary_icon_name,
|
) {
|
||||||
"label", primary_label_text,
|
return g_object_new(
|
||||||
|
KOTO_TYPE_EXPANDER,
|
||||||
|
"orientation",
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
|
"icon-name",
|
||||||
|
primary_icon_name,
|
||||||
|
"label",
|
||||||
|
primary_label_text,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, KotoButton *secondary_button) {
|
KotoExpander * koto_expander_new_with_button(
|
||||||
return g_object_new(KOTO_TYPE_EXPANDER,
|
gchar * primary_icon_name,
|
||||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
gchar * primary_label_text,
|
||||||
"icon-name", primary_icon_name,
|
KotoButton * secondary_button
|
||||||
"label", primary_label_text,
|
) {
|
||||||
"secondary-button", 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
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,44 @@
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_EXPANDER (koto_expander_get_type())
|
#define KOTO_TYPE_EXPANDER (koto_expander_get_type())
|
||||||
G_DECLARE_FINAL_TYPE (KotoExpander, koto_expander, KOTO, EXPANDER, GtkBox)
|
G_DECLARE_FINAL_TYPE(KotoExpander, koto_expander, KOTO, EXPANDER, GtkBox)
|
||||||
#define KOTO_IS_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_EXPANDER))
|
#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(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(
|
||||||
GtkWidget* koto_expander_get_content(KotoExpander *self);
|
gchar * primary_icon_name,
|
||||||
void koto_expander_set_icon_name(KotoExpander *self, const gchar *in);
|
gchar * primary_label_text,
|
||||||
void koto_expander_set_label(KotoExpander *self, const gchar *label);
|
KotoButton * secondary_button
|
||||||
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);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
189
src/koto-nav.c
189
src/koto-nav.c
|
@ -26,39 +26,39 @@
|
||||||
#include "koto-utils.h"
|
#include "koto-utils.h"
|
||||||
#include "koto-window.h"
|
#include "koto-window.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoWindow *main_window;
|
extern KotoWindow * main_window;
|
||||||
|
|
||||||
struct _KotoNav {
|
struct _KotoNav {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
GtkWidget *win;
|
GtkWidget * win;
|
||||||
GtkWidget *content;
|
GtkWidget * content;
|
||||||
|
|
||||||
KotoButton *home_button;
|
KotoButton * home_button;
|
||||||
KotoExpander *audiobook_expander;
|
KotoExpander * audiobook_expander;
|
||||||
KotoExpander *music_expander;
|
KotoExpander * music_expander;
|
||||||
KotoExpander *podcast_expander;
|
KotoExpander * podcast_expander;
|
||||||
KotoExpander *playlists_expander;
|
KotoExpander * playlists_expander;
|
||||||
|
|
||||||
// Audiobooks
|
// Audiobooks
|
||||||
|
|
||||||
KotoButton *audiobooks_local;
|
KotoButton * audiobooks_local;
|
||||||
KotoButton *audiobooks_audible;
|
KotoButton * audiobooks_audible;
|
||||||
KotoButton *audiobooks_librivox;
|
KotoButton * audiobooks_librivox;
|
||||||
|
|
||||||
// Music
|
// Music
|
||||||
|
|
||||||
KotoButton *music_local;
|
KotoButton * music_local;
|
||||||
KotoButton *music_radio;
|
KotoButton * music_radio;
|
||||||
|
|
||||||
// Playlists
|
// Playlists
|
||||||
|
|
||||||
GHashTable *playlist_buttons;
|
GHashTable * playlist_buttons;
|
||||||
|
|
||||||
// Podcasts
|
// Podcasts
|
||||||
|
|
||||||
KotoButton *podcasts_local;
|
KotoButton * podcasts_local;
|
||||||
KotoButton *podcasts_discover;
|
KotoButton * podcasts_discover;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoNavClass {
|
struct _KotoNavClass {
|
||||||
|
@ -67,11 +67,11 @@ struct _KotoNavClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoNav, koto_nav, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoNav, koto_nav, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void koto_nav_class_init(KotoNavClass *c) {
|
static void koto_nav_class_init(KotoNavClass * c) {
|
||||||
(void) c;
|
(void) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_nav_init(KotoNav *self) {
|
static void koto_nav_init(KotoNav * self) {
|
||||||
self->playlist_buttons = g_hash_table_new(g_str_hash, g_str_equal);
|
self->playlist_buttons = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
self->win = gtk_scrolled_window_new();
|
self->win = gtk_scrolled_window_new();
|
||||||
gtk_widget_set_hexpand_set(self->win, TRUE); // using hexpand-set works, hexpand seems to break it by causing it to take up way too much space
|
gtk_widget_set_hexpand_set(self->win, TRUE); // using hexpand-set works, hexpand seems to break it by causing it to take up way too much space
|
||||||
|
@ -88,7 +88,8 @@ static void koto_nav_init(KotoNav *self) {
|
||||||
|
|
||||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->win), self->content);
|
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->win), self->content);
|
||||||
|
|
||||||
KotoButton *h_button = koto_button_new_with_icon("Home", "user-home-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
KotoButton * h_button = koto_button_new_with_icon("Home", "user-home-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||||
|
|
||||||
|
|
||||||
if (h_button != NULL) {
|
if (h_button != NULL) {
|
||||||
self->home_button = h_button;
|
self->home_button = h_button;
|
||||||
|
@ -101,13 +102,16 @@ static void koto_nav_init(KotoNav *self) {
|
||||||
koto_nav_create_playlist_section(self);
|
koto_nav_create_playlist_section(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_nav_create_audiobooks_section(KotoNav *self) {
|
void koto_nav_create_audiobooks_section(KotoNav * self) {
|
||||||
KotoExpander *a_expander = koto_expander_new("ephy-bookmarks-symbolic", "Audiobooks");
|
KotoExpander * a_expander = koto_expander_new("ephy-bookmarks-symbolic", "Audiobooks");
|
||||||
|
|
||||||
|
|
||||||
self->audiobook_expander = a_expander;
|
self->audiobook_expander = a_expander;
|
||||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->audiobook_expander));
|
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->audiobook_expander));
|
||||||
|
|
||||||
GtkWidget *new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
|
|
||||||
koto_expander_set_content(a_expander, new_content);
|
koto_expander_set_content(a_expander, new_content);
|
||||||
|
|
||||||
self->audiobooks_local = koto_button_new_plain("Local Library");
|
self->audiobooks_local = koto_button_new_plain("Local Library");
|
||||||
|
@ -119,12 +123,15 @@ void koto_nav_create_audiobooks_section(KotoNav *self) {
|
||||||
gtk_box_append(GTK_BOX(new_content), GTK_WIDGET(self->audiobooks_librivox));
|
gtk_box_append(GTK_BOX(new_content), GTK_WIDGET(self->audiobooks_librivox));
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_nav_create_music_section(KotoNav *self) {
|
void koto_nav_create_music_section(KotoNav * self) {
|
||||||
KotoExpander *m_expander = koto_expander_new("emblem-music-symbolic", "Music");
|
KotoExpander * m_expander = koto_expander_new("emblem-music-symbolic", "Music");
|
||||||
|
|
||||||
|
|
||||||
self->music_expander = m_expander;
|
self->music_expander = m_expander;
|
||||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->music_expander));
|
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->music_expander));
|
||||||
|
|
||||||
GtkWidget *new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
|
|
||||||
self->music_local = koto_button_new_plain("Local Library");
|
self->music_local = koto_button_new_plain("Local Library");
|
||||||
self->music_radio = koto_button_new_plain("Radio");
|
self->music_radio = koto_button_new_plain("Radio");
|
||||||
|
@ -136,15 +143,17 @@ void koto_nav_create_music_section(KotoNav *self) {
|
||||||
koto_button_add_click_handler(self->music_local, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_nav_handle_local_music_click), NULL);
|
koto_button_add_click_handler(self->music_local, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_nav_handle_local_music_click), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_nav_create_playlist_section(KotoNav *self) {
|
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);
|
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);
|
KotoExpander * pl_expander = koto_expander_new_with_button("playlist-symbolic", "Playlists", playlist_add_button);
|
||||||
|
|
||||||
|
|
||||||
self->playlists_expander = pl_expander;
|
self->playlists_expander = pl_expander;
|
||||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->playlists_expander));
|
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->playlists_expander));
|
||||||
|
|
||||||
// TODO: Turn into ListBox to sort playlists
|
// TODO: Turn into ListBox to sort playlists
|
||||||
GtkWidget *playlist_list = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
GtkWidget * playlist_list = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
|
|
||||||
koto_expander_set_content(self->playlists_expander, playlist_list);
|
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);
|
koto_button_add_click_handler(playlist_add_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_nav_handle_playlist_add_click), NULL);
|
||||||
|
@ -153,12 +162,15 @@ void koto_nav_create_playlist_section(KotoNav *self) {
|
||||||
g_signal_connect(koto_maps, "playlist-removed", G_CALLBACK(koto_nav_handle_playlist_removed), self);
|
g_signal_connect(koto_maps, "playlist-removed", G_CALLBACK(koto_nav_handle_playlist_removed), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_nav_create_podcasts_section(KotoNav *self) {
|
void koto_nav_create_podcasts_section(KotoNav * self) {
|
||||||
KotoExpander *p_expander = koto_expander_new("microphone-sensitivity-high-symbolic", "Podcasts");
|
KotoExpander * p_expander = koto_expander_new("microphone-sensitivity-high-symbolic", "Podcasts");
|
||||||
|
|
||||||
|
|
||||||
self->podcast_expander = p_expander;
|
self->podcast_expander = p_expander;
|
||||||
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->podcast_expander));
|
gtk_box_append(GTK_BOX(self->content), GTK_WIDGET(self->podcast_expander));
|
||||||
|
|
||||||
GtkWidget *new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
GtkWidget * new_content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
|
|
||||||
self->podcasts_local = koto_button_new_plain("Library");
|
self->podcasts_local = koto_button_new_plain("Library");
|
||||||
self->podcasts_discover = koto_button_new_plain("Find New Podcasts");
|
self->podcasts_discover = koto_button_new_plain("Find New Podcasts");
|
||||||
|
@ -169,43 +181,82 @@ void koto_nav_create_podcasts_section(KotoNav *self) {
|
||||||
koto_expander_set_content(p_expander, new_content);
|
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 koto_nav_handle_playlist_add_click(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) user_data;
|
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");
|
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 koto_nav_handle_local_music_click(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) user_data;
|
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
|
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 koto_nav_handle_playlist_button_click(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
gchar *playlist_uuid = user_data;
|
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
|
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;
|
(void) carto;
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoNav *self = user_data;
|
KotoNav * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_NAV(self)) {
|
if (!KOTO_IS_NAV(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID for a playlist
|
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
|
if (g_hash_table_contains(self->playlist_buttons, playlist_uuid)) { // Already added button
|
||||||
g_free(playlist_uuid);
|
g_free(playlist_uuid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *playlist_name = koto_playlist_get_name(playlist);
|
gchar * playlist_name = koto_playlist_get_name(playlist);
|
||||||
gchar *playlist_art_path = koto_playlist_get_artwork(playlist); // Get any file path for it
|
gchar * playlist_art_path = koto_playlist_get_artwork(playlist); // Get any file path for it
|
||||||
KotoButton *playlist_button = NULL;
|
KotoButton * playlist_button = NULL;
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(playlist_art_path)) { // Have a file associated
|
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);
|
playlist_button = koto_button_new_with_file(playlist_name, playlist_art_path, KOTO_BUTTON_PIXBUF_SIZE_NORMAL);
|
||||||
|
@ -217,7 +268,7 @@ void koto_nav_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playl
|
||||||
g_hash_table_insert(self->playlist_buttons, playlist_uuid, playlist_button); // Add the button
|
g_hash_table_insert(self->playlist_buttons, playlist_uuid, playlist_button); // Add the button
|
||||||
|
|
||||||
// TODO: Make this a ListBox and sort the playlists alphabetically
|
// TODO: Make this a ListBox and sort the playlists alphabetically
|
||||||
GtkBox *playlist_expander_content = GTK_BOX(koto_expander_get_content(self->playlists_expander));
|
GtkBox * playlist_expander_content = GTK_BOX(koto_expander_get_content(self->playlists_expander));
|
||||||
|
|
||||||
if (GTK_IS_BOX(playlist_expander_content)) {
|
if (GTK_IS_BOX(playlist_expander_content)) {
|
||||||
gtk_box_append(playlist_expander_content, GTK_WIDGET(playlist_button));
|
gtk_box_append(playlist_expander_content, GTK_WIDGET(playlist_button));
|
||||||
|
@ -229,58 +280,76 @@ 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)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoNav *self = user_data;
|
KotoNav * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_NAV(self)) {
|
if (!KOTO_IS_NAV(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID for a playlist
|
gchar * playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID for a playlist
|
||||||
|
|
||||||
|
KotoButton * playlist_button = g_hash_table_lookup(self->playlist_buttons, playlist_uuid);
|
||||||
|
|
||||||
KotoButton *playlist_button = g_hash_table_lookup(self->playlist_buttons, playlist_uuid);
|
|
||||||
|
|
||||||
if (!KOTO_IS_BUTTON(playlist_button)) {
|
if (!KOTO_IS_BUTTON(playlist_button)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
gchar * artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(artwork)) { // Have valid artwork
|
if (koto_utils_is_string_valid(artwork)) { // Have valid artwork
|
||||||
koto_button_set_file_path(playlist_button, artwork); // Update the artwork path
|
koto_button_set_file_path(playlist_button, artwork); // Update the artwork path
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *name = koto_playlist_get_name(playlist); // Get the name
|
gchar * name = koto_playlist_get_name(playlist); // Get the name
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(name)) { // Have valid name
|
if (koto_utils_is_string_valid(name)) { // Have valid name
|
||||||
koto_button_set_text(playlist_button, name); // Update the button text
|
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;
|
(void) carto;
|
||||||
KotoNav *self = user_data;
|
KotoNav * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!g_hash_table_contains(self->playlist_buttons, playlist_uuid)) { // Does not contain this
|
if (!g_hash_table_contains(self->playlist_buttons, playlist_uuid)) { // Does not contain this
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoButton *playlist_btn = g_hash_table_lookup(self->playlist_buttons, playlist_uuid); // Get the playlist button
|
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
|
if (!KOTO_IS_BUTTON(playlist_btn)) { // Not a playlist button
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkBox *playlist_expander_content = GTK_BOX(koto_expander_get_content(self->playlists_expander));
|
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
|
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
|
g_hash_table_remove(self->playlist_buttons, playlist_uuid); // Remove from the playlist buttons hash table
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_nav_get_nav(KotoNav *self) {
|
GtkWidget * koto_nav_get_nav(KotoNav * self) {
|
||||||
return self->win;
|
return self->win;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoNav* koto_nav_new(void) {
|
KotoNav * koto_nav_new(void) {
|
||||||
return g_object_new(KOTO_TYPE_NAV ,NULL);
|
return g_object_new(KOTO_TYPE_NAV, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,19 +24,50 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_NAV (koto_nav_get_type())
|
#define KOTO_TYPE_NAV (koto_nav_get_type())
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (KotoNav, koto_nav, KOTO, NAV, GObject)
|
G_DECLARE_FINAL_TYPE(KotoNav, koto_nav, KOTO, NAV, GObject)
|
||||||
|
|
||||||
KotoNav* koto_nav_new (void);
|
KotoNav* koto_nav_new(void);
|
||||||
void koto_nav_create_audiobooks_section(KotoNav *self);
|
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);
|
|
||||||
|
|
||||||
GtkWidget* koto_nav_get_nav(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
|
||||||
|
);
|
||||||
|
|
||||||
|
GtkWidget * koto_nav_get_nav(KotoNav * self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -26,40 +26,40 @@
|
||||||
#include "koto-config.h"
|
#include "koto-config.h"
|
||||||
#include "koto-playerbar.h"
|
#include "koto-playerbar.h"
|
||||||
|
|
||||||
extern KotoAddRemoveTrackPopover *koto_add_remove_track_popup;
|
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoPlaybackEngine *playback_engine;
|
extern KotoPlaybackEngine * playback_engine;
|
||||||
|
|
||||||
struct _KotoPlayerBar {
|
struct _KotoPlayerBar {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
GtkWidget *main;
|
GtkWidget * main;
|
||||||
GtkWidget *controls;
|
GtkWidget * controls;
|
||||||
|
|
||||||
/* Sections */
|
/* Sections */
|
||||||
GtkWidget *playback_section;
|
GtkWidget * playback_section;
|
||||||
GtkWidget *primary_controls_section;
|
GtkWidget * primary_controls_section;
|
||||||
GtkWidget *secondary_controls_section;
|
GtkWidget * secondary_controls_section;
|
||||||
|
|
||||||
/* Primary Buttons */
|
/* Primary Buttons */
|
||||||
KotoButton *back_button;
|
KotoButton * back_button;
|
||||||
KotoButton *play_pause_button;
|
KotoButton * play_pause_button;
|
||||||
KotoButton *forward_button;
|
KotoButton * forward_button;
|
||||||
KotoButton *repeat_button;
|
KotoButton * repeat_button;
|
||||||
KotoButton *shuffle_button;
|
KotoButton * shuffle_button;
|
||||||
KotoButton *playlist_button;
|
KotoButton * playlist_button;
|
||||||
KotoButton *eq_button;
|
KotoButton * eq_button;
|
||||||
GtkWidget *volume_button;
|
GtkWidget * volume_button;
|
||||||
|
|
||||||
GtkWidget *progress_bar;
|
GtkWidget * progress_bar;
|
||||||
|
|
||||||
/* Selected Playback Section */
|
/* Selected Playback Section */
|
||||||
|
|
||||||
GtkWidget *playback_details_section;
|
GtkWidget * playback_details_section;
|
||||||
GtkWidget *artwork;
|
GtkWidget * artwork;
|
||||||
GtkWidget *playback_title;
|
GtkWidget * playback_title;
|
||||||
GtkWidget *playback_album;
|
GtkWidget * playback_album;
|
||||||
GtkWidget *playback_artist;
|
GtkWidget * playback_artist;
|
||||||
|
|
||||||
gint64 last_recorded_duration;
|
gint64 last_recorded_duration;
|
||||||
|
|
||||||
|
@ -72,17 +72,21 @@ struct _KotoPlayerBarClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPlayerBar, koto_playerbar, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoPlayerBar, koto_playerbar, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void koto_playerbar_constructed(GObject *obj);
|
static void koto_playerbar_constructed(GObject * obj);
|
||||||
|
|
||||||
|
static void koto_playerbar_class_init(KotoPlayerBarClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
|
|
||||||
static void koto_playerbar_class_init(KotoPlayerBarClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
|
|
||||||
gobject_class->constructed = koto_playerbar_constructed;
|
gobject_class->constructed = koto_playerbar_constructed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playerbar_constructed(GObject *obj) {
|
static void koto_playerbar_constructed(GObject * obj) {
|
||||||
KotoPlayerBar *self = KOTO_PLAYERBAR(obj);
|
KotoPlayerBar * self = KOTO_PLAYERBAR(obj);
|
||||||
|
|
||||||
|
|
||||||
self->main = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
self->main = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_widget_add_css_class(self->main, "player-bar");
|
gtk_widget_add_css_class(self->main, "player-bar");
|
||||||
|
|
||||||
|
@ -93,7 +97,9 @@ static void koto_playerbar_constructed(GObject *obj) {
|
||||||
gtk_range_set_increments(GTK_RANGE(self->progress_bar), 1, 1);
|
gtk_range_set_increments(GTK_RANGE(self->progress_bar), 1, 1);
|
||||||
gtk_range_set_round_digits(GTK_RANGE(self->progress_bar), 1);
|
gtk_range_set_round_digits(GTK_RANGE(self->progress_bar), 1);
|
||||||
|
|
||||||
GtkGesture *press_controller = gtk_gesture_click_new(); // Create a new GtkGestureLongPress
|
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
|
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);
|
g_signal_connect(press_controller, "begin", G_CALLBACK(koto_playerbar_handle_progressbar_gesture_begin), self);
|
||||||
|
@ -140,19 +146,20 @@ static void koto_playerbar_constructed(GObject *obj) {
|
||||||
g_signal_connect(playback_engine, "track-shuffle-changed", G_CALLBACK(koto_playerbar_handle_track_shuffle), self);
|
g_signal_connect(playback_engine, "track-shuffle-changed", G_CALLBACK(koto_playerbar_handle_track_shuffle), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playerbar_init(KotoPlayerBar *self) {
|
static void koto_playerbar_init(KotoPlayerBar * self) {
|
||||||
self->last_recorded_duration = 0;
|
self->last_recorded_duration = 0;
|
||||||
self->is_progressbar_seeking = FALSE;
|
self->is_progressbar_seeking = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar* koto_playerbar_new(void) {
|
KotoPlayerBar * koto_playerbar_new(void) {
|
||||||
return g_object_new(KOTO_TYPE_PLAYERBAR, NULL);
|
return g_object_new(KOTO_TYPE_PLAYERBAR, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_create_playback_details(KotoPlayerBar* bar) {
|
void koto_playerbar_create_playback_details(KotoPlayerBar* bar) {
|
||||||
bar->playback_details_section = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
bar->playback_details_section = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
GtkIconTheme *default_icon_theme = gtk_icon_theme_get_for_display(gdk_display_get_default()); // Get the icon theme for this display
|
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) {
|
if (default_icon_theme != NULL) {
|
||||||
gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(bar->main));
|
gint scale_factor = gtk_widget_get_scale_factor(GTK_WIDGET(bar->main));
|
||||||
|
@ -235,7 +242,7 @@ void koto_playerbar_create_secondary_controls(KotoPlayerBar* bar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GTK_IS_VOLUME_BUTTON(bar->volume_button)) {
|
if (GTK_IS_VOLUME_BUTTON(bar->volume_button)) {
|
||||||
GtkAdjustment *granular_volume_change = gtk_adjustment_new(0.5, 0, 1.0, 0.02, 0.02, 0.02);
|
GtkAdjustment * granular_volume_change = gtk_adjustment_new(0.5, 0, 1.0, 0.02, 0.02, 0.02);
|
||||||
g_object_set(bar->volume_button, "use-symbolic", TRUE, NULL);
|
g_object_set(bar->volume_button, "use-symbolic", TRUE, NULL);
|
||||||
gtk_scale_button_set_adjustment(GTK_SCALE_BUTTON(bar->volume_button), granular_volume_change); // Set our adjustment
|
gtk_scale_button_set_adjustment(GTK_SCALE_BUTTON(bar->volume_button), granular_volume_change); // Set our adjustment
|
||||||
gtk_box_append(GTK_BOX(bar->secondary_controls_section), bar->volume_button);
|
gtk_box_append(GTK_BOX(bar->secondary_controls_section), bar->volume_button);
|
||||||
|
@ -245,24 +252,48 @@ 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_backwards(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
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);
|
koto_playback_engine_backwards(playback_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_go_forwards(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_playerbar_go_forwards(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
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);
|
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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -271,12 +302,16 @@ 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
|
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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -285,9 +320,19 @@ 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
|
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 koto_playerbar_handle_playlist_button_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlayerBar *self = data;
|
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
|
if (!KOTO_IS_PLAYERBAR(self)) { // Not a playerbar
|
||||||
return;
|
return;
|
||||||
|
@ -297,9 +342,15 @@ void koto_playerbar_handle_playlist_button_clicked(GtkGestureClick *gesture, int
|
||||||
gtk_widget_show(GTK_WIDGET(koto_add_remove_track_popup));
|
gtk_widget_show(GTK_WIDGET(koto_add_remove_track_popup));
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
void koto_playerbar_handle_progressbar_gesture_begin(
|
||||||
(void) gesture; (void) seq;
|
GtkGesture * gesture,
|
||||||
KotoPlayerBar *bar = data;
|
GdkEventSequence * seq,
|
||||||
|
gpointer data
|
||||||
|
) {
|
||||||
|
(void) gesture;
|
||||||
|
(void) seq;
|
||||||
|
KotoPlayerBar * bar = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -308,9 +359,15 @@ void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEve
|
||||||
bar->is_progressbar_seeking = TRUE;
|
bar->is_progressbar_seeking = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_gesture_end(GtkGesture *gesture, GdkEventSequence *seq, gpointer data) {
|
void koto_playerbar_handle_progressbar_gesture_end(
|
||||||
(void) gesture; (void) seq;
|
GtkGesture * gesture,
|
||||||
KotoPlayerBar *bar = data;
|
GdkEventSequence * seq,
|
||||||
|
gpointer data
|
||||||
|
) {
|
||||||
|
(void) gesture;
|
||||||
|
(void) seq;
|
||||||
|
KotoPlayerBar * bar = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -318,9 +375,19 @@ void koto_playerbar_handle_progressbar_gesture_end(GtkGesture *gesture, GdkEvent
|
||||||
bar->is_progressbar_seeking = FALSE;
|
bar->is_progressbar_seeking = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_playerbar_handle_progressbar_pressed(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlayerBar *bar = data;
|
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)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -329,8 +396,12 @@ void koto_playerbar_handle_progressbar_pressed(GtkGestureClick *gesture, int n_p
|
||||||
bar->is_progressbar_seeking = TRUE;
|
bar->is_progressbar_seeking = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpointer data) {
|
void koto_playerbar_handle_progressbar_value_changed(
|
||||||
KotoPlayerBar *bar = data;
|
GtkRange * progress_bar,
|
||||||
|
gpointer data
|
||||||
|
) {
|
||||||
|
KotoPlayerBar * bar = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -342,15 +413,20 @@ void koto_playerbar_handle_progressbar_value_changed(GtkRange *progress_bar, gpo
|
||||||
|
|
||||||
int desired_position = (int) gtk_range_get_value(progress_bar);
|
int desired_position = (int) gtk_range_get_value(progress_bar);
|
||||||
|
|
||||||
|
|
||||||
koto_playback_engine_set_position(playback_engine, desired_position); // Update our position
|
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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -360,12 +436,16 @@ 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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -376,12 +456,16 @@ 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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
|
@ -394,12 +478,16 @@ 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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
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 koto_playerbar_handle_volume_button_change(
|
||||||
(void) button; (void) user_data;
|
GtkScaleButton * button,
|
||||||
|
double value,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
(void) button;
|
||||||
|
(void) user_data;
|
||||||
koto_playback_engine_set_volume(playback_engine, value);
|
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
|
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) {
|
if (duration <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -433,52 +529,92 @@ 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);
|
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 koto_playerbar_toggle_play_pause(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
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);
|
koto_playback_engine_toggle(playback_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playerbar_toggle_playlist_shuffle(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
void koto_playerbar_toggle_playlist_shuffle(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
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
|
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 koto_playerbar_toggle_track_repeat(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y; (void) data;
|
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
|
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)) {
|
if (!KOTO_IS_PLAYBACK_ENGINE(engine)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlayerBar *bar = user_data;
|
KotoPlayerBar * bar = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYERBAR(bar)) {
|
if (!KOTO_IS_PLAYERBAR(bar)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack *current_track = koto_playback_engine_get_current_track(playback_engine); // Get the current track from the playback engine
|
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)) {
|
if (!KOTO_IS_INDEXED_TRACK(current_track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *track_name = NULL;
|
gchar * track_name = NULL;
|
||||||
gchar *artist_uuid = NULL;
|
gchar * artist_uuid = NULL;
|
||||||
gchar *album_uuid = NULL;
|
gchar * album_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(current_track, "parsed-name", &track_name, "artist-uuid", &artist_uuid, "album-uuid", &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);
|
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid);
|
||||||
KotoIndexedAlbum *album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||||
|
|
||||||
|
|
||||||
g_free(artist_uuid);
|
g_free(artist_uuid);
|
||||||
g_free(album_uuid);
|
g_free(album_uuid);
|
||||||
|
@ -488,7 +624,7 @@ void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_ARTIST(artist)) {
|
if (KOTO_IS_INDEXED_ARTIST(artist)) {
|
||||||
gchar *artist_name = NULL;
|
gchar * artist_name = NULL;
|
||||||
g_object_get(artist, "name", &artist_name, NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
|
|
||||||
if ((artist_name != NULL) && (strcmp(artist_name, "") != 0)) { // Have an artist name
|
if ((artist_name != NULL) && (strcmp(artist_name, "") != 0)) { // Have an artist name
|
||||||
|
@ -500,8 +636,8 @@ void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_ALBUM(album)) {
|
if (KOTO_IS_INDEXED_ALBUM(album)) {
|
||||||
gchar *album_name = NULL;
|
gchar * album_name = NULL;
|
||||||
gchar *art_path = NULL;
|
gchar * art_path = NULL;
|
||||||
g_object_get(album, "name", &album_name, "art-path", &art_path, NULL); // Get album name and art path
|
g_object_get(album, "name", &album_name, "art-path", &art_path, NULL); // Get album name and art path
|
||||||
|
|
||||||
if ((album_name != NULL) && (strcmp(album_name, "") != 0)) { // Have an album name
|
if ((album_name != NULL) && (strcmp(album_name, "") != 0)) { // Have an album name
|
||||||
|
@ -519,6 +655,6 @@ void koto_playerbar_update_track_info(KotoPlaybackEngine *engine, gpointer user_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_playerbar_get_main(KotoPlayerBar* bar) {
|
GtkWidget * koto_playerbar_get_main(KotoPlayerBar* bar) {
|
||||||
return bar->main;
|
return bar->main;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,35 +23,147 @@
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_PLAYERBAR (koto_playerbar_get_type())
|
#define KOTO_TYPE_PLAYERBAR (koto_playerbar_get_type())
|
||||||
G_DECLARE_FINAL_TYPE (KotoPlayerBar, koto_playerbar, KOTO, PLAYERBAR, GObject)
|
G_DECLARE_FINAL_TYPE(KotoPlayerBar, koto_playerbar, KOTO, PLAYERBAR, GObject)
|
||||||
#define KOTO_IS_PLAYERBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYERBAR))
|
#define KOTO_IS_PLAYERBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYERBAR))
|
||||||
|
|
||||||
KotoPlayerBar* koto_playerbar_new (void);
|
KotoPlayerBar * koto_playerbar_new(void);
|
||||||
GtkWidget* koto_playerbar_get_main(KotoPlayerBar* bar);
|
GtkWidget * koto_playerbar_get_main(KotoPlayerBar* bar);
|
||||||
|
|
||||||
void koto_playerbar_create_playback_details(KotoPlayerBar* bar);
|
void koto_playerbar_create_playback_details(KotoPlayerBar* bar);
|
||||||
|
|
||||||
void koto_playerbar_create_primary_controls(KotoPlayerBar* bar);
|
void koto_playerbar_create_primary_controls(KotoPlayerBar* bar);
|
||||||
|
|
||||||
void koto_playerbar_create_secondary_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_go_backwards(
|
||||||
void koto_playerbar_handle_is_playing(KotoPlaybackEngine *engine, gpointer user_data);
|
GtkGestureClick * gesture,
|
||||||
void koto_playerbar_handle_is_paused(KotoPlaybackEngine *engine, gpointer user_data);
|
int n_press,
|
||||||
void koto_playerbar_handle_playlist_button_clicked(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
double x,
|
||||||
void koto_playerbar_handle_progressbar_scroll_begin(GtkEventControllerScroll *controller, gpointer data);
|
double y,
|
||||||
void koto_playerbar_handle_progressbar_gesture_begin(GtkGesture *gesture, GdkEventSequence *seq, gpointer data);
|
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_go_forwards(
|
||||||
void koto_playerbar_handle_tick_duration(KotoPlaybackEngine *engine, gpointer user_data);
|
GtkGestureClick * gesture,
|
||||||
void koto_playerbar_handle_tick_track(KotoPlaybackEngine *engine, gpointer user_data);
|
int n_press,
|
||||||
void koto_playerbar_handle_track_repeat(KotoPlaybackEngine *engine, gpointer user_data);
|
double x,
|
||||||
void koto_playerbar_handle_track_shuffle(KotoPlaybackEngine *engine, gpointer user_data);
|
double y,
|
||||||
void koto_playerbar_handle_volume_button_change(GtkScaleButton *button, double value, gpointer user_data);
|
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_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_set_progressbar_duration(
|
||||||
void koto_playerbar_toggle_play_pause(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
KotoPlayerBar* bar,
|
||||||
void koto_playerbar_toggle_playlist_shuffle(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
gint64 duration
|
||||||
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_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
|
G_END_DECLS
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
#include "koto-button.h"
|
#include "koto-button.h"
|
||||||
#include "koto-track-item.h"
|
#include "koto-track-item.h"
|
||||||
|
|
||||||
extern KotoAddRemoveTrackPopover *koto_add_remove_track_popup;
|
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup;
|
||||||
|
|
||||||
struct _KotoTrackItem {
|
struct _KotoTrackItem {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
KotoIndexedTrack *track;
|
KotoIndexedTrack * track;
|
||||||
|
|
||||||
GtkWidget *track_label;
|
GtkWidget * track_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoTrackItemClass {
|
struct _KotoTrackItemClass {
|
||||||
|
@ -40,15 +40,30 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoTrackItem, koto_track_item, GTK_TYPE_BOX);
|
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_get_property(
|
||||||
static void koto_track_item_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_track_item_class_init(KotoTrackItemClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_track_item_set_property;
|
gobject_class->set_property = koto_track_item_set_property;
|
||||||
gobject_class->get_property = koto_track_item_get_property;
|
gobject_class->get_property = koto_track_item_get_property;
|
||||||
|
@ -58,14 +73,20 @@ static void koto_track_item_class_init(KotoTrackItemClass *c) {
|
||||||
"Track",
|
"Track",
|
||||||
"Track",
|
"Track",
|
||||||
KOTO_TYPE_INDEXED_TRACK,
|
KOTO_TYPE_INDEXED_TRACK,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
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(
|
||||||
KotoTrackItem *self = KOTO_TRACK_ITEM(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoTrackItem * self = KOTO_TRACK_ITEM(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_TRACK:
|
case PROP_TRACK:
|
||||||
|
@ -77,8 +98,14 @@ 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(
|
||||||
KotoTrackItem *self = KOTO_TRACK_ITEM(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoTrackItem * self = KOTO_TRACK_ITEM(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_TRACK:
|
case PROP_TRACK:
|
||||||
|
@ -90,7 +117,7 @@ static void koto_track_item_set_property(GObject *obj, guint prop_id, const GVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_track_item_init(KotoTrackItem *self) {
|
static void koto_track_item_init(KotoTrackItem * self) {
|
||||||
self->track_label = gtk_label_new(NULL); // Create with no track name
|
self->track_label = gtk_label_new(NULL); // Create with no track name
|
||||||
gtk_label_set_xalign(GTK_LABEL(self->track_label), 0.0);
|
gtk_label_set_xalign(GTK_LABEL(self->track_label), 0.0);
|
||||||
|
|
||||||
|
@ -101,23 +128,29 @@ static void koto_track_item_init(KotoTrackItem *self) {
|
||||||
gtk_box_prepend(GTK_BOX(self), self->track_label);
|
gtk_box_prepend(GTK_BOX(self), self->track_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack* koto_track_item_get_track(KotoTrackItem *self) {
|
KotoIndexedTrack * koto_track_item_get_track(KotoTrackItem * self) {
|
||||||
return self->track;
|
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
|
if (track == NULL) { // Not a track
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->track = track;
|
self->track = track;
|
||||||
gchar *track_name;
|
gchar * track_name;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(self->track, "parsed-name", &track_name, NULL);
|
g_object_get(self->track, "parsed-name", &track_name, NULL);
|
||||||
gtk_label_set_text(GTK_LABEL(self->track_label), track_name); // Update the text
|
gtk_label_set_text(GTK_LABEL(self->track_label), track_name); // Update the text
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoTrackItem* koto_track_item_new(KotoIndexedTrack *track) {
|
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",
|
||||||
track,
|
track,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -27,9 +27,20 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(KotoTrackItem, koto_track_item, KOTO, TRACK_ITEM, GtkBox)
|
G_DECLARE_FINAL_TYPE(KotoTrackItem, koto_track_item, KOTO, TRACK_ITEM, GtkBox)
|
||||||
|
|
||||||
KotoTrackItem* koto_track_item_new(KotoIndexedTrack *track);
|
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(
|
||||||
KotoIndexedTrack* koto_track_item_get_track(KotoTrackItem *self);
|
GtkGestureClick * gesture,
|
||||||
void koto_track_item_set_track(KotoTrackItem *self, KotoIndexedTrack *track);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
#include <glib-2.0/glib.h>
|
#include <glib-2.0/glib.h>
|
||||||
#include <gtk-4.0/gtk/gtk.h>
|
#include <gtk-4.0/gtk/gtk.h>
|
||||||
|
|
||||||
extern GtkWindow *main_window;
|
extern GtkWindow * main_window;
|
||||||
|
|
||||||
GtkFileChooserNative* koto_utils_create_image_file_chooser(gchar *file_chooser_label) {
|
GtkFileChooserNative * koto_utils_create_image_file_chooser(gchar * file_chooser_label) {
|
||||||
GtkFileChooserNative* chooser = gtk_file_chooser_native_new(
|
GtkFileChooserNative* chooser = gtk_file_chooser_native_new(
|
||||||
file_chooser_label,
|
file_chooser_label,
|
||||||
main_window,
|
main_window,
|
||||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||||
|
@ -29,7 +29,9 @@ GtkFileChooserNative* koto_utils_create_image_file_chooser(gchar *file_chooser_l
|
||||||
"Cancel"
|
"Cancel"
|
||||||
);
|
);
|
||||||
|
|
||||||
GtkFileFilter *image_filter = gtk_file_filter_new(); // Create our file filter
|
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_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_filter(GTK_FILE_CHOOSER(chooser), image_filter); // Only allow picking images
|
||||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), FALSE);
|
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;
|
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;
|
GtkWidget* image = NULL;
|
||||||
|
|
||||||
|
|
||||||
if ((filepath != NULL) && (strcmp(filepath, "") != 0)) { // If we have a filepath
|
if ((filepath != NULL) && (strcmp(filepath, "") != 0)) { // If we have a filepath
|
||||||
if (g_file_test(filepath, G_FILE_TEST_EXISTS)) { // File exists
|
if (g_file_test(filepath, G_FILE_TEST_EXISTS)) { // File exists
|
||||||
image = gtk_image_new_from_file(filepath); // Load from the filepath
|
image = gtk_image_new_from_file(filepath); // Load from the filepath
|
||||||
|
@ -57,21 +65,24 @@ GtkWidget* koto_utils_create_image_from_filepath(gchar *filepath, gchar *fallbac
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_utils_get_filename_without_extension(gchar *filename) {
|
gchar * koto_utils_get_filename_without_extension(gchar * filename) {
|
||||||
gchar *trimmed_file_name = g_strdup(filename);
|
gchar * trimmed_file_name = g_strdup(filename);
|
||||||
gchar **split = g_strsplit(filename, ".", -1); // Split every time we see .
|
gchar ** split = g_strsplit(filename, ".", -1); // Split every time we see .
|
||||||
|
|
||||||
|
|
||||||
g_free(trimmed_file_name);
|
g_free(trimmed_file_name);
|
||||||
guint len_of_extension_split = g_strv_length(split);
|
guint len_of_extension_split = g_strv_length(split);
|
||||||
|
|
||||||
|
|
||||||
if (len_of_extension_split == 2) { // Only have two elements
|
if (len_of_extension_split == 2) { // Only have two elements
|
||||||
trimmed_file_name = g_strdup(split[0]); // Get the first element
|
trimmed_file_name = g_strdup(split[0]); // Get the first element
|
||||||
} else {
|
} else {
|
||||||
gchar *new_parsed_name = "";
|
gchar * new_parsed_name = "";
|
||||||
for (guint i = 0; i < len_of_extension_split - 1; i++) { // Iterate over everything except the last item
|
for (guint i = 0; i < len_of_extension_split - 1; i++) { // Iterate over everything except the last item
|
||||||
if (g_strcmp0(new_parsed_name, "") == 0) { // Currently empty
|
if (g_strcmp0(new_parsed_name, "") == 0) { // Currently empty
|
||||||
new_parsed_name = g_strdup(split[i]); // Just duplicate this string
|
new_parsed_name = g_strdup(split[i]); // Just duplicate this string
|
||||||
} else {
|
} else {
|
||||||
gchar *tmp_copy = g_strdup(new_parsed_name);
|
gchar * tmp_copy = g_strdup(new_parsed_name);
|
||||||
g_free(new_parsed_name); // Free the old
|
g_free(new_parsed_name); // Free the old
|
||||||
new_parsed_name = g_strjoin(".", tmp_copy, split[i], NULL); // Join the two strings with a . again and duplicate it, setting it to our new_parsed_name
|
new_parsed_name = g_strjoin(".", tmp_copy, split[i], NULL); // Join the two strings with a . again and duplicate it, setting it to our new_parsed_name
|
||||||
g_free(tmp_copy); // Free our temporary copy
|
g_free(tmp_copy); // Free our temporary copy
|
||||||
|
@ -82,22 +93,32 @@ gchar* koto_utils_get_filename_without_extension(gchar *filename) {
|
||||||
g_free(new_parsed_name);
|
g_free(new_parsed_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *stripped_file_name = g_strstrip(g_strdup(trimmed_file_name)); // Strip leading and trailing whitespace
|
gchar * stripped_file_name = g_strstrip(g_strdup(trimmed_file_name)); // Strip leading and trailing whitespace
|
||||||
|
|
||||||
|
|
||||||
g_free(trimmed_file_name);
|
g_free(trimmed_file_name);
|
||||||
return stripped_file_name;
|
return stripped_file_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_utils_is_string_valid(gchar *str) {
|
gboolean koto_utils_is_string_valid(gchar * str) {
|
||||||
return ((str != NULL) && (g_strcmp0(str, "") != 0));
|
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);
|
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 *cleaned_string = "";
|
gchar * str,
|
||||||
gchar **split = g_strsplit(str, find, -1); // Split on find
|
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
|
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
|
cleaned_string = g_strjoin(repl, cleaned_string, split[i], NULL); // Join the strings with our replace string
|
||||||
|
@ -107,16 +128,19 @@ gchar* koto_utils_replace_string_all(gchar *str, gchar *find, gchar *repl) {
|
||||||
return cleaned_string;
|
return cleaned_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_utils_unquote_string(gchar *s) {
|
gchar * koto_utils_unquote_string(gchar * s) {
|
||||||
gchar *new_s = NULL;
|
gchar * new_s = NULL;
|
||||||
|
|
||||||
|
|
||||||
if (g_str_has_prefix(s, "'") && g_str_has_suffix(s, "'")) { // Begins and ends with '
|
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
|
new_s = g_utf8_substring(s, 1, g_utf8_strlen(s, -1) - 1); // Start at 1 and end at n-1
|
||||||
} else {
|
} else {
|
||||||
new_s = g_strdup(s);
|
new_s = g_strdup(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar **split_on_double_single = g_strsplit(new_s, "''", -1); // Split on instances of ''
|
gchar ** split_on_double_single = g_strsplit(new_s, "''", -1); // Split on instances of ''
|
||||||
|
|
||||||
|
|
||||||
new_s = g_strjoinv("'", split_on_double_single); // Rejoin as '
|
new_s = g_strjoinv("'", split_on_double_single); // Rejoin as '
|
||||||
g_strfreev(split_on_double_single); // Free our array
|
g_strfreev(split_on_double_single); // Free our array
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,30 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
GtkFileChooserNative* koto_utils_create_image_file_chooser(gchar *file_chooser_label);
|
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);
|
|
||||||
gchar* koto_utils_get_filename_without_extension(gchar *filename);
|
GtkWidget * koto_utils_create_image_from_filepath(
|
||||||
gboolean koto_utils_is_string_valid(gchar *str);
|
gchar * filepath,
|
||||||
void koto_utils_push_queue_element_to_store(gpointer data, gpointer user_data);
|
gchar * fallback_icon,
|
||||||
gchar *koto_utils_replace_string_all(gchar *str, gchar *find, gchar *repl);
|
guint width,
|
||||||
gchar* koto_utils_unquote_string(gchar *s);
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
gchar * koto_utils_unquote_string(gchar * s);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -31,45 +31,47 @@
|
||||||
#include "koto-playerbar.h"
|
#include "koto-playerbar.h"
|
||||||
#include "koto-window.h"
|
#include "koto-window.h"
|
||||||
|
|
||||||
extern KotoActionBar *action_bar;
|
extern KotoActionBar * action_bar;
|
||||||
extern KotoAddRemoveTrackPopover *koto_add_remove_track_popup;
|
extern KotoAddRemoveTrackPopover * koto_add_remove_track_popup;
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoCreateModifyPlaylistDialog *playlist_create_modify_dialog;
|
extern KotoCreateModifyPlaylistDialog * playlist_create_modify_dialog;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
extern KotoPageMusicLocal *music_local_page;
|
extern KotoPageMusicLocal * music_local_page;
|
||||||
extern KotoPlaybackEngine *playback_engine;
|
extern KotoPlaybackEngine * playback_engine;
|
||||||
|
|
||||||
struct _KotoWindow {
|
struct _KotoWindow {
|
||||||
GtkApplicationWindow parent_instance;
|
GtkApplicationWindow parent_instance;
|
||||||
KotoIndexedLibrary *library;
|
KotoIndexedLibrary * library;
|
||||||
KotoCurrentPlaylist *current_playlist;
|
KotoCurrentPlaylist * current_playlist;
|
||||||
|
|
||||||
KotoDialogContainer *dialogs;
|
KotoDialogContainer * dialogs;
|
||||||
|
|
||||||
GtkWidget *overlay;
|
GtkWidget * overlay;
|
||||||
GtkWidget *header_bar;
|
GtkWidget * header_bar;
|
||||||
GtkWidget *menu_button;
|
GtkWidget * menu_button;
|
||||||
GtkWidget *search_entry;
|
GtkWidget * search_entry;
|
||||||
|
|
||||||
GtkWidget *primary_layout;
|
GtkWidget * primary_layout;
|
||||||
GtkWidget *content_layout;
|
GtkWidget * content_layout;
|
||||||
|
|
||||||
KotoNav *nav;
|
KotoNav * nav;
|
||||||
GtkWidget *pages;
|
GtkWidget * pages;
|
||||||
KotoPlayerBar *player_bar;
|
KotoPlayerBar * player_bar;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (KotoWindow, koto_window, GTK_TYPE_APPLICATION_WINDOW)
|
G_DEFINE_TYPE(KotoWindow, koto_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||||
|
|
||||||
static void koto_window_class_init (KotoWindowClass *klass) {
|
static void koto_window_class_init (KotoWindowClass * klass) {
|
||||||
(void)klass;
|
(void) klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_window_init (KotoWindow *self) {
|
static void koto_window_init (KotoWindow * self) {
|
||||||
current_playlist = koto_current_playlist_new();
|
current_playlist = koto_current_playlist_new();
|
||||||
playback_engine = koto_playback_engine_new();
|
playback_engine = koto_playback_engine_new();
|
||||||
|
|
||||||
GtkCssProvider* provider = gtk_css_provider_new();
|
GtkCssProvider* provider = gtk_css_provider_new();
|
||||||
|
|
||||||
|
|
||||||
gtk_css_provider_load_from_resource(provider, "/com/github/joshstrobl/koto/style.css");
|
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);
|
gtk_style_context_add_provider_for_display(gdk_display_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||||
|
|
||||||
|
@ -115,7 +117,7 @@ static void koto_window_init (KotoWindow *self) {
|
||||||
action_bar = koto_action_bar_new(); // Create our Koto Action Bar
|
action_bar = koto_action_bar_new(); // Create our Koto Action Bar
|
||||||
|
|
||||||
if (KOTO_IS_ACTION_BAR(action_bar)) { // Is an action bar
|
if (KOTO_IS_ACTION_BAR(action_bar)) { // Is an action bar
|
||||||
GtkActionBar *bar = koto_action_bar_get_main(action_bar);
|
GtkActionBar * bar = koto_action_bar_get_main(action_bar);
|
||||||
|
|
||||||
if (GTK_IS_ACTION_BAR(bar)) {
|
if (GTK_IS_ACTION_BAR(bar)) {
|
||||||
gtk_box_append(GTK_BOX(self->primary_layout), GTK_WIDGET(bar)); // Add the action
|
gtk_box_append(GTK_BOX(self->primary_layout), GTK_WIDGET(bar)); // Add the action
|
||||||
|
@ -125,7 +127,7 @@ static void koto_window_init (KotoWindow *self) {
|
||||||
self->player_bar = koto_playerbar_new();
|
self->player_bar = koto_playerbar_new();
|
||||||
|
|
||||||
if (KOTO_IS_PLAYERBAR(self->player_bar)) { // Is a playerbar
|
if (KOTO_IS_PLAYERBAR(self->player_bar)) { // Is a playerbar
|
||||||
GtkWidget *playerbar_main = koto_playerbar_get_main(self->player_bar);
|
GtkWidget * playerbar_main = koto_playerbar_get_main(self->player_bar);
|
||||||
gtk_box_append(GTK_BOX(self->primary_layout), playerbar_main);
|
gtk_box_append(GTK_BOX(self->primary_layout), playerbar_main);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,45 +143,65 @@ static void koto_window_init (KotoWindow *self) {
|
||||||
g_thread_new("load-library", (void*) load_library, 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);
|
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);
|
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;
|
(void) carto;
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoWindow *self = user_data;
|
KotoWindow * self = user_data;
|
||||||
|
|
||||||
|
gchar * playlist_uuid = koto_playlist_get_uuid(playlist);
|
||||||
|
KotoPlaylistPage * playlist_page = koto_playlist_page_new(playlist_uuid); // Create our new Playlist Page
|
||||||
|
|
||||||
|
|
||||||
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
|
koto_window_add_page(self, playlist_uuid, koto_playlist_page_get_main(playlist_page)); // Get the GtkScrolledWindow "main" content of the playlist page and add that as a page to our stack by the playlist UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_window_hide_dialogs(KotoWindow *self) {
|
void koto_window_hide_dialogs(KotoWindow * self) {
|
||||||
koto_dialog_container_hide(self->dialogs); // Hide the dialog container
|
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(
|
||||||
GtkWidget *page = gtk_stack_get_child_by_name(GTK_STACK(self->pages), page_name);
|
KotoWindow * self,
|
||||||
|
gchar * page_name
|
||||||
|
) {
|
||||||
|
GtkWidget * page = gtk_stack_get_child_by_name(GTK_STACK(self->pages), page_name);
|
||||||
|
|
||||||
|
|
||||||
if (GTK_IS_WIDGET(page)) {
|
if (GTK_IS_WIDGET(page)) {
|
||||||
gtk_stack_remove(GTK_STACK(self->pages), 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);
|
koto_dialog_container_show_dialog(self->dialogs, dialog_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_new_headerbar(KotoWindow *self) {
|
void create_new_headerbar(KotoWindow * self) {
|
||||||
self->header_bar = gtk_header_bar_new();
|
self->header_bar = gtk_header_bar_new();
|
||||||
gtk_widget_add_css_class(self->header_bar, "hdr");
|
gtk_widget_add_css_class(self->header_bar, "hdr");
|
||||||
g_return_if_fail(GTK_IS_HEADER_BAR(self->header_bar));
|
g_return_if_fail(GTK_IS_HEADER_BAR(self->header_bar));
|
||||||
|
@ -199,8 +221,9 @@ void create_new_headerbar(KotoWindow *self) {
|
||||||
gtk_window_set_titlebar(GTK_WINDOW(self), self->header_bar);
|
gtk_window_set_titlebar(GTK_WINDOW(self), self->header_bar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_library(KotoWindow *self) {
|
void load_library(KotoWindow * self) {
|
||||||
KotoIndexedLibrary *lib = koto_indexed_library_new(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC));
|
KotoIndexedLibrary * lib = koto_indexed_library_new(g_get_user_special_dir(G_USER_DIRECTORY_MUSIC));
|
||||||
|
|
||||||
|
|
||||||
if (lib != NULL) {
|
if (lib != NULL) {
|
||||||
self->library = lib;
|
self->library = lib;
|
||||||
|
@ -216,20 +239,26 @@ void load_library(KotoWindow *self) {
|
||||||
g_thread_exit(0);
|
g_thread_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_optimal_default_window_size(KotoWindow *self) {
|
void set_optimal_default_window_size(KotoWindow * self) {
|
||||||
GdkDisplay *default_display = gdk_display_get_default();
|
GdkDisplay * default_display = gdk_display_get_default();
|
||||||
|
|
||||||
|
|
||||||
if (!GDK_IS_X11_DISPLAY(default_display)) { // Not an X11 display
|
if (!GDK_IS_X11_DISPLAY(default_display)) { // Not an X11 display
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GdkMonitor *default_monitor = gdk_x11_display_get_primary_monitor(GDK_X11_DISPLAY(default_display)); // Get primary monitor for the X11
|
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
|
if (!GDK_IS_X11_MONITOR(default_monitor)) { // Not an X11 Monitor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GdkRectangle workarea = {0};
|
GdkRectangle workarea = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
gdk_monitor_get_geometry(default_monitor, &workarea);
|
gdk_monitor_get_geometry(default_monitor, &workarea);
|
||||||
|
|
||||||
if (workarea.width <= 1280) { // Honestly how do you even get anything done?
|
if (workarea.width <= 1280) { // Honestly how do you even get anything done?
|
||||||
|
|
|
@ -25,18 +25,43 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_WINDOW (koto_window_get_type())
|
#define KOTO_TYPE_WINDOW (koto_window_get_type())
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (KotoWindow, koto_window, KOTO, WINDOW, GtkApplicationWindow)
|
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_add_page(
|
||||||
void koto_window_go_to_page(KotoWindow *self, gchar *page_name);
|
KotoWindow * self,
|
||||||
void koto_window_handle_playlist_added(KotoCartographer *carto, KotoPlaylist *playlist, gpointer user_data);
|
gchar * page_name,
|
||||||
void koto_window_hide_dialogs(KotoWindow *self);
|
GtkWidget * page
|
||||||
void koto_window_remove_page(KotoWindow *self, gchar *page_name);
|
);
|
||||||
void koto_window_show_dialog(KotoWindow *self, gchar *dialog_name);
|
|
||||||
|
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 create_new_headerbar(KotoWindow * self);
|
||||||
|
|
||||||
void create_new_headerbar(KotoWindow *self);
|
|
||||||
void handle_album_added();
|
void handle_album_added();
|
||||||
void load_library(KotoWindow *self);
|
|
||||||
void set_optimal_default_window_size(KotoWindow *self);
|
void load_library(KotoWindow * self);
|
||||||
|
|
||||||
|
void set_optimal_default_window_size(KotoWindow * self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
42
src/main.c
42
src/main.c
|
@ -27,23 +27,23 @@
|
||||||
#include "koto-window.h"
|
#include "koto-window.h"
|
||||||
|
|
||||||
extern guint mpris_bus_id;
|
extern guint mpris_bus_id;
|
||||||
extern GDBusNodeInfo *introspection_data;
|
extern GDBusNodeInfo * introspection_data;
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
extern GHashTable *supported_mimes_hash;
|
extern GHashTable * supported_mimes_hash;
|
||||||
extern GList *supported_mimes;
|
extern GList * supported_mimes;
|
||||||
|
|
||||||
GtkApplication *app = NULL;
|
GtkApplication * app = NULL;
|
||||||
GtkWindow *main_window;
|
GtkWindow * main_window;
|
||||||
|
|
||||||
static void on_activate (GtkApplication *app) {
|
static void on_activate (GtkApplication * app) {
|
||||||
g_assert(GTK_IS_APPLICATION (app));
|
g_assert(GTK_IS_APPLICATION(app));
|
||||||
|
|
||||||
main_window = gtk_application_get_active_window (app);
|
main_window = gtk_application_get_active_window(app);
|
||||||
if (main_window == NULL) {
|
if (main_window == NULL) {
|
||||||
main_window = g_object_new(KOTO_TYPE_WINDOW, "application", app, "default-width", 1200, "default-height", 675, NULL);
|
main_window = g_object_new(KOTO_TYPE_WINDOW, "application", app, "default-width", 1200, "default-height", 675, NULL);
|
||||||
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
setup_mpris_interfaces(); // Set up our MPRIS interfaces
|
||||||
setup_mediakeys_interface(); // Set up our media key support
|
setup_mediakeys_interface(); // Set up our media key support
|
||||||
}
|
}
|
||||||
|
@ -51,20 +51,24 @@ static void on_activate (GtkApplication *app) {
|
||||||
gtk_window_present(main_window);
|
gtk_window_present(main_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_shutdown(GtkApplication *app) {
|
static void on_shutdown(GtkApplication * app) {
|
||||||
(void) app;
|
(void) app;
|
||||||
close_db(); // Close the database
|
close_db(); // Close the database
|
||||||
g_bus_unown_name(mpris_bus_id);
|
g_bus_unown_name(mpris_bus_id);
|
||||||
g_dbus_node_info_unref(introspection_data);
|
g_dbus_node_info_unref(introspection_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (
|
||||||
|
int argc,
|
||||||
|
char * argv[]
|
||||||
|
) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
/* Set up gettext translations */
|
/* Set up gettext translations */
|
||||||
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
||||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
||||||
textdomain (GETTEXT_PACKAGE);
|
textdomain(GETTEXT_PACKAGE);
|
||||||
|
|
||||||
gtk_init();
|
gtk_init();
|
||||||
gst_init(&argc, &argv);
|
gst_init(&argc, &argv);
|
||||||
|
@ -76,10 +80,10 @@ int main (int argc, char *argv[]) {
|
||||||
koto_maps = koto_cartographer_new(); // Create our new cartographer and their collection of maps
|
koto_maps = koto_cartographer_new(); // Create our new cartographer and their collection of maps
|
||||||
open_db(); // Open our database
|
open_db(); // Open our database
|
||||||
|
|
||||||
app = gtk_application_new ("com.github.joshstrobl.koto", G_APPLICATION_FLAGS_NONE);
|
app = gtk_application_new("com.github.joshstrobl.koto", G_APPLICATION_FLAGS_NONE);
|
||||||
g_signal_connect (app, "activate", G_CALLBACK (on_activate), NULL);
|
g_signal_connect(app, "activate", G_CALLBACK(on_activate), NULL);
|
||||||
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), NULL);
|
g_signal_connect(app, "shutdown", G_CALLBACK(on_shutdown), NULL);
|
||||||
ret = g_application_run (G_APPLICATION (app), argc, argv);
|
ret = g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,23 +25,23 @@
|
||||||
#include "koto-config.h"
|
#include "koto-config.h"
|
||||||
#include "koto-utils.h"
|
#include "koto-utils.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
|
|
||||||
struct _KotoAlbumView {
|
struct _KotoAlbumView {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
KotoIndexedAlbum *album;
|
KotoIndexedAlbum * album;
|
||||||
GtkWidget *main;
|
GtkWidget * main;
|
||||||
GtkWidget *album_tracks_box;
|
GtkWidget * album_tracks_box;
|
||||||
GtkWidget *discs;
|
GtkWidget * discs;
|
||||||
|
|
||||||
GtkWidget *album_overlay_art;
|
GtkWidget * album_overlay_art;
|
||||||
GtkWidget *album_overlay_container;
|
GtkWidget * album_overlay_container;
|
||||||
GtkWidget *album_overlay_controls;
|
GtkWidget * album_overlay_controls;
|
||||||
GtkWidget *album_overlay_revealer;
|
GtkWidget * album_overlay_revealer;
|
||||||
KotoButton *play_pause_button;
|
KotoButton * play_pause_button;
|
||||||
|
|
||||||
GtkWidget *album_label;
|
GtkWidget * album_label;
|
||||||
GHashTable *cd_to_track_listbox;
|
GHashTable * cd_to_track_listbox;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoAlbumView, koto_album_view, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoAlbumView, koto_album_view, G_TYPE_OBJECT);
|
||||||
|
@ -52,12 +52,27 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
NULL,
|
||||||
static void koto_album_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
};
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_album_view_class_init(KotoAlbumViewClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_album_view_set_property;
|
gobject_class->set_property = koto_album_view_set_property;
|
||||||
gobject_class->get_property = koto_album_view_get_property;
|
gobject_class->get_property = koto_album_view_get_property;
|
||||||
|
@ -67,13 +82,13 @@ static void koto_album_view_class_init(KotoAlbumViewClass *c) {
|
||||||
"Album",
|
"Album",
|
||||||
"Album",
|
"Album",
|
||||||
KOTO_TYPE_INDEXED_ALBUM,
|
KOTO_TYPE_INDEXED_ALBUM,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_album_view_init(KotoAlbumView *self) {
|
static void koto_album_view_init(KotoAlbumView * self) {
|
||||||
self->cd_to_track_listbox = g_hash_table_new(g_str_hash, g_str_equal);
|
self->cd_to_track_listbox = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
self->main = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
self->main = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||||
gtk_widget_add_css_class(self->main, "album-view");
|
gtk_widget_add_css_class(self->main, "album-view");
|
||||||
|
@ -113,7 +128,9 @@ static void koto_album_view_init(KotoAlbumView *self) {
|
||||||
gtk_overlay_add_overlay(GTK_OVERLAY(self->album_overlay_container), self->album_overlay_revealer); // Add our revealer as the overlay
|
gtk_overlay_add_overlay(GTK_OVERLAY(self->album_overlay_container), self->album_overlay_revealer); // Add our revealer as the overlay
|
||||||
gtk_box_prepend(GTK_BOX(self->main), self->album_overlay_container); // Add our album overlay container
|
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
|
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, "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);
|
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);
|
gtk_widget_add_controller(self->album_overlay_container, motion_controller);
|
||||||
|
@ -121,12 +138,18 @@ static void koto_album_view_init(KotoAlbumView *self) {
|
||||||
koto_button_add_click_handler(self->play_pause_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_album_view_toggle_album_playback), self);
|
koto_button_add_click_handler(self->play_pause_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_album_view_toggle_album_playback), self);
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_album_view_get_main(KotoAlbumView *self) {
|
GtkWidget * koto_album_view_get_main(KotoAlbumView * self) {
|
||||||
return self->main;
|
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(
|
||||||
KotoAlbumView *self = KOTO_ALBUM_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoAlbumView * self = KOTO_ALBUM_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ALBUM:
|
case PROP_ALBUM:
|
||||||
|
@ -138,8 +161,14 @@ 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(
|
||||||
KotoAlbumView *self = KOTO_ALBUM_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoAlbumView * self = KOTO_ALBUM_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ALBUM:
|
case PROP_ALBUM:
|
||||||
|
@ -151,58 +180,75 @@ 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 koto_album_view_add_track_to_listbox(
|
||||||
(void) self; (void) track;
|
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;
|
(void) controller;
|
||||||
KotoAlbumView* self = data;
|
KotoAlbumView* self = data;
|
||||||
|
|
||||||
|
|
||||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->album_overlay_revealer), FALSE);
|
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) {
|
if (album == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->album = album;
|
self->album = album;
|
||||||
|
|
||||||
gchar *album_art = koto_indexed_album_get_album_art(self->album); // Get the art for the 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);
|
gtk_image_set_from_file(GTK_IMAGE(self->album_overlay_art), album_art);
|
||||||
|
|
||||||
gchar *album_name;
|
gchar * album_name;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(album, "name", &album_name, NULL); // Get the album name
|
g_object_get(album, "name", &album_name, NULL); // Get the album name
|
||||||
|
|
||||||
self->album_label = gtk_label_new(album_name);
|
self->album_label = gtk_label_new(album_name);
|
||||||
gtk_widget_set_halign(self->album_label, GTK_ALIGN_START);
|
gtk_widget_set_halign(self->album_label, GTK_ALIGN_START);
|
||||||
gtk_box_prepend(GTK_BOX(self->album_tracks_box), self->album_label); // Prepend our new label to the album + tracks box
|
gtk_box_prepend(GTK_BOX(self->album_tracks_box), self->album_label); // Prepend our new label to the album + tracks box
|
||||||
|
|
||||||
GHashTable *discs = g_hash_table_new(g_str_hash, g_str_equal);
|
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
|
GList * tracks = koto_indexed_album_get_tracks(album); // Get the tracks for this album
|
||||||
|
|
||||||
|
|
||||||
for (guint i = 0; i < g_list_length(tracks); i++) {
|
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
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) g_list_nth_data(tracks, i)); // Get the track by its UUID
|
||||||
|
|
||||||
if (track == NULL) { // Track doesn't exist
|
if (track == NULL) { // Track doesn't exist
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint *disc_number;
|
guint * disc_number;
|
||||||
g_object_get(track, "cd", &disc_number, NULL);
|
g_object_get(track, "cd", &disc_number, NULL);
|
||||||
gchar *disc_num_as_str = g_strdup_printf("%u", GPOINTER_TO_UINT(disc_number));
|
gchar * disc_num_as_str = g_strdup_printf("%u", GPOINTER_TO_UINT(disc_number));
|
||||||
|
|
||||||
if (g_hash_table_contains(discs, disc_num_as_str)) { // Already have this added
|
if (g_hash_table_contains(discs, disc_num_as_str)) { // Already have this added
|
||||||
continue; // Skip
|
continue; // Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
g_hash_table_insert(discs, disc_num_as_str, "0"); // Mark this disc number in the hash table
|
g_hash_table_insert(discs, disc_num_as_str, "0"); // Mark this disc number in the hash table
|
||||||
KotoDiscView *disc_view = koto_disc_view_new(album, disc_number);
|
KotoDiscView * disc_view = koto_disc_view_new(album, disc_number);
|
||||||
gtk_list_box_append(GTK_LIST_BOX(self->discs), GTK_WIDGET(disc_view)); // Add the Disc View to the List Box
|
gtk_list_box_append(GTK_LIST_BOX(self->discs), GTK_WIDGET(disc_view)); // Add the Disc View to the List Box
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_list_length(g_hash_table_get_keys(discs)) == 1) { // Only have one album
|
if (g_list_length(g_hash_table_get_keys(discs)) == 1) { // Only have one album
|
||||||
GtkListBoxRow *row = gtk_list_box_get_row_at_index(GTK_LIST_BOX(self->discs), 0); // Get the first item
|
GtkListBoxRow * row = gtk_list_box_get_row_at_index(GTK_LIST_BOX(self->discs), 0); // Get the first item
|
||||||
|
|
||||||
if (GTK_IS_LIST_BOX_ROW(row)) { // Is a row
|
if (GTK_IS_LIST_BOX_ROW(row)) { // Is a row
|
||||||
koto_disc_view_set_disc_label_visible((KotoDiscView*) gtk_list_box_row_get_child(row), FALSE); // Get
|
koto_disc_view_set_disc_label_visible((KotoDiscView*) gtk_list_box_row_get_child(row), FALSE); // Get
|
||||||
|
@ -212,21 +258,30 @@ void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
||||||
g_hash_table_destroy(discs);
|
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;
|
(void) controller;
|
||||||
KotoAlbumView* self = data;
|
KotoAlbumView* self = data;
|
||||||
|
|
||||||
|
|
||||||
gtk_revealer_set_reveal_child(GTK_REVEALER(self->album_overlay_revealer), TRUE);
|
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;
|
(void) user_data;
|
||||||
KotoDiscView *disc1_item = KOTO_DISC_VIEW(gtk_list_box_row_get_child(disc1));
|
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));
|
KotoDiscView * disc2_item = KOTO_DISC_VIEW(gtk_list_box_row_get_child(disc2));
|
||||||
|
|
||||||
guint disc1_num;
|
guint disc1_num;
|
||||||
guint disc2_num;
|
guint disc2_num;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(disc1_item, "disc", &disc1_num, NULL);
|
g_object_get(disc1_item, "disc", &disc1_num, NULL);
|
||||||
g_object_get(disc2_item, "disc", &disc2_num, NULL);
|
g_object_get(disc2_item, "disc", &disc2_num, NULL);
|
||||||
|
|
||||||
|
@ -239,14 +294,24 @@ 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 koto_album_view_toggle_album_playback(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
|
int n_press,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
gpointer data
|
||||||
|
) {
|
||||||
|
(void) gesture;
|
||||||
|
(void) n_press;
|
||||||
|
(void) x;
|
||||||
|
(void) y;
|
||||||
KotoAlbumView* self = data;
|
KotoAlbumView* self = data;
|
||||||
|
|
||||||
|
|
||||||
koto_button_show_image(KOTO_BUTTON(self->play_pause_button), TRUE);
|
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
|
koto_indexed_album_set_as_current_playlist(self->album); // Set as the current playlist
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum *album) {
|
KotoAlbumView * koto_album_view_new(KotoIndexedAlbum * album) {
|
||||||
return g_object_new(KOTO_TYPE_ALBUM_VIEW, "album", album, NULL);
|
return g_object_new(KOTO_TYPE_ALBUM_VIEW, "album", album, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,41 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(KotoAlbumView, koto_album_view, KOTO, ALBUM_VIEW, GObject)
|
G_DECLARE_FINAL_TYPE(KotoAlbumView, koto_album_view, KOTO, ALBUM_VIEW, GObject)
|
||||||
|
|
||||||
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum *album);
|
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum * album);
|
||||||
GtkWidget* koto_album_view_get_main(KotoAlbumView *self);
|
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_add_track_to_listbox(
|
||||||
void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album);
|
KotoIndexedAlbum * self,
|
||||||
void koto_album_view_show_overlay_controls(GtkEventControllerFocus *controller, gpointer data);
|
KotoIndexedTrack * track
|
||||||
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_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
|
G_END_DECLS
|
||||||
|
|
|
@ -24,17 +24,17 @@
|
||||||
#include "koto-config.h"
|
#include "koto-config.h"
|
||||||
#include "koto-utils.h"
|
#include "koto-utils.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
|
|
||||||
struct _KotoArtistView {
|
struct _KotoArtistView {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
KotoIndexedArtist *artist;
|
KotoIndexedArtist * artist;
|
||||||
GtkWidget *scrolled_window;
|
GtkWidget * scrolled_window;
|
||||||
GtkWidget *content;
|
GtkWidget * content;
|
||||||
GtkWidget *favorites_list;
|
GtkWidget * favorites_list;
|
||||||
GtkWidget *album_list;
|
GtkWidget * album_list;
|
||||||
|
|
||||||
GHashTable *albums_to_component;
|
GHashTable * albums_to_component;
|
||||||
|
|
||||||
gboolean constructed;
|
gboolean constructed;
|
||||||
};
|
};
|
||||||
|
@ -47,13 +47,29 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
static void koto_artist_view_constructed(GObject *obj);
|
NULL,
|
||||||
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_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_class_init(KotoArtistViewClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
|
|
||||||
static void koto_artist_view_class_init(KotoArtistViewClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->constructed = koto_artist_view_constructed;
|
gobject_class->constructed = koto_artist_view_constructed;
|
||||||
gobject_class->set_property = koto_artist_view_set_property;
|
gobject_class->set_property = koto_artist_view_set_property;
|
||||||
|
@ -64,14 +80,20 @@ static void koto_artist_view_class_init(KotoArtistViewClass *c) {
|
||||||
"Artist",
|
"Artist",
|
||||||
"Artist",
|
"Artist",
|
||||||
KOTO_TYPE_INDEXED_ARTIST,
|
KOTO_TYPE_INDEXED_ARTIST,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
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(
|
||||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ARTIST:
|
case PROP_ARTIST:
|
||||||
|
@ -83,8 +105,14 @@ 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(
|
||||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_ARTIST:
|
case PROP_ARTIST:
|
||||||
|
@ -96,13 +124,15 @@ static void koto_artist_view_set_property(GObject *obj, guint prop_id, const GVa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_artist_view_init(KotoArtistView *self) {
|
static void koto_artist_view_init(KotoArtistView * self) {
|
||||||
self->artist = NULL;
|
self->artist = NULL;
|
||||||
self->constructed = FALSE;
|
self->constructed = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_artist_view_constructed(GObject *obj) {
|
static void koto_artist_view_constructed(GObject * obj) {
|
||||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
KotoArtistView * self = KOTO_ARTIST_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
self->albums_to_component = g_hash_table_new(g_str_hash, g_str_equal);
|
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->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
|
self->content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); // Create our content as a GtkBox
|
||||||
|
@ -132,23 +162,33 @@ static void koto_artist_view_constructed(GObject *obj) {
|
||||||
gtk_widget_set_hexpand(GTK_WIDGET(self->favorites_list), TRUE);
|
gtk_widget_set_hexpand(GTK_WIDGET(self->favorites_list), TRUE);
|
||||||
gtk_widget_set_hexpand(GTK_WIDGET(self->album_list), TRUE);
|
gtk_widget_set_hexpand(GTK_WIDGET(self->album_list), TRUE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (koto_artist_view_parent_class)->constructed (obj);
|
G_OBJECT_CLASS(koto_artist_view_parent_class)->constructed(obj);
|
||||||
self->constructed = TRUE;
|
self->constructed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album) {
|
void koto_artist_view_add_album(
|
||||||
gchar *album_art = koto_indexed_album_get_album_art(album); // Get the art for the 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);
|
||||||
|
|
||||||
|
|
||||||
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_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
|
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
|
KotoAlbumView* album_view = koto_album_view_new(album); // Create our new album view
|
||||||
GtkWidget* album_view_main = koto_album_view_get_main(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
|
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) {
|
if (artist == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -159,11 +199,13 @@ void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *albums = koto_indexed_artist_get_albums(self->artist); // Get the albums
|
GList * albums = koto_indexed_artist_get_albums(self->artist); // Get the albums
|
||||||
|
|
||||||
|
GList * a;
|
||||||
|
|
||||||
|
|
||||||
GList *a;
|
|
||||||
for (a = albums; a != NULL; a = a->next) {
|
for (a = albums; a != NULL; a = a->next) {
|
||||||
KotoIndexedAlbum *album = koto_cartographer_get_album_by_uuid(koto_maps, (gchar*) a->data);
|
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, (gchar*) a->data);
|
||||||
|
|
||||||
if (album != NULL) {
|
if (album != NULL) {
|
||||||
koto_artist_view_add_album(self, album); // Add the album
|
koto_artist_view_add_album(self, album); // Add the album
|
||||||
|
@ -171,10 +213,10 @@ void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_artist_view_get_main(KotoArtistView *self) {
|
GtkWidget * koto_artist_view_get_main(KotoArtistView * self) {
|
||||||
return self->scrolled_window;
|
return self->scrolled_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoArtistView* koto_artist_view_new() {
|
KotoArtistView * koto_artist_view_new() {
|
||||||
return g_object_new(KOTO_TYPE_ARTIST_VIEW, NULL);
|
return g_object_new(KOTO_TYPE_ARTIST_VIEW, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,11 +25,19 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_ARTIST_VIEW (koto_artist_view_get_type())
|
#define KOTO_TYPE_ARTIST_VIEW (koto_artist_view_get_type())
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (KotoArtistView, koto_artist_view, KOTO, ARTIST_VIEW, GObject)
|
G_DECLARE_FINAL_TYPE(KotoArtistView, koto_artist_view, KOTO, ARTIST_VIEW, GObject)
|
||||||
|
|
||||||
KotoArtistView* koto_artist_view_new();
|
KotoArtistView* koto_artist_view_new();
|
||||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album);
|
void koto_artist_view_add_album(
|
||||||
void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist);
|
KotoArtistView * self,
|
||||||
GtkWidget* koto_artist_view_get_main(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
|
G_END_DECLS
|
||||||
|
|
|
@ -23,17 +23,17 @@
|
||||||
#include "../../koto-utils.h"
|
#include "../../koto-utils.h"
|
||||||
#include "disc-view.h"
|
#include "disc-view.h"
|
||||||
|
|
||||||
extern KotoActionBar *action_bar;
|
extern KotoActionBar * action_bar;
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
|
|
||||||
struct _KotoDiscView {
|
struct _KotoDiscView {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
KotoIndexedAlbum *album;
|
KotoIndexedAlbum * album;
|
||||||
GtkWidget *header;
|
GtkWidget * header;
|
||||||
GtkWidget *label;
|
GtkWidget * label;
|
||||||
GtkWidget *list;
|
GtkWidget * list;
|
||||||
|
|
||||||
guint *disc_number;
|
guint * disc_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoDiscView, koto_disc_view, GTK_TYPE_BOX);
|
G_DEFINE_TYPE(KotoDiscView, koto_disc_view, GTK_TYPE_BOX);
|
||||||
|
@ -45,12 +45,27 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
static void koto_disc_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
NULL,
|
||||||
static void koto_disc_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
};
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_disc_view_class_init(KotoDiscViewClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_disc_view_set_property;
|
gobject_class->set_property = koto_disc_view_set_property;
|
||||||
gobject_class->get_property = koto_disc_view_get_property;
|
gobject_class->get_property = koto_disc_view_get_property;
|
||||||
|
@ -62,7 +77,7 @@ static void koto_disc_view_class_init(KotoDiscViewClass *c) {
|
||||||
0,
|
0,
|
||||||
G_MAXUINT16,
|
G_MAXUINT16,
|
||||||
1,
|
1,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ALBUM] = g_param_spec_object(
|
props[PROP_ALBUM] = g_param_spec_object(
|
||||||
|
@ -70,14 +85,20 @@ static void koto_disc_view_class_init(KotoDiscViewClass *c) {
|
||||||
"Album",
|
"Album",
|
||||||
"Album",
|
"Album",
|
||||||
KOTO_TYPE_INDEXED_ALBUM,
|
KOTO_TYPE_INDEXED_ALBUM,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
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(
|
||||||
KotoDiscView *self = KOTO_DISC_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoDiscView * self = KOTO_DISC_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_DISC:
|
case PROP_DISC:
|
||||||
|
@ -92,8 +113,14 @@ 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(
|
||||||
KotoDiscView *self = KOTO_DISC_VIEW(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoDiscView * self = KOTO_DISC_VIEW(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_DISC:
|
case PROP_DISC:
|
||||||
|
@ -108,14 +135,16 @@ static void koto_disc_view_set_property(GObject *obj, guint prop_id, const GValu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_disc_view_init(KotoDiscView *self) {
|
static void koto_disc_view_init(KotoDiscView * self) {
|
||||||
gtk_widget_add_css_class(GTK_WIDGET(self), "disc-view");
|
gtk_widget_add_css_class(GTK_WIDGET(self), "disc-view");
|
||||||
gtk_widget_set_can_focus(GTK_WIDGET(self), FALSE);
|
gtk_widget_set_can_focus(GTK_WIDGET(self), FALSE);
|
||||||
self->header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
self->header = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||||
gtk_widget_set_hexpand(self->header, TRUE);
|
gtk_widget_set_hexpand(self->header, TRUE);
|
||||||
gtk_widget_set_size_request(self->header, 16, -1);
|
gtk_widget_set_size_request(self->header, 16, -1);
|
||||||
|
|
||||||
GtkWidget *ico = gtk_image_new_from_icon_name("drive-optical-symbolic");
|
GtkWidget * ico = gtk_image_new_from_icon_name("drive-optical-symbolic");
|
||||||
|
|
||||||
|
|
||||||
gtk_box_prepend(GTK_BOX(self->header), ico);
|
gtk_box_prepend(GTK_BOX(self->header), ico);
|
||||||
|
|
||||||
self->label = gtk_label_new(NULL); // Create an empty label
|
self->label = gtk_label_new(NULL); // Create an empty label
|
||||||
|
@ -137,41 +166,55 @@ 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);
|
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(
|
||||||
KotoDiscView *self = (KotoDiscView*) selfptr;
|
gpointer data,
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) data); // Get the track by its UUID
|
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;
|
||||||
|
|
||||||
|
|
||||||
guint *disc_number;
|
|
||||||
g_object_get(track, "cd", &disc_number, NULL); // get the 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
|
if (GPOINTER_TO_UINT(self->disc_number) != GPOINTER_TO_UINT(disc_number)) { // Track does not belong to this CD
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoTrackItem *track_item = koto_track_item_new(track); // Create our new track item
|
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
|
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(
|
||||||
KotoDiscView *self = user_data;
|
GtkListBox * box,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
KotoDiscView * self = user_data;
|
||||||
|
|
||||||
|
gchar * album_uuid = koto_indexed_album_get_album_uuid(self->album); // Get the UUID
|
||||||
|
|
||||||
gchar *album_uuid = koto_indexed_album_get_album_uuid(self->album); // Get the UUID
|
|
||||||
|
|
||||||
if (!koto_utils_is_string_valid(album_uuid)) { // Not set
|
if (!koto_utils_is_string_valid(album_uuid)) { // Not set
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *selected_rows = gtk_list_box_get_selected_rows(box); // Get the selected rows
|
GList * selected_rows = gtk_list_box_get_selected_rows(box); // Get the selected rows
|
||||||
|
|
||||||
|
|
||||||
if (g_list_length(selected_rows) == 0) { // No rows selected
|
if (g_list_length(selected_rows) == 0) { // No rows selected
|
||||||
koto_action_bar_toggle_reveal(action_bar, FALSE); // Close the action bar
|
koto_action_bar_toggle_reveal(action_bar, FALSE); // Close the action bar
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *selected_tracks = NULL; // Create our list of KotoIndexedTracks
|
GList * selected_tracks = NULL; // Create our list of KotoIndexedTracks
|
||||||
GList *cur_selected_rows;
|
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
|
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);
|
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
|
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
|
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) {
|
if (album == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -195,28 +241,43 @@ 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);
|
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) {
|
if (disc_number == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->disc_number = GUINT_TO_POINTER(disc_number);
|
self->disc_number = GUINT_TO_POINTER(disc_number);
|
||||||
|
|
||||||
gchar *disc_label = g_strdup_printf("Disc %u", 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
|
|
||||||
|
|
||||||
|
gtk_label_set_text(GTK_LABEL(self->label), disc_label); // Set the label
|
||||||
|
|
||||||
g_free(disc_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);
|
(visible) ? gtk_widget_show(self->header) : gtk_widget_hide(self->header);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoDiscView* koto_disc_view_new(KotoIndexedAlbum *album, guint *disc_number) {
|
KotoDiscView * koto_disc_view_new(
|
||||||
return g_object_new(KOTO_TYPE_DISC_VIEW,
|
KotoIndexedAlbum * album,
|
||||||
"disc", disc_number,
|
guint * disc_number
|
||||||
"album", album,
|
) {
|
||||||
"orientation", GTK_ORIENTATION_VERTICAL,
|
return g_object_new(
|
||||||
|
KOTO_TYPE_DISC_VIEW,
|
||||||
|
"disc",
|
||||||
|
disc_number,
|
||||||
|
"album",
|
||||||
|
album,
|
||||||
|
"orientation",
|
||||||
|
GTK_ORIENTATION_VERTICAL,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,30 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE(KotoDiscView, koto_disc_view, KOTO, DISC_VIEW, GtkBox)
|
G_DECLARE_FINAL_TYPE(KotoDiscView, koto_disc_view, KOTO, DISC_VIEW, GtkBox)
|
||||||
|
|
||||||
KotoDiscView* koto_disc_view_new(KotoIndexedAlbum *album, guint *disc);
|
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_handle_selected_rows_changed(
|
||||||
void koto_disc_view_list_tracks(gpointer data, gpointer selfptr);
|
GtkListBox * box,
|
||||||
void koto_disc_view_set_album(KotoDiscView *self, KotoIndexedAlbum *album);
|
gpointer user_data
|
||||||
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_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
|
G_END_DECLS
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "../../koto-utils.h"
|
#include "../../koto-utils.h"
|
||||||
#include "music-local.h"
|
#include "music-local.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
@ -32,15 +32,17 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoPageMusicLocal {
|
struct _KotoPageMusicLocal {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
GtkWidget *scrolled_window;
|
GtkWidget * scrolled_window;
|
||||||
GtkWidget *artist_list;
|
GtkWidget * artist_list;
|
||||||
GtkWidget *stack;
|
GtkWidget * stack;
|
||||||
|
|
||||||
KotoIndexedLibrary *lib;
|
KotoIndexedLibrary * lib;
|
||||||
gboolean constructed;
|
gboolean constructed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,14 +52,28 @@ struct _KotoPageMusicLocalClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPageMusicLocal, koto_page_music_local, GTK_TYPE_BOX);
|
G_DEFINE_TYPE(KotoPageMusicLocal, koto_page_music_local, GTK_TYPE_BOX);
|
||||||
|
|
||||||
KotoPageMusicLocal *music_local_page;
|
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_class_init(KotoPageMusicLocalClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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_class_init(KotoPageMusicLocalClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->constructed = koto_page_music_local_constructed;
|
gobject_class->constructed = koto_page_music_local_constructed;
|
||||||
gobject_class->set_property = koto_page_music_local_set_property;
|
gobject_class->set_property = koto_page_music_local_set_property;
|
||||||
|
@ -68,14 +84,20 @@ static void koto_page_music_local_class_init(KotoPageMusicLocalClass *c) {
|
||||||
"Library",
|
"Library",
|
||||||
"Library",
|
"Library",
|
||||||
KOTO_TYPE_INDEXED_LIBRARY,
|
KOTO_TYPE_INDEXED_LIBRARY,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
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(
|
||||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_LIB:
|
case PROP_LIB:
|
||||||
|
@ -87,8 +109,14 @@ 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(
|
||||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_LIB:
|
case PROP_LIB:
|
||||||
|
@ -100,7 +128,7 @@ static void koto_page_music_local_set_property(GObject *obj, guint prop_id, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_page_music_local_init(KotoPageMusicLocal *self) {
|
static void koto_page_music_local_init(KotoPageMusicLocal * self) {
|
||||||
self->lib = NULL;
|
self->lib = NULL;
|
||||||
self->constructed = FALSE;
|
self->constructed = FALSE;
|
||||||
|
|
||||||
|
@ -130,36 +158,55 @@ static void koto_page_music_local_init(KotoPageMusicLocal *self) {
|
||||||
gtk_box_append(GTK_BOX(self), self->stack);
|
gtk_box_append(GTK_BOX(self), self->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_page_music_local_constructed(GObject *obj) {
|
static void koto_page_music_local_constructed(GObject * obj) {
|
||||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
KotoPageMusicLocal * self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||||
|
|
||||||
G_OBJECT_CLASS (koto_page_music_local_parent_class)->constructed (obj);
|
|
||||||
|
G_OBJECT_CLASS(koto_page_music_local_parent_class)->constructed(obj);
|
||||||
self->constructed = TRUE;
|
self->constructed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist) {
|
void koto_page_music_local_add_artist(
|
||||||
gchar *artist_name;
|
KotoPageMusicLocal * self,
|
||||||
|
KotoIndexedArtist * artist
|
||||||
|
) {
|
||||||
|
gchar * artist_name;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(artist, "name", &artist_name, NULL);
|
g_object_get(artist, "name", &artist_name, NULL);
|
||||||
KotoButton *artist_button = koto_button_new_plain(artist_name);
|
KotoButton * artist_button = koto_button_new_plain(artist_name);
|
||||||
|
|
||||||
|
|
||||||
gtk_list_box_prepend(GTK_LIST_BOX(self->artist_list), GTK_WIDGET(artist_button));
|
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
|
KotoArtistView * artist_view = koto_artist_view_new(); // Create our new artist view
|
||||||
|
|
||||||
|
|
||||||
koto_artist_view_add_artist(artist_view, artist); // Add the artist
|
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);
|
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);
|
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(
|
||||||
KotoIndexedArtist *artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid); // Get the artist
|
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
|
if (!KOTO_IS_INDEXED_ARTIST(artist)) { // No artist for this UUID
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artist_name = NULL;
|
gchar * artist_name = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
artist,
|
artist,
|
||||||
"name",
|
"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);
|
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;
|
(void) box;
|
||||||
KotoPageMusicLocal *self = (KotoPageMusicLocal*) data;
|
KotoPageMusicLocal * self = (KotoPageMusicLocal*) data;
|
||||||
KotoButton *btn = KOTO_BUTTON(gtk_list_box_row_get_child(row));
|
KotoButton * btn = KOTO_BUTTON(gtk_list_box_row_get_child(row));
|
||||||
|
|
||||||
|
gchar * artist_name;
|
||||||
|
|
||||||
|
|
||||||
gchar *artist_name;
|
|
||||||
g_object_get(btn, "button-text", &artist_name, NULL);
|
g_object_get(btn, "button-text", &artist_name, NULL);
|
||||||
koto_page_music_local_go_to_artist_by_name(self, artist_name);
|
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) {
|
if (lib == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -203,11 +259,12 @@ void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibr
|
||||||
gpointer artist_key;
|
gpointer artist_key;
|
||||||
gpointer artist_data;
|
gpointer artist_data;
|
||||||
|
|
||||||
GHashTable *artists = koto_indexed_library_get_artists(self->lib); // Get the artists
|
GHashTable * artists = koto_indexed_library_get_artists(self->lib); // Get the artists
|
||||||
|
|
||||||
|
|
||||||
g_hash_table_iter_init(&artist_list_iter, 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
|
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
|
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, (gchar*) artist_data); // Cast our data as a KotoIndexedArtist
|
||||||
|
|
||||||
if (artist != NULL) {
|
if (artist != NULL) {
|
||||||
koto_page_music_local_add_artist(self, artist);
|
koto_page_music_local_add_artist(self, artist);
|
||||||
|
@ -215,13 +272,18 @@ 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;
|
(void) user_data;
|
||||||
KotoButton *artist1_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist1));
|
KotoButton * artist1_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist1));
|
||||||
KotoButton *artist2_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist2));
|
KotoButton * artist2_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist2));
|
||||||
|
|
||||||
|
gchar * artist1_text;
|
||||||
|
gchar * artist2_text;
|
||||||
|
|
||||||
gchar *artist1_text;
|
|
||||||
gchar *artist2_text;
|
|
||||||
|
|
||||||
g_object_get(artist1_btn, "button-text", &artist1_text, NULL);
|
g_object_get(artist1_btn, "button-text", &artist1_text, NULL);
|
||||||
g_object_get(artist2_btn, "button-text", &artist2_text, NULL);
|
g_object_get(artist2_btn, "button-text", &artist2_text, NULL);
|
||||||
|
@ -229,9 +291,11 @@ int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *ar
|
||||||
return g_utf8_collate(artist1_text, artist2_text);
|
return g_utf8_collate(artist1_text, artist2_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPageMusicLocal* koto_page_music_local_new() {
|
KotoPageMusicLocal * koto_page_music_local_new() {
|
||||||
return g_object_new(KOTO_TYPE_PAGE_MUSIC_LOCAL,
|
return g_object_new(
|
||||||
"orientation", GTK_ORIENTATION_HORIZONTAL,
|
KOTO_TYPE_PAGE_MUSIC_LOCAL,
|
||||||
|
"orientation",
|
||||||
|
GTK_ORIENTATION_HORIZONTAL,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,14 +26,39 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_PAGE_MUSIC_LOCAL (koto_page_music_local_get_type())
|
#define KOTO_TYPE_PAGE_MUSIC_LOCAL (koto_page_music_local_get_type())
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (KotoPageMusicLocal, koto_page_music_local, KOTO, PAGE_MUSIC_LOCAL, GtkBox)
|
G_DECLARE_FINAL_TYPE(KotoPageMusicLocal, koto_page_music_local, KOTO, PAGE_MUSIC_LOCAL, GtkBox)
|
||||||
|
|
||||||
KotoPageMusicLocal* koto_page_music_local_new();
|
KotoPageMusicLocal* koto_page_music_local_new();
|
||||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist);
|
void koto_page_music_local_add_artist(
|
||||||
void koto_page_music_local_handle_artist_click(GtkListBox *box, GtkListBoxRow *row, gpointer data);
|
KotoPageMusicLocal * self,
|
||||||
void koto_page_music_local_go_to_artist_by_name(KotoPageMusicLocal *self, gchar *artist_name);
|
KotoIndexedArtist * artist
|
||||||
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_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
|
G_END_DECLS
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
#include "../../playlist/create-modify-dialog.h"
|
#include "../../playlist/create-modify-dialog.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
extern KotoActionBar *action_bar;
|
extern KotoActionBar * action_bar;
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoCreateModifyPlaylistDialog *playlist_create_modify_dialog;
|
extern KotoCreateModifyPlaylistDialog * playlist_create_modify_dialog;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
extern KotoWindow *main_window;
|
extern KotoWindow * main_window;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
@ -39,41 +39,43 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
struct _KotoPlaylistPage {
|
struct _KotoPlaylistPage {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
KotoPlaylist *playlist;
|
KotoPlaylist * playlist;
|
||||||
gchar *uuid;
|
gchar * uuid;
|
||||||
|
|
||||||
GtkWidget *main; // Our Scrolled Window
|
GtkWidget * main; // Our Scrolled Window
|
||||||
GtkWidget *content; // Content inside scrolled window
|
GtkWidget * content; // Content inside scrolled window
|
||||||
GtkWidget *header;
|
GtkWidget * header;
|
||||||
|
|
||||||
KotoCoverArtButton *playlist_image;
|
KotoCoverArtButton * playlist_image;
|
||||||
GtkWidget *name_label;
|
GtkWidget * name_label;
|
||||||
GtkWidget *tracks_count_label;
|
GtkWidget * tracks_count_label;
|
||||||
GtkWidget *type_label;
|
GtkWidget * type_label;
|
||||||
KotoButton *favorite_button;
|
KotoButton * favorite_button;
|
||||||
KotoButton *edit_button;
|
KotoButton * edit_button;
|
||||||
|
|
||||||
GtkListItemFactory *item_factory;
|
GtkListItemFactory * item_factory;
|
||||||
GListModel *model;
|
GListModel * model;
|
||||||
GtkSelectionModel *selection_model;
|
GtkSelectionModel * selection_model;
|
||||||
|
|
||||||
GtkWidget *track_list_content;
|
GtkWidget * track_list_content;
|
||||||
GtkWidget *track_list_header;
|
GtkWidget * track_list_header;
|
||||||
GtkWidget *track_list_view;
|
GtkWidget * track_list_view;
|
||||||
|
|
||||||
KotoButton *track_num_button;
|
KotoButton * track_num_button;
|
||||||
KotoButton *track_title_button;
|
KotoButton * track_title_button;
|
||||||
KotoButton *track_album_button;
|
KotoButton * track_album_button;
|
||||||
KotoButton *track_artist_button;
|
KotoButton * track_artist_button;
|
||||||
|
|
||||||
GtkSizeGroup *track_pos_size_group;
|
GtkSizeGroup * track_pos_size_group;
|
||||||
GtkSizeGroup *track_name_size_group;
|
GtkSizeGroup * track_name_size_group;
|
||||||
GtkSizeGroup *track_album_size_group;
|
GtkSizeGroup * track_album_size_group;
|
||||||
GtkSizeGroup *track_artist_size_group;
|
GtkSizeGroup * track_artist_size_group;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoPlaylistPageClass {
|
struct _KotoPlaylistPageClass {
|
||||||
|
@ -82,11 +84,24 @@ struct _KotoPlaylistPageClass {
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPlaylistPage, koto_playlist_page, G_TYPE_OBJECT);
|
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_get_property(
|
||||||
static void koto_playlist_page_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_playlist_page_class_init(KotoPlaylistPageClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->get_property = koto_playlist_page_get_property;
|
gobject_class->get_property = koto_playlist_page_get_property;
|
||||||
gobject_class->set_property = koto_playlist_page_set_property;
|
gobject_class->set_property = koto_playlist_page_set_property;
|
||||||
|
@ -96,13 +111,13 @@ static void koto_playlist_page_class_init(KotoPlaylistPageClass *c) {
|
||||||
"UUID of associated Playlist",
|
"UUID of associated Playlist",
|
||||||
"UUID of associated Playlist",
|
"UUID of associated Playlist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playlist_page_init(KotoPlaylistPage *self) {
|
static void koto_playlist_page_init(KotoPlaylistPage * self) {
|
||||||
self->track_name_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
self->track_name_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
||||||
self->track_pos_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
self->track_pos_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
||||||
self->track_album_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
self->track_album_size_group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
|
||||||
|
@ -119,10 +134,14 @@ static void koto_playlist_page_init(KotoPlaylistPage *self) {
|
||||||
gtk_box_prepend(GTK_BOX(self->content), self->header);
|
gtk_box_prepend(GTK_BOX(self->content), self->header);
|
||||||
|
|
||||||
self->playlist_image = koto_cover_art_button_new(220, 220, NULL); // Create our Cover Art Button with no art by default
|
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
|
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);
|
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);
|
GtkWidget * info_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
|
|
||||||
gtk_widget_set_size_request(info_box, -1, 220);
|
gtk_widget_set_size_request(info_box, -1, 220);
|
||||||
gtk_widget_add_css_class(info_box, "playlist-page-header-info");
|
gtk_widget_add_css_class(info_box, "playlist-page-header-info");
|
||||||
gtk_widget_set_hexpand(info_box, TRUE);
|
gtk_widget_set_hexpand(info_box, TRUE);
|
||||||
|
@ -176,8 +195,14 @@ 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
|
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(
|
||||||
KotoPlaylistPage *self = KOTO_PLAYLIST_PAGE(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPlaylistPage * self = KOTO_PLAYLIST_PAGE(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PLAYLIST_UUID:
|
case PROP_PLAYLIST_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(
|
||||||
KotoPlaylistPage *self = KOTO_PLAYLIST_PAGE(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPlaylistPage * self = KOTO_PLAYLIST_PAGE(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PLAYLIST_UUID:
|
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
|
koto_playlist_page_set_playlist_uuid(self, g_strdup(g_value_get_string(val))); // Call to our playlist UUID set function
|
||||||
|
@ -201,23 +233,29 @@ 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;
|
(void) factory;
|
||||||
|
|
||||||
GtkWidget *track_position_label = gtk_widget_get_first_child(gtk_list_item_get_child(item));
|
GtkWidget * track_position_label = gtk_widget_get_first_child(gtk_list_item_get_child(item));
|
||||||
GtkWidget *track_name_label = gtk_widget_get_next_sibling(track_position_label);
|
GtkWidget * track_name_label = gtk_widget_get_next_sibling(track_position_label);
|
||||||
GtkWidget *track_album_label = gtk_widget_get_next_sibling(track_name_label);
|
GtkWidget * track_album_label = gtk_widget_get_next_sibling(track_name_label);
|
||||||
GtkWidget *track_artist_label = gtk_widget_get_next_sibling(track_album_label);
|
GtkWidget * track_artist_label = gtk_widget_get_next_sibling(track_album_label);
|
||||||
|
|
||||||
|
KotoIndexedTrack * track = gtk_list_item_get_item(item); // Get the track UUID from our model
|
||||||
|
|
||||||
KotoIndexedTrack *track = gtk_list_item_get_item(item); // Get the track UUID from our model
|
|
||||||
|
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *track_name = NULL;
|
gchar * track_name = NULL;
|
||||||
gchar *album_uuid = NULL;
|
gchar * album_uuid = NULL;
|
||||||
gchar *artist_uuid = NULL;
|
gchar * artist_uuid = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
track,
|
track,
|
||||||
|
@ -232,23 +270,26 @@ void koto_playlist_page_bind_track_item(GtkListItemFactory *factory, GtkListItem
|
||||||
|
|
||||||
guint track_position = koto_playlist_get_position_of_track(self->playlist, track);
|
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_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
|
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);
|
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid(koto_maps, album_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_ALBUM(album)) {
|
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
|
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);
|
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid(koto_maps, artist_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_ARTIST(artist)) {
|
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
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_page_create_tracks_header(KotoPlaylistPage *self) {
|
void koto_playlist_page_create_tracks_header(KotoPlaylistPage * self) {
|
||||||
self->track_num_button = koto_button_new_with_icon("#", "pan-down-symbolic", "pan-up-symbolic", KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
self->track_num_button = koto_button_new_with_icon("#", "pan-down-symbolic", "pan-up-symbolic", KOTO_BUTTON_PIXBUF_SIZE_SMALL);
|
||||||
koto_button_add_click_handler(self->track_num_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_playlist_page_handle_track_num_clicked), self);
|
koto_button_add_click_handler(self->track_num_button, KOTO_BUTTON_CLICK_TYPE_PRIMARY, G_CALLBACK(koto_playlist_page_handle_track_num_clicked), self);
|
||||||
koto_button_set_image_position(self->track_num_button, KOTO_BUTTON_IMAGE_POS_RIGHT); // Move the image to the right
|
koto_button_set_image_position(self->track_num_button, KOTO_BUTTON_IMAGE_POS_RIGHT); // Move the image to the right
|
||||||
|
@ -276,13 +317,17 @@ void koto_playlist_page_create_tracks_header(KotoPlaylistPage *self) {
|
||||||
gtk_box_append(GTK_BOX(self->track_list_header), GTK_WIDGET(self->track_artist_button));
|
gtk_box_append(GTK_BOX(self->track_list_header), GTK_WIDGET(self->track_artist_button));
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget* koto_playlist_page_get_main(KotoPlaylistPage *self) {
|
GtkWidget * koto_playlist_page_get_main(KotoPlaylistPage * self) {
|
||||||
return self->main;
|
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;
|
(void) bar;
|
||||||
KotoPlaylistPage *self = data;
|
KotoPlaylistPage * self = data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(self->playlist)) { // No playlist set
|
if (!KOTO_IS_PLAYLIST(self->playlist)) { // No playlist set
|
||||||
return;
|
return;
|
||||||
|
@ -292,9 +337,19 @@ void koto_playlist_page_handle_action_bar_closed(KotoActionBar *bar, gpointer da
|
||||||
gtk_widget_grab_focus(GTK_WIDGET(main_window)); // Focus on the window
|
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 koto_playlist_page_handle_cover_art_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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
|
if (!KOTO_IS_PLAYLIST(self->playlist)) { // No playlist set
|
||||||
return;
|
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);
|
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 koto_playlist_page_handle_edit_button_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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_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");
|
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)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylistPage *self = user_data;
|
KotoPlaylistPage * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
gchar * artwork = koto_playlist_get_artwork(playlist); // Get the artwork
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(artwork)) { // Have valid 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
|
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
|
gchar * name = koto_playlist_get_name(playlist); // Get the name
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(name)) { // Have valid 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
|
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 koto_playlist_page_handle_track_album_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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");
|
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_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);
|
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 koto_playlist_page_handle_track_artist_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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");
|
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_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);
|
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 koto_playlist_page_handle_track_name_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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");
|
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_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);
|
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 koto_playlist_page_handle_track_num_clicked(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
GtkGestureClick * gesture,
|
||||||
KotoPlaylistPage *self = user_data;
|
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);
|
KotoPreferredModelType current_model = koto_playlist_get_current_model(self->playlist);
|
||||||
|
|
||||||
|
|
||||||
if (current_model == KOTO_PREFERRED_MODEL_TYPE_DEFAULT) { // Set to newest currently
|
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_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)
|
koto_button_show_image(self->track_num_button, TRUE); // Use inverted value (pan-up-symbolic)
|
||||||
|
@ -370,21 +488,29 @@ 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;
|
(void) position;
|
||||||
KotoPlaylistPage *self = user_data;
|
KotoPlaylistPage * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (n_items == 0) { // No items selected
|
if (n_items == 0) { // No items selected
|
||||||
koto_action_bar_toggle_reveal(action_bar, FALSE); // Hide the action bar
|
koto_action_bar_toggle_reveal(action_bar, FALSE); // Hide the action bar
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkBitset *selected_items_bitset = gtk_selection_model_get_selection(model); // Get the selected items as a GtkBitSet
|
GtkBitset * selected_items_bitset = gtk_selection_model_get_selection(model); // Get the selected items as a GtkBitSet
|
||||||
GtkBitsetIter iter;
|
GtkBitsetIter iter;
|
||||||
GList *selected_tracks = NULL;
|
GList * selected_tracks = NULL;
|
||||||
GList *selected_tracks_pos = NULL;
|
GList * selected_tracks_pos = NULL;
|
||||||
|
|
||||||
guint first_track_pos;
|
guint first_track_pos;
|
||||||
|
|
||||||
|
|
||||||
if (!gtk_bitset_iter_init_first(&iter, selected_items_bitset, &first_track_pos)) { // Failed to get the first item
|
if (!gtk_bitset_iter_init_first(&iter, selected_items_bitset, &first_track_pos)) { // Failed to get the first item
|
||||||
return;
|
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));
|
selected_tracks_pos = g_list_append(selected_tracks_pos, GUINT_TO_POINTER(first_track_pos));
|
||||||
|
|
||||||
gboolean have_more_items = TRUE;
|
gboolean have_more_items = TRUE;
|
||||||
|
|
||||||
|
|
||||||
while (have_more_items) { // While we are able to get selected items
|
while (have_more_items) { // While we are able to get selected items
|
||||||
guint track_pos;
|
guint track_pos;
|
||||||
have_more_items = gtk_bitset_iter_next(&iter, &track_pos);
|
have_more_items = gtk_bitset_iter_next(&iter, &track_pos);
|
||||||
|
@ -400,9 +528,11 @@ void koto_playlist_page_handle_tracks_selected(GtkSelectionModel *model, guint p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *cur_pos_list;
|
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
|
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
|
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
|
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
|
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)) {
|
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +561,9 @@ void koto_playlist_page_set_playlist_uuid(KotoPlaylistPage *self, gchar *playlis
|
||||||
}
|
}
|
||||||
|
|
||||||
self->uuid = g_strdup(playlist_uuid); // Duplicate the playlist UUID
|
self->uuid = g_strdup(playlist_uuid); // Duplicate the playlist UUID
|
||||||
KotoPlaylist *playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->uuid);
|
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->uuid);
|
||||||
|
|
||||||
|
|
||||||
self->playlist = playlist;
|
self->playlist = playlist;
|
||||||
koto_playlist_page_set_playlist_model(self, KOTO_PREFERRED_MODEL_TYPE_DEFAULT); // TODO: Enable this to be changed
|
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
|
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
|
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)) {
|
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -447,11 +585,11 @@ void koto_playlist_page_set_playlist_model(KotoPlaylistPage *self, KotoPreferred
|
||||||
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM) { // Not sorting by album currently
|
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM) { // Not sorting by album currently
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(self->track_album_button), "active");
|
gtk_widget_remove_css_class(GTK_WIDGET(self->track_album_button), "active");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST) { // Not sorting by artist currently
|
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST) { // Not sorting by artist currently
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(self->track_artist_button), "active");
|
gtk_widget_remove_css_class(GTK_WIDGET(self->track_artist_button), "active");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME) { // Not sorting by track name
|
if (model != KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME) { // Not sorting by track name
|
||||||
gtk_widget_remove_css_class(GTK_WIDGET(self->track_title_button), "active");
|
gtk_widget_remove_css_class(GTK_WIDGET(self->track_title_button), "active");
|
||||||
}
|
}
|
||||||
|
@ -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
|
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;
|
(void) factory;
|
||||||
KotoPlaylistPage *self = user_data;
|
KotoPlaylistPage * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *item_content = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); // Have a horizontal box for our content
|
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");
|
gtk_widget_add_css_class(item_content, "track-list-columned-item");
|
||||||
|
|
||||||
GtkWidget *track_number = gtk_label_new(NULL); // Our track number
|
GtkWidget * track_number = gtk_label_new(NULL); // Our track number
|
||||||
|
|
||||||
|
|
||||||
gtk_label_set_xalign(GTK_LABEL(track_number), 0);
|
gtk_label_set_xalign(GTK_LABEL(track_number), 0);
|
||||||
gtk_widget_add_css_class(track_number, "track-column-number");
|
gtk_widget_add_css_class(track_number, "track-column-number");
|
||||||
gtk_widget_set_halign(track_number, GTK_ALIGN_END);
|
gtk_widget_set_halign(track_number, GTK_ALIGN_END);
|
||||||
|
@ -482,7 +629,9 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
||||||
gtk_box_append(GTK_BOX(item_content), track_number);
|
gtk_box_append(GTK_BOX(item_content), track_number);
|
||||||
gtk_size_group_add_widget(self->track_pos_size_group, track_number);
|
gtk_size_group_add_widget(self->track_pos_size_group, track_number);
|
||||||
|
|
||||||
GtkWidget *track_name = gtk_label_new(NULL); // Our track name
|
GtkWidget * track_name = gtk_label_new(NULL); // Our track name
|
||||||
|
|
||||||
|
|
||||||
gtk_label_set_xalign(GTK_LABEL(track_name), 0);
|
gtk_label_set_xalign(GTK_LABEL(track_name), 0);
|
||||||
gtk_widget_add_css_class(track_name, "track-column-name");
|
gtk_widget_add_css_class(track_name, "track-column-name");
|
||||||
gtk_widget_set_halign(track_name, GTK_ALIGN_START);
|
gtk_widget_set_halign(track_name, GTK_ALIGN_START);
|
||||||
|
@ -491,7 +640,9 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
||||||
gtk_box_append(GTK_BOX(item_content), track_name);
|
gtk_box_append(GTK_BOX(item_content), track_name);
|
||||||
gtk_size_group_add_widget(self->track_name_size_group, track_name);
|
gtk_size_group_add_widget(self->track_name_size_group, track_name);
|
||||||
|
|
||||||
GtkWidget *track_album = gtk_label_new(NULL); // Our track album
|
GtkWidget * track_album = gtk_label_new(NULL); // Our track album
|
||||||
|
|
||||||
|
|
||||||
gtk_label_set_xalign(GTK_LABEL(track_album), 0);
|
gtk_label_set_xalign(GTK_LABEL(track_album), 0);
|
||||||
gtk_widget_add_css_class(track_album, "track-column-album");
|
gtk_widget_add_css_class(track_album, "track-column-album");
|
||||||
gtk_widget_set_halign(track_album, GTK_ALIGN_START);
|
gtk_widget_set_halign(track_album, GTK_ALIGN_START);
|
||||||
|
@ -501,7 +652,9 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
||||||
gtk_box_append(GTK_BOX(item_content), track_album);
|
gtk_box_append(GTK_BOX(item_content), track_album);
|
||||||
gtk_size_group_add_widget(self->track_album_size_group, track_album);
|
gtk_size_group_add_widget(self->track_album_size_group, track_album);
|
||||||
|
|
||||||
GtkWidget *track_artist = gtk_label_new(NULL); // Our track artist
|
GtkWidget * track_artist = gtk_label_new(NULL); // Our track artist
|
||||||
|
|
||||||
|
|
||||||
gtk_label_set_xalign(GTK_LABEL(track_artist), 0);
|
gtk_label_set_xalign(GTK_LABEL(track_artist), 0);
|
||||||
gtk_widget_add_css_class(track_artist, "track-column-artist");
|
gtk_widget_add_css_class(track_artist, "track-column-artist");
|
||||||
gtk_widget_set_halign(track_artist, GTK_ALIGN_START);
|
gtk_widget_set_halign(track_artist, GTK_ALIGN_START);
|
||||||
|
@ -514,7 +667,7 @@ void koto_playlist_page_setup_track_item(GtkListItemFactory *factory, GtkListIte
|
||||||
gtk_list_item_set_child(item, item_content);
|
gtk_list_item_set_child(item, item_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_page_update_header(KotoPlaylistPage *self) {
|
void koto_playlist_page_update_header(KotoPlaylistPage * self) {
|
||||||
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
if (!KOTO_IS_PLAYLIST_PAGE(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -524,6 +677,8 @@ void koto_playlist_page_update_header(KotoPlaylistPage *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean ephemeral = TRUE;
|
gboolean ephemeral = TRUE;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
self->playlist,
|
self->playlist,
|
||||||
"ephemeral",
|
"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
|
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
|
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
|
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);
|
gchar * artwork = koto_playlist_get_artwork(self->playlist);
|
||||||
|
|
||||||
|
|
||||||
if (koto_utils_is_string_valid(artwork)) { // Have artwork
|
if (koto_utils_is_string_valid(artwork)) { // Have artwork
|
||||||
koto_cover_art_button_set_art_path(self->playlist_image, artwork); // Update our 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
|
KotoPreferredModelType current_model = koto_playlist_get_current_model(self->playlist); // Get the current model
|
||||||
|
|
||||||
|
|
||||||
if (current_model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) {
|
if (current_model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) {
|
||||||
koto_button_show_image(self->track_num_button, TRUE); // Immediately use pan-up-symbolic
|
koto_button_show_image(self->track_num_button, TRUE); // Immediately use pan-up-symbolic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylistPage* koto_playlist_page_new(gchar *playlist_uuid) {
|
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",
|
"uuid",
|
||||||
playlist_uuid,
|
playlist_uuid,
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -26,31 +26,122 @@
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define KOTO_TYPE_PLAYLIST_PAGE koto_playlist_page_get_type()
|
#define KOTO_TYPE_PLAYLIST_PAGE koto_playlist_page_get_type()
|
||||||
G_DECLARE_FINAL_TYPE (KotoPlaylistPage, koto_playlist_page, KOTO, PLAYLIST_PAGE, GObject);
|
G_DECLARE_FINAL_TYPE(KotoPlaylistPage, koto_playlist_page, KOTO, PLAYLIST_PAGE, GObject);
|
||||||
#define KOTO_IS_PLAYLIST_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_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);
|
KotoPlaylistPage * koto_playlist_page_new(gchar * playlist_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);
|
|
||||||
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_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_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_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
|
||||||
|
);
|
||||||
|
|
||||||
|
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_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_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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -38,25 +38,26 @@ enum {
|
||||||
N_SIGNALS
|
N_SIGNALS
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint playback_engine_signals[N_SIGNALS] = { 0 };
|
static guint playback_engine_signals[N_SIGNALS] = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
|
|
||||||
KotoPlaybackEngine *playback_engine;
|
KotoPlaybackEngine * playback_engine;
|
||||||
|
|
||||||
struct _KotoPlaybackEngine {
|
struct _KotoPlaybackEngine {
|
||||||
GObject parent_class;
|
GObject parent_class;
|
||||||
GstElement *player;
|
GstElement * player;
|
||||||
GstElement *playbin;
|
GstElement * playbin;
|
||||||
GstElement *suppress_video;
|
GstElement * suppress_video;
|
||||||
GstBus *monitor;
|
GstBus * monitor;
|
||||||
|
|
||||||
GstQuery *duration_query;
|
GstQuery * duration_query;
|
||||||
GstQuery *position_query;
|
GstQuery * position_query;
|
||||||
|
|
||||||
KotoIndexedTrack *current_track;
|
KotoIndexedTrack * current_track;
|
||||||
NotifyNotification *track_notification;
|
|
||||||
|
|
||||||
gboolean is_muted;
|
gboolean is_muted;
|
||||||
gboolean is_repeat_enabled;
|
gboolean is_repeat_enabled;
|
||||||
|
@ -74,22 +75,24 @@ struct _KotoPlaybackEngine {
|
||||||
struct _KotoPlaybackEngineClass {
|
struct _KotoPlaybackEngineClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (* is_playing) (KotoPlaybackEngine *engine);
|
void (* is_playing) (KotoPlaybackEngine * engine);
|
||||||
void (* is_paused) (KotoPlaybackEngine *engine);
|
void (* is_paused) (KotoPlaybackEngine * engine);
|
||||||
void (* play_state_changed) (KotoPlaybackEngine *engine);
|
void (* play_state_changed) (KotoPlaybackEngine * engine);
|
||||||
void (* tick_duration) (KotoPlaybackEngine *engine);
|
void (* tick_duration) (KotoPlaybackEngine * engine);
|
||||||
void (* tick_track) (KotoPlaybackEngine *engine);
|
void (* tick_track) (KotoPlaybackEngine * engine);
|
||||||
void (* track_changed) (KotoPlaybackEngine *engine);
|
void (* track_changed) (KotoPlaybackEngine * engine);
|
||||||
void (* track_repeat_changed) (KotoPlaybackEngine *engine);
|
void (* track_repeat_changed) (KotoPlaybackEngine * engine);
|
||||||
void (* track_shuffle_changed) (KotoPlaybackEngine *engine);
|
void (* track_shuffle_changed) (KotoPlaybackEngine * engine);
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPlaybackEngine, koto_playback_engine, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoPlaybackEngine, koto_playback_engine, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static void koto_playback_engine_class_init(KotoPlaybackEngineClass *c) {
|
static void koto_playback_engine_class_init(KotoPlaybackEngineClass * c) {
|
||||||
c->play_state_changed = NULL;
|
c->play_state_changed = NULL;
|
||||||
|
|
||||||
GObjectClass *gobject_class;
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
|
|
||||||
playback_engine_signals[SIGNAL_IS_PLAYING] = g_signal_new(
|
playback_engine_signals[SIGNAL_IS_PLAYING] = g_signal_new(
|
||||||
|
@ -189,7 +192,7 @@ static void koto_playback_engine_class_init(KotoPlaybackEngineClass *c) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playback_engine_init(KotoPlaybackEngine *self) {
|
static void koto_playback_engine_init(KotoPlaybackEngine * self) {
|
||||||
self->current_track = NULL;
|
self->current_track = NULL;
|
||||||
|
|
||||||
self->player = gst_pipeline_new("player");
|
self->player = gst_pipeline_new("player");
|
||||||
|
@ -223,8 +226,9 @@ static void koto_playback_engine_init(KotoPlaybackEngine *self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_backwards(KotoPlaybackEngine *self) {
|
void koto_playback_engine_backwards(KotoPlaybackEngine * self) {
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist); // Get the current playlist
|
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
|
if (!KOTO_IS_PLAYLIST(playlist)) { // If we do not have a playlist currently
|
||||||
return;
|
return;
|
||||||
|
@ -242,7 +246,8 @@ void koto_playback_engine_current_playlist_changed() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist); // Get the current playlist
|
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
|
if (!KOTO_IS_PLAYLIST(playlist)) { // If we do not have a playlist currently
|
||||||
return;
|
return;
|
||||||
|
@ -251,8 +256,9 @@ void koto_playback_engine_current_playlist_changed() {
|
||||||
koto_playback_engine_set_track_by_uuid(playback_engine, koto_playlist_go_to_next(playlist)); // Go to "next" which is the first track
|
koto_playback_engine_set_track_by_uuid(playback_engine, koto_playlist_go_to_next(playlist)); // Go to "next" which is the first track
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_forwards(KotoPlaybackEngine *self) {
|
void koto_playback_engine_forwards(KotoPlaybackEngine * self) {
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist); // Get the current playlist
|
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
|
if (!KOTO_IS_PLAYLIST(playlist)) { // If we do not have a playlist currently
|
||||||
return;
|
return;
|
||||||
|
@ -265,12 +271,14 @@ void koto_playback_engine_forwards(KotoPlaybackEngine *self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack* koto_playback_engine_get_current_track(KotoPlaybackEngine *self) {
|
KotoIndexedTrack * koto_playback_engine_get_current_track(KotoPlaybackEngine * self) {
|
||||||
return self->current_track;
|
return self->current_track;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine *self) {
|
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine * self) {
|
||||||
gint64 duration = 0;
|
gint64 duration = 0;
|
||||||
|
|
||||||
|
|
||||||
if (gst_element_query(self->player, self->duration_query)) { // Able to query our duration
|
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
|
gst_query_parse_duration(self->duration_query, NULL, &duration); // Get the duration
|
||||||
duration = duration / GST_SECOND; // Divide by NS to get seconds
|
duration = duration / GST_SECOND; // Divide by NS to get seconds
|
||||||
|
@ -279,9 +287,11 @@ gint64 koto_playback_engine_get_duration(KotoPlaybackEngine *self) {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine *self) {
|
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine * self) {
|
||||||
gdouble progress = 0.0;
|
gdouble progress = 0.0;
|
||||||
gint64 gstprog = 0;
|
gint64 gstprog = 0;
|
||||||
|
|
||||||
|
|
||||||
if (gst_element_query(self->playbin, self->position_query)) { // Able to get our position
|
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
|
gst_query_parse_position(self->position_query, NULL, &gstprog); // Get the progress
|
||||||
|
|
||||||
|
@ -295,31 +305,39 @@ gdouble koto_playback_engine_get_progress(KotoPlaybackEngine *self) {
|
||||||
return progress;
|
return progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
GstState koto_playback_engine_get_state(KotoPlaybackEngine *self) {
|
GstState koto_playback_engine_get_state(KotoPlaybackEngine * self) {
|
||||||
return GST_STATE(self->player);
|
return GST_STATE(self->player);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine *self) {
|
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine * self) {
|
||||||
return self->is_repeat_enabled;
|
return self->is_repeat_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine *self) {
|
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine * self) {
|
||||||
(void) self;
|
(void) self;
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
KotoPlaylist * playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean currently_shuffling = FALSE;
|
gboolean currently_shuffling = FALSE;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(playlist, "is-shuffle-enabled", ¤tly_shuffling, NULL); // Get the current is-shuffle-enabled
|
g_object_get(playlist, "is-shuffle-enabled", ¤tly_shuffling, NULL); // Get the current is-shuffle-enabled
|
||||||
|
|
||||||
return currently_shuffling;
|
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;
|
(void) bus;
|
||||||
KotoPlaybackEngine *self = user_data;
|
KotoPlaybackEngine * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
switch (GST_MESSAGE_TYPE(msg)) {
|
switch (GST_MESSAGE_TYPE(msg)) {
|
||||||
case GST_MESSAGE_ASYNC_DONE:
|
case GST_MESSAGE_ASYNC_DONE:
|
||||||
|
@ -357,7 +375,7 @@ gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpoi
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_play(KotoPlaybackEngine *self) {
|
void koto_playback_engine_play(KotoPlaybackEngine * self) {
|
||||||
self->is_playing = TRUE;
|
self->is_playing = TRUE;
|
||||||
gst_element_set_state(self->player, GST_STATE_PLAYING); // Set our state to play
|
gst_element_set_state(self->player, GST_STATE_PLAYING); // Set our state to play
|
||||||
|
|
||||||
|
@ -374,23 +392,33 @@ void koto_playback_engine_play(KotoPlaybackEngine *self) {
|
||||||
koto_update_mpris_playback_state(GST_STATE_PLAYING);
|
koto_update_mpris_playback_state(GST_STATE_PLAYING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_pause(KotoPlaybackEngine *self) {
|
void koto_playback_engine_pause(KotoPlaybackEngine * self) {
|
||||||
self->is_playing = FALSE;
|
self->is_playing = FALSE;
|
||||||
gst_element_change_state(self->player, GST_STATE_CHANGE_PLAYING_TO_PAUSED);
|
gst_element_change_state(self->player, GST_STATE_CHANGE_PLAYING_TO_PAUSED);
|
||||||
koto_update_mpris_playback_state(GST_STATE_PAUSED);
|
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);
|
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;
|
self->is_repeat_enabled = enable_repeat;
|
||||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_REPEAT_CHANGE], 0); // Emit our track repeat changed event
|
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(
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
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
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Don't have a playlist currently
|
||||||
return;
|
return;
|
||||||
|
@ -400,12 +428,16 @@ 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
|
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) {
|
if (track_uuid == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid); // Get the track from cartographer
|
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
|
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||||
return;
|
return;
|
||||||
|
@ -413,12 +445,15 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
||||||
|
|
||||||
self->current_track = track;
|
self->current_track = track;
|
||||||
|
|
||||||
gchar *track_file_path = NULL;
|
gchar * track_file_path = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_object_get(track, "path", &track_file_path, NULL); // Get the path to the track
|
g_object_get(track, "path", &track_file_path, NULL); // Get the path to the track
|
||||||
|
|
||||||
koto_playback_engine_stop(self); // Stop current 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
|
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_object_set(self->playbin, "uri", gst_filename, NULL);
|
||||||
g_free(gst_filename); // Free the filename
|
g_free(gst_filename); // Free the filename
|
||||||
|
@ -429,34 +464,36 @@ void koto_playback_engine_set_track_by_uuid(KotoPlaybackEngine *self, gchar *tra
|
||||||
koto_playback_engine_set_position(self, 0);
|
koto_playback_engine_set_position(self, 0);
|
||||||
koto_playback_engine_set_volume(self, self->volume); // Re-enforce our volume on the updated playbin
|
koto_playback_engine_set_volume(self, self->volume); // Re-enforce our volume on the updated playbin
|
||||||
|
|
||||||
GVariant *metadata = koto_indexed_track_get_metadata_vardict(track); // Get the GVariantBuilder variable dict for the metadata
|
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);
|
GVariantDict * metadata_dict = g_variant_dict_new(metadata);
|
||||||
|
|
||||||
|
|
||||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TRACK_CHANGE], 0); // Emit our track change signal
|
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);
|
koto_update_mpris_info_for_track(self->current_track);
|
||||||
|
|
||||||
GVariant *track_name_var = g_variant_dict_lookup_value(metadata_dict, "xesam:title", NULL); // Get the GVariant for the name of the track
|
GVariant * track_name_var = g_variant_dict_lookup_value(metadata_dict, "xesam:title", NULL); // Get the GVariant for the name of the track
|
||||||
const gchar *track_name = g_variant_get_string(track_name_var, NULL); // Get the string of the track name
|
const gchar * track_name = g_variant_get_string(track_name_var, NULL); // Get the string of the track name
|
||||||
|
|
||||||
GVariant *album_name_var = g_variant_dict_lookup_value(metadata_dict, "xesam:album", NULL); // Get the GVariant for the album name
|
GVariant * album_name_var = g_variant_dict_lookup_value(metadata_dict, "xesam:album", NULL); // Get the GVariant for the album name
|
||||||
const gchar *album_name = g_variant_get_string(album_name_var, NULL); // Get the string for the album name
|
const gchar * album_name = g_variant_get_string(album_name_var, NULL); // Get the string for the album name
|
||||||
|
|
||||||
GVariant *artist_name_var = g_variant_dict_lookup_value(metadata_dict, "playbackengine:artist", NULL); // Get the GVariant for the name of the artist
|
GVariant * artist_name_var = g_variant_dict_lookup_value(metadata_dict, "playbackengine:artist", NULL); // Get the GVariant for the name of the artist
|
||||||
const gchar *artist_name = g_variant_get_string(artist_name_var, NULL); // Get the string for the artist name
|
const gchar * artist_name = g_variant_get_string(artist_name_var, NULL); // Get the string for the artist name
|
||||||
|
|
||||||
gchar *artist_album_combo = g_strjoin(" - ", artist_name, album_name, NULL); // Join artist and album name separated by " - "
|
gchar * artist_album_combo = g_strjoin(" - ", artist_name, album_name, NULL); // Join artist and album name separated by " - "
|
||||||
|
|
||||||
|
gchar * icon_name = "audio-x-generic-symbolic";
|
||||||
|
|
||||||
gchar *icon_name = "audio-x-generic-symbolic";
|
|
||||||
|
|
||||||
if (g_variant_dict_contains(metadata_dict, "mpris:artUrl")) { // If we have artwork specified
|
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
|
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
|
const gchar * art_uri = g_variant_get_string(art_url_var, NULL); // Get the string for the artwork
|
||||||
icon_name = koto_utils_replace_string_all(g_strdup(art_uri), "file://", "");
|
icon_name = koto_utils_replace_string_all(g_strdup(art_uri), "file://", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Super important note: We are not using libnotify directly because the synchronous nature of notify_notification_send seems to result in dbus timeouts
|
// Super important note: We are not using libnotify directly because the synchronous nature of notify_notification_send seems to result in dbus timeouts
|
||||||
if (g_find_program_in_path("notify-send") != NULL) { // Have notify-send
|
if (g_find_program_in_path("notify-send") != NULL) { // Have notify-send
|
||||||
char *argv[12];
|
char * argv[12];
|
||||||
argv[0] = "notify-send";
|
argv[0] = "notify-send";
|
||||||
argv[1] = "-a";
|
argv[1] = "-a";
|
||||||
argv[2] = "Koto";
|
argv[2] = "Koto";
|
||||||
|
@ -474,14 +511,18 @@ 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;
|
self->volume = volume;
|
||||||
g_object_set(self->playbin, "volume", self->volume, NULL);
|
g_object_set(self->playbin, "volume", self->volume, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_stop(KotoPlaybackEngine *self) {
|
void koto_playback_engine_stop(KotoPlaybackEngine * self) {
|
||||||
gst_element_set_state(self->player, GST_STATE_NULL);
|
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
|
GstPad * pad = gst_element_get_static_pad(self->player, "sink"); // Get the static pad of the audio element
|
||||||
|
|
||||||
|
|
||||||
if (!GST_IS_PAD(pad)) {
|
if (!GST_IS_PAD(pad)) {
|
||||||
return;
|
return;
|
||||||
|
@ -491,7 +532,7 @@ void koto_playback_engine_stop(KotoPlaybackEngine *self) {
|
||||||
koto_update_mpris_playback_state(GST_STATE_NULL);
|
koto_update_mpris_playback_state(GST_STATE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_toggle(KotoPlaybackEngine *self) {
|
void koto_playback_engine_toggle(KotoPlaybackEngine * self) {
|
||||||
if (self->is_playing) { // Currently playing
|
if (self->is_playing) { // Currently playing
|
||||||
koto_playback_engine_pause(self); // Pause
|
koto_playback_engine_pause(self); // Pause
|
||||||
} else {
|
} else {
|
||||||
|
@ -500,7 +541,8 @@ void koto_playback_engine_toggle(KotoPlaybackEngine *self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_playback_engine_tick_duration(gpointer user_data) {
|
gboolean koto_playback_engine_tick_duration(gpointer user_data) {
|
||||||
KotoPlaybackEngine *self = user_data;
|
KotoPlaybackEngine * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (self->is_playing) { // Is playing
|
if (self->is_playing) { // Is playing
|
||||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_DURATION], 0); // Emit our 1s track tick
|
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_DURATION], 0); // Emit our 1s track tick
|
||||||
|
@ -512,7 +554,8 @@ gboolean koto_playback_engine_tick_duration(gpointer user_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_playback_engine_tick_track(gpointer user_data) {
|
gboolean koto_playback_engine_tick_track(gpointer user_data) {
|
||||||
KotoPlaybackEngine *self = user_data;
|
KotoPlaybackEngine * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (self->is_playing) { // Is playing
|
if (self->is_playing) { // Is playing
|
||||||
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_TRACK], 0); // Emit our 100ms track tick
|
g_signal_emit(self, playback_engine_signals[SIGNAL_TICK_TRACK], 0); // Emit our 100ms track tick
|
||||||
|
@ -523,14 +566,14 @@ gboolean koto_playback_engine_tick_track(gpointer user_data) {
|
||||||
return self->is_playing;
|
return self->is_playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self) {
|
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine * self) {
|
||||||
koto_playback_engine_set_track_repeat(self, !self->is_repeat_enabled);
|
koto_playback_engine_set_track_repeat(self, !self->is_repeat_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine *self) {
|
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine * self) {
|
||||||
koto_playback_engine_set_track_shuffle(self, !koto_playback_engine_get_track_shuffle(self)); // Invert the currently shuffling vale
|
koto_playback_engine_set_track_shuffle(self, !koto_playback_engine_get_track_shuffle(self)); // Invert the currently shuffling vale
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaybackEngine* koto_playback_engine_new() {
|
KotoPlaybackEngine * koto_playback_engine_new() {
|
||||||
return g_object_new(KOTO_TYPE_PLAYBACK_ENGINE, NULL);
|
return g_object_new(KOTO_TYPE_PLAYBACK_ENGINE, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,10 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_PLAYBACK_ENGINE (koto_playback_engine_get_type())
|
#define KOTO_TYPE_PLAYBACK_ENGINE (koto_playback_engine_get_type())
|
||||||
#define KOTO_PLAYBACK_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KOTO_TYPE_PLAYBACK_ENGINE, KotoPlaybackEngine))
|
#define KOTO_PLAYBACK_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KOTO_TYPE_PLAYBACK_ENGINE, KotoPlaybackEngine))
|
||||||
#define KOTO_IS_PLAYBACK_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYBACK_ENGINE))
|
#define KOTO_IS_PLAYBACK_ENGINE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYBACK_ENGINE))
|
||||||
|
|
||||||
typedef struct _KotoPlaybackEngine KotoPlaybackEngine;
|
typedef struct _KotoPlaybackEngine KotoPlaybackEngine;
|
||||||
|
@ -39,32 +39,75 @@ GType koto_playback_engine_get_type(void) G_GNUC_CONST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playback Engine Functions
|
* Playback Engine Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
KotoPlaybackEngine * koto_playback_engine_new();
|
||||||
|
|
||||||
|
void koto_playback_engine_backwards(KotoPlaybackEngine * self);
|
||||||
|
|
||||||
KotoPlaybackEngine* koto_playback_engine_new();
|
|
||||||
void koto_playback_engine_backwards(KotoPlaybackEngine *self);
|
|
||||||
void koto_playback_engine_current_playlist_changed();
|
void koto_playback_engine_current_playlist_changed();
|
||||||
void koto_playback_engine_forwards(KotoPlaybackEngine *self);
|
|
||||||
KotoIndexedTrack* koto_playback_engine_get_current_track(KotoPlaybackEngine *self);
|
void koto_playback_engine_forwards(KotoPlaybackEngine * self);
|
||||||
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine *self);
|
|
||||||
GstState koto_playback_engine_get_state(KotoPlaybackEngine *self);
|
KotoIndexedTrack * koto_playback_engine_get_current_track(KotoPlaybackEngine * self);
|
||||||
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine *self);
|
|
||||||
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine *self);
|
gint64 koto_playback_engine_get_duration(KotoPlaybackEngine * self);
|
||||||
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine *self);
|
|
||||||
void koto_playback_engine_mute(KotoPlaybackEngine *self);
|
GstState koto_playback_engine_get_state(KotoPlaybackEngine * self);
|
||||||
gboolean koto_playback_engine_monitor_changed(GstBus *bus, GstMessage *msg, gpointer user_data);
|
|
||||||
void koto_playback_engine_pause(KotoPlaybackEngine *self);
|
gdouble koto_playback_engine_get_progress(KotoPlaybackEngine * self);
|
||||||
void koto_playback_engine_play(KotoPlaybackEngine *self);
|
|
||||||
void koto_playback_engine_toggle(KotoPlaybackEngine *self);
|
gboolean koto_playback_engine_get_track_repeat(KotoPlaybackEngine * self);
|
||||||
void koto_playback_engine_set_position(KotoPlaybackEngine *self, int position);
|
|
||||||
void koto_playback_engine_set_track_repeat(KotoPlaybackEngine *self, gboolean enable_repeat);
|
gboolean koto_playback_engine_get_track_shuffle(KotoPlaybackEngine * self);
|
||||||
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_mute(KotoPlaybackEngine * self);
|
||||||
void koto_playback_engine_set_volume(KotoPlaybackEngine *self, gdouble volume);
|
|
||||||
void koto_playback_engine_stop(KotoPlaybackEngine *self);
|
gboolean koto_playback_engine_monitor_changed(
|
||||||
void koto_playback_engine_toggle_track_repeat(KotoPlaybackEngine *self);
|
GstBus * bus,
|
||||||
void koto_playback_engine_toggle_track_shuffle(KotoPlaybackEngine *self);
|
GstMessage * msg,
|
||||||
void koto_playback_engine_update_duration(KotoPlaybackEngine *self);
|
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_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_duration(gpointer user_data);
|
||||||
|
|
||||||
gboolean koto_playback_engine_tick_track(gpointer user_data);
|
gboolean koto_playback_engine_tick_track(gpointer user_data);
|
||||||
|
|
|
@ -21,30 +21,30 @@
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "media-keys.h"
|
#include "media-keys.h"
|
||||||
|
|
||||||
extern GtkWindow *main_window;
|
extern GtkWindow * main_window;
|
||||||
extern KotoPlaybackEngine *playback_engine;
|
extern KotoPlaybackEngine * playback_engine;
|
||||||
|
|
||||||
GDBusConnection *media_keys_dbus_conn = NULL;
|
GDBusConnection * media_keys_dbus_conn = NULL;
|
||||||
GDBusProxy *media_keys_proxy = NULL;
|
GDBusProxy * media_keys_proxy = NULL;
|
||||||
GDBusNodeInfo *media_keys_introspection_data = NULL;
|
GDBusNodeInfo * media_keys_introspection_data = NULL;
|
||||||
|
|
||||||
static const gchar introspection_xml[] =
|
static const gchar introspection_xml[] =
|
||||||
"<node name='/org/gnome/SettingsDaemon/MediaKeys'>"
|
"<node name='/org/gnome/SettingsDaemon/MediaKeys'>"
|
||||||
" <interface name='org.gnome.SettingsDaemon.MediaKeys'>"
|
" <interface name='org.gnome.SettingsDaemon.MediaKeys'>"
|
||||||
" <annotation name='org.freedesktop.DBus.GLib.CSymbol' value='gsd_media_keys_manager'/>"
|
" <annotation name='org.freedesktop.DBus.GLib.CSymbol' value='gsd_media_keys_manager'/>"
|
||||||
" <method name='GrabMediaPlayerKeys'>"
|
" <method name='GrabMediaPlayerKeys'>"
|
||||||
" <arg name='application' direction='in' type='s'/>"
|
" <arg name='application' direction='in' type='s'/>"
|
||||||
" <arg name='time' direction='in' type='u'/>"
|
" <arg name='time' direction='in' type='u'/>"
|
||||||
" </method>"
|
" </method>"
|
||||||
" <method name='ReleaseMediaPlayerKeys'>"
|
" <method name='ReleaseMediaPlayerKeys'>"
|
||||||
" <arg name='application' direction='in' type='s'/>"
|
" <arg name='application' direction='in' type='s'/>"
|
||||||
" </method>"
|
" </method>"
|
||||||
" <signal name='MediaPlayerKeyPressed'>"
|
" <signal name='MediaPlayerKeyPressed'>"
|
||||||
" <arg name='application' type='s'/>"
|
" <arg name='application' type='s'/>"
|
||||||
" <arg name='key' type='s'/>"
|
" <arg name='key' type='s'/>"
|
||||||
" </signal>"
|
" </signal>"
|
||||||
" </interface>"
|
" </interface>"
|
||||||
"</node>";
|
"</node>";
|
||||||
|
|
||||||
void grab_media_keys() {
|
void grab_media_keys() {
|
||||||
if (media_keys_proxy == NULL) { // No connection
|
if (media_keys_proxy == NULL) { // No connection
|
||||||
|
@ -63,19 +63,32 @@ 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;
|
(void) user_data;
|
||||||
g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), res, NULL); // Ensure we finish our call
|
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 handle_media_keys_signal(
|
||||||
(void) proxy; (void) sender_name; (void) user_data;
|
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
|
if (g_strcmp0(signal_name, "MediaPlayerKeyPressed") != 0) { // Not MediaPlayerKeyPressed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *application_name = NULL;
|
gchar * application_name = NULL;
|
||||||
gchar *key = NULL;
|
gchar * key = NULL;
|
||||||
|
|
||||||
|
|
||||||
g_variant_get(parameters, "(ss)", &application_name, &key);
|
g_variant_get(parameters, "(ss)", &application_name, &key);
|
||||||
|
|
||||||
|
@ -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 handle_window_enter(
|
||||||
(void) controller; (void) user_data;
|
GtkEventControllerFocus * controller,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
(void) controller;
|
||||||
|
(void) user_data;
|
||||||
grab_media_keys(); // Grab our media keys
|
grab_media_keys(); // Grab our media keys
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data) {
|
void handle_window_leave(
|
||||||
(void) controller; (void) user_data;
|
GtkEventControllerFocus * controller,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
(void) controller;
|
||||||
|
(void) user_data;
|
||||||
release_media_keys(); // Release our media keys
|
release_media_keys(); // Release our media keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +136,8 @@ void release_media_keys() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariant *params = g_variant_new_string(g_strdup("com.github.joshstrobl.koto"));
|
GVariant * params = g_variant_new_string(g_strdup("com.github.joshstrobl.koto"));
|
||||||
|
|
||||||
|
|
||||||
g_dbus_proxy_call(
|
g_dbus_proxy_call(
|
||||||
media_keys_proxy,
|
media_keys_proxy,
|
||||||
|
@ -133,8 +155,9 @@ void setup_mediakeys_interface() {
|
||||||
media_keys_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
media_keys_introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
||||||
g_assert(media_keys_introspection_data != NULL);
|
g_assert(media_keys_introspection_data != NULL);
|
||||||
|
|
||||||
GDBusConnection *bus;
|
GDBusConnection * bus;
|
||||||
GError *error = NULL;
|
GError * error = NULL;
|
||||||
|
|
||||||
|
|
||||||
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
|
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
|
|
||||||
|
@ -169,7 +192,9 @@ void setup_mediakeys_interface() {
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
GtkEventController *focus_controller = gtk_event_controller_focus_new(); // Create a new focus controller
|
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, "enter", G_CALLBACK(handle_window_enter), NULL);
|
||||||
g_signal_connect(focus_controller, "leave", G_CALLBACK(handle_window_leave), NULL);
|
g_signal_connect(focus_controller, "leave", G_CALLBACK(handle_window_leave), NULL);
|
||||||
gtk_widget_add_controller(GTK_WIDGET(main_window), focus_controller);
|
gtk_widget_add_controller(GTK_WIDGET(main_window), focus_controller);
|
||||||
|
|
|
@ -22,11 +22,33 @@
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void grab_media_keys();
|
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_media_keys_async_done(
|
||||||
void handle_window_enter(GtkEventControllerFocus *controller, gpointer user_data);
|
GObject * source_object,
|
||||||
void handle_window_leave(GtkEventControllerFocus *controller, gpointer user_data);
|
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 release_media_keys();
|
||||||
|
|
||||||
void setup_mediakeys_interface();
|
void setup_mediakeys_interface();
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -20,12 +20,18 @@
|
||||||
#include <gstreamer-1.0/gst/gst.h>
|
#include <gstreamer-1.0/gst/gst.h>
|
||||||
#include "../koto-utils.h"
|
#include "../koto-utils.h"
|
||||||
|
|
||||||
GHashTable *supported_mimes_hash = NULL;
|
GHashTable * supported_mimes_hash = NULL;
|
||||||
GList *supported_mimes = NULL;
|
GList * supported_mimes = NULL;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
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
|
if (g_str_has_prefix(caps_name, "unknown")) { // Is unknown
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -42,11 +48,16 @@ gboolean koto_playback_engine_gst_caps_iter(GstCapsFeatures *features, GstStruct
|
||||||
return TRUE;
|
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;
|
(void) user_data;
|
||||||
GstStaticPadTemplate *templ = list_data;
|
GstStaticPadTemplate * templ = list_data;
|
||||||
|
|
||||||
|
|
||||||
if (templ->direction == GST_PAD_SINK) { // Is a sink pad
|
if (templ->direction == GST_PAD_SINK) { // Is a sink pad
|
||||||
GstCaps *capabilities = gst_static_pad_template_get_caps(templ); // Get the capabilities
|
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
|
gst_caps_foreach(capabilities, koto_playback_engine_gst_caps_iter, NULL); // Iterate over and add to mimes
|
||||||
gst_caps_unref(capabilities);
|
gst_caps_unref(capabilities);
|
||||||
}
|
}
|
||||||
|
@ -55,12 +66,14 @@ void koto_playback_engine_gst_pad_iter(gpointer list_data, gpointer user_data) {
|
||||||
void koto_playback_engine_get_supported_mimetypes() {
|
void koto_playback_engine_get_supported_mimetypes() {
|
||||||
// Credit for code goes to https://github.com/mopidy/mopidy/issues/812#issuecomment-75868363
|
// Credit for code goes to https://github.com/mopidy/mopidy/issues/812#issuecomment-75868363
|
||||||
// These are GstElementFactory
|
// These are GstElementFactory
|
||||||
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 * 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;
|
||||||
|
|
||||||
|
|
||||||
GList *ele;
|
|
||||||
for (ele = elements; ele != NULL; ele = ele->next) { // For each of the elements
|
for (ele = elements; ele != NULL; ele = ele->next) { // For each of the elements
|
||||||
// GList of GstStaticPadTemplate
|
// GList of GstStaticPadTemplate
|
||||||
GList *static_pads = (GList*) gst_element_factory_get_static_pad_templates(ele->data); // Get the pads
|
GList * static_pads = (GList*) gst_element_factory_get_static_pad_templates(ele->data); // Get the pads
|
||||||
g_list_foreach(static_pads, koto_playback_engine_gst_pad_iter, NULL);
|
g_list_foreach(static_pads, koto_playback_engine_gst_pad_iter, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,17 @@
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
gboolean koto_bplayback_engine_gst_caps_iter(GstCapsFeatures *features, GstStructure *structure, gpointer user_data);
|
gboolean koto_bplayback_engine_gst_caps_iter(
|
||||||
void koto_playback_engine_gst_pad_iter(gpointer list_data, gpointer user_data);
|
GstCapsFeatures * features,
|
||||||
void koto_playback_engine_get_supported_mimetypes(GList *mimes);
|
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
|
G_END_DECLS
|
||||||
|
|
|
@ -28,73 +28,78 @@
|
||||||
#include "mimes.h"
|
#include "mimes.h"
|
||||||
#include "mpris.h"
|
#include "mpris.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoCurrentPlaylist *current_playlist;
|
extern KotoCurrentPlaylist * current_playlist;
|
||||||
extern GtkApplication *app;
|
extern GtkApplication * app;
|
||||||
extern GtkWindow *main_window;
|
extern GtkWindow * main_window;
|
||||||
extern KotoPlaybackEngine *playback_engine;
|
extern KotoPlaybackEngine * playback_engine;
|
||||||
extern GList *supported_mimes;
|
extern GList * supported_mimes;
|
||||||
|
|
||||||
GDBusConnection *dbus_conn = NULL;
|
GDBusConnection * dbus_conn = NULL;
|
||||||
guint mpris_bus_id = 0;
|
guint mpris_bus_id = 0;
|
||||||
GDBusNodeInfo *introspection_data = NULL;
|
GDBusNodeInfo * introspection_data = NULL;
|
||||||
|
|
||||||
static const gchar introspection_xml[] =
|
static const gchar introspection_xml[] =
|
||||||
"<node>"
|
"<node>"
|
||||||
" <interface name='org.mpris.MediaPlayer2'>"
|
" <interface name='org.mpris.MediaPlayer2'>"
|
||||||
" <method name='Raise' />"
|
" <method name='Raise' />"
|
||||||
" <method name='Quit' />"
|
" <method name='Quit' />"
|
||||||
" <property type='b' name='CanQuit' access='read' />"
|
" <property type='b' name='CanQuit' access='read' />"
|
||||||
" <property type='b' name='CanRaise' access='read' />"
|
" <property type='b' name='CanRaise' access='read' />"
|
||||||
" <property type='b' name='HasTrackList' access='read' />"
|
" <property type='b' name='HasTrackList' access='read' />"
|
||||||
" <property type='s' name='Identity' access='read' />"
|
" <property type='s' name='Identity' access='read' />"
|
||||||
" <property type='s' name='DesktopEntry' access='read' />"
|
" <property type='s' name='DesktopEntry' access='read' />"
|
||||||
" <property type='as' name='SupportedUriSchemas' access='read' />"
|
" <property type='as' name='SupportedUriSchemas' access='read' />"
|
||||||
" <property type='as' name='SupportedMimeTypes' access='read' />"
|
" <property type='as' name='SupportedMimeTypes' access='read' />"
|
||||||
" </interface>"
|
" </interface>"
|
||||||
" <interface name='org.mpris.MediaPlayer2.Player'>"
|
" <interface name='org.mpris.MediaPlayer2.Player'>"
|
||||||
" <method name='Next' />"
|
" <method name='Next' />"
|
||||||
" <method name='Previous' />"
|
" <method name='Previous' />"
|
||||||
" <method name='Pause' />"
|
" <method name='Pause' />"
|
||||||
" <method name='PlayPause' />"
|
" <method name='PlayPause' />"
|
||||||
" <method name='Stop' />"
|
" <method name='Stop' />"
|
||||||
" <method name='Play' />"
|
" <method name='Play' />"
|
||||||
" <method name='Seek'>"
|
" <method name='Seek'>"
|
||||||
" <arg type='x' name='offset' />"
|
" <arg type='x' name='offset' />"
|
||||||
" </method>"
|
" </method>"
|
||||||
" <method name='SetPosition'>"
|
" <method name='SetPosition'>"
|
||||||
" <arg type='o' name='track_id' />"
|
" <arg type='o' name='track_id' />"
|
||||||
" <arg type='x' name='pos' />"
|
" <arg type='x' name='pos' />"
|
||||||
" </method>"
|
" </method>"
|
||||||
" <property type='s' name='PlaybackStatus' access='read' />"
|
" <property type='s' name='PlaybackStatus' access='read' />"
|
||||||
" <property type='s' name='LoopStatus' access='readwrite' />"
|
" <property type='s' name='LoopStatus' access='readwrite' />"
|
||||||
" <property type='d' name='Rate' access='readwrite' />"
|
" <property type='d' name='Rate' access='readwrite' />"
|
||||||
" <property type='b' name='Shuffle' access='readwrite' />"
|
" <property type='b' name='Shuffle' access='readwrite' />"
|
||||||
" <property type='a{sv}' name='Metadata' access='read' />"
|
" <property type='a{sv}' name='Metadata' access='read' />"
|
||||||
" <property type='d' name='Volume' access='readwrite' />"
|
" <property type='d' name='Volume' access='readwrite' />"
|
||||||
" <property type='x' name='Position' access='read' />"
|
" <property type='x' name='Position' access='read' />"
|
||||||
" <property type='d' name='MinimumRate' access='read' />"
|
" <property type='d' name='MinimumRate' access='read' />"
|
||||||
" <property type='d' name='MaximumRate' access='read' />"
|
" <property type='d' name='MaximumRate' access='read' />"
|
||||||
" <property type='b' name='CanGoNext' access='read' />"
|
" <property type='b' name='CanGoNext' access='read' />"
|
||||||
" <property type='b' name='CanGoPrevious' access='read' />"
|
" <property type='b' name='CanGoPrevious' access='read' />"
|
||||||
" <property type='b' name='CanPlay' access='read' />"
|
" <property type='b' name='CanPlay' access='read' />"
|
||||||
" <property type='b' name='CanPause' access='read' />"
|
" <property type='b' name='CanPause' access='read' />"
|
||||||
" <property type='b' name='CanSeek' access='read' />"
|
" <property type='b' name='CanSeek' access='read' />"
|
||||||
" <property type='b' name='CanControl' access='read' />"
|
" <property type='b' name='CanControl' access='read' />"
|
||||||
" </interface>"
|
" </interface>"
|
||||||
"</node>";
|
"</node>";
|
||||||
|
|
||||||
void handle_method_call(
|
void handle_method_call(
|
||||||
GDBusConnection *connection,
|
GDBusConnection * connection,
|
||||||
const gchar *sender,
|
const gchar * sender,
|
||||||
const gchar *object_path,
|
const gchar * object_path,
|
||||||
const gchar *interface_name,
|
const gchar * interface_name,
|
||||||
const gchar *method_name,
|
const gchar * method_name,
|
||||||
GVariant *parameters,
|
GVariant * parameters,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation * invocation,
|
||||||
gpointer user_data
|
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(interface_name, "org.mpris.MediaPlayer2") == 0) { // Root mediaplayer2 interface
|
||||||
if (g_strcmp0(method_name, "Raise") == 0) { // Raise the window
|
if (g_strcmp0(method_name, "Raise") == 0) { // Raise the window
|
||||||
|
@ -140,17 +145,24 @@ void handle_method_call(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariant* handle_get_property(
|
GVariant * handle_get_property(
|
||||||
GDBusConnection *connection,
|
GDBusConnection * connection,
|
||||||
const gchar *sender,
|
const gchar * sender,
|
||||||
const gchar *object_path,
|
const gchar * object_path,
|
||||||
const gchar *interface_name,
|
const gchar * interface_name,
|
||||||
const gchar *property_name,
|
const gchar * property_name,
|
||||||
GError **error,
|
GError ** error,
|
||||||
gpointer user_data
|
gpointer user_data
|
||||||
) {
|
) {
|
||||||
(void) connection; (void) sender; (void) object_path; (void) interface_name; (void) error; (void) user_data;
|
(void) connection;
|
||||||
GVariant *ret;
|
(void) sender;
|
||||||
|
(void) object_path;
|
||||||
|
(void) interface_name;
|
||||||
|
(void) error;
|
||||||
|
(void) user_data;
|
||||||
|
GVariant * ret;
|
||||||
|
|
||||||
|
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "CanQuit") == 0) { // If property is CanQuit
|
if (g_strcmp0(property_name, "CanQuit") == 0) { // If property is CanQuit
|
||||||
|
@ -162,7 +174,7 @@ GVariant* handle_get_property(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "HasTrackList") == 0) { // If property is HasTrackList
|
if (g_strcmp0(property_name, "HasTrackList") == 0) { // If property is HasTrackList
|
||||||
KotoPlaylist *playlist = koto_current_playlist_get_playlist(current_playlist);
|
KotoPlaylist * playlist = koto_current_playlist_get_playlist(current_playlist);
|
||||||
if (KOTO_IS_PLAYLIST(playlist)) {
|
if (KOTO_IS_PLAYLIST(playlist)) {
|
||||||
ret = g_variant_new_boolean(koto_playlist_get_length(playlist) > 0);
|
ret = g_variant_new_boolean(koto_playlist_get_length(playlist) > 0);
|
||||||
} else { // Don't have a playlist
|
} else { // Don't have a playlist
|
||||||
|
@ -179,15 +191,15 @@ GVariant* handle_get_property(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "SupportedUriSchemas") == 0) { // Supported URI Schemas
|
if (g_strcmp0(property_name, "SupportedUriSchemas") == 0) { // Supported URI Schemas
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("as")); // Array of strings
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE("as")); // Array of strings
|
||||||
g_variant_builder_add(builder, "s", "file");
|
g_variant_builder_add(builder, "s", "file");
|
||||||
ret = g_variant_new("as", builder);
|
ret = g_variant_new("as", builder);
|
||||||
g_variant_builder_unref(builder); // Unref builder since we no longer need it
|
g_variant_builder_unref(builder); // Unref builder since we no longer need it
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "SupportedMimeTypes") == 0) { // Supported mimetypes
|
if (g_strcmp0(property_name, "SupportedMimeTypes") == 0) { // Supported mimetypes
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE("as")); // Array of strings
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE("as")); // Array of strings
|
||||||
GList *mimes;
|
GList * mimes;
|
||||||
mimes = NULL;
|
mimes = NULL;
|
||||||
|
|
||||||
for (mimes = supported_mimes; mimes != NULL; mimes = mimes->next) { // For each mimetype
|
for (mimes = supported_mimes; mimes != NULL; mimes = mimes->next) { // For each mimetype
|
||||||
|
@ -200,21 +212,21 @@ GVariant* handle_get_property(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "Metadata") == 0) { // Metadata
|
if (g_strcmp0(property_name, "Metadata") == 0) { // Metadata
|
||||||
KotoIndexedTrack *current_track = koto_playback_engine_get_current_track(playback_engine);
|
KotoIndexedTrack * current_track = koto_playback_engine_get_current_track(playback_engine);
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_TRACK(current_track)) { // Currently playing a track
|
if (KOTO_IS_INDEXED_TRACK(current_track)) { // Currently playing a track
|
||||||
ret = koto_indexed_track_get_metadata_vardict(current_track);
|
ret = koto_indexed_track_get_metadata_vardict(current_track);
|
||||||
} else { // No track
|
} else { // No track
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT); // Create an empty builder
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_VARDICT); // Create an empty builder
|
||||||
ret = g_variant_builder_end(builder); // return the vardict
|
ret = g_variant_builder_end(builder); // return the vardict
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(g_strcmp0(property_name, "CanPlay") == 0) ||
|
(g_strcmp0(property_name, "CanPlay") == 0) ||
|
||||||
(g_strcmp0(property_name, "CanPause") == 0)
|
(g_strcmp0(property_name, "CanPause") == 0)
|
||||||
) {
|
) {
|
||||||
KotoIndexedTrack *current_track = koto_playback_engine_get_current_track(playback_engine);
|
KotoIndexedTrack * current_track = koto_playback_engine_get_current_track(playback_engine);
|
||||||
ret = g_variant_new_boolean(KOTO_IS_INDEXED_TRACK(current_track));
|
ret = g_variant_new_boolean(KOTO_IS_INDEXED_TRACK(current_track));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +244,7 @@ GVariant* handle_get_property(
|
||||||
ret = g_variant_new_boolean(TRUE);
|
ret = g_variant_new_boolean(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_strcmp0(property_name, "CanControl") == 0){ // Can Control
|
if (g_strcmp0(property_name, "CanControl") == 0) { // Can Control
|
||||||
ret = g_variant_new_boolean(TRUE);
|
ret = g_variant_new_boolean(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,16 +264,21 @@ GVariant* handle_get_property(
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean handle_set_property(
|
gboolean handle_set_property(
|
||||||
GDBusConnection *connection,
|
GDBusConnection * connection,
|
||||||
const gchar *sender,
|
const gchar * sender,
|
||||||
const gchar *object_path,
|
const gchar * object_path,
|
||||||
const gchar *interface_name,
|
const gchar * interface_name,
|
||||||
const gchar *property_name,
|
const gchar * property_name,
|
||||||
GVariant *value,
|
GVariant * value,
|
||||||
GError **error,
|
GError ** error,
|
||||||
gpointer user_data
|
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
|
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
|
koto_playback_engine_set_track_repeat(playback_engine, g_variant_get_boolean(value)); // Set the loop status state
|
||||||
|
@ -277,7 +294,8 @@ gboolean handle_set_property(
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_update_mpris_playback_state(GstState state) {
|
void koto_update_mpris_playback_state(GstState state) {
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||||
|
|
||||||
|
|
||||||
if (state == GST_STATE_PLAYING) {
|
if (state == GST_STATE_PLAYING) {
|
||||||
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Playing"));
|
g_variant_builder_add(builder, "{sv}", "PlaybackStatus", g_variant_new_string("Playing"));
|
||||||
|
@ -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_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,
|
NULL,
|
||||||
"/org/mpris/MediaPlayer2",
|
"/org/mpris/MediaPlayer2",
|
||||||
"org.freedesktop.DBus.Properties",
|
"org.freedesktop.DBus.Properties",
|
||||||
|
@ -297,24 +316,32 @@ void koto_update_mpris_playback_state(GstState state) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_update_mpris_info_for_track(KotoIndexedTrack *track) {
|
void koto_update_mpris_info_for_track(KotoIndexedTrack * track) {
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariant *metadata = koto_indexed_track_get_metadata_vardict(track); // Get the GVariantBuilder variable dict for the metadata
|
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);
|
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)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GVariantBuilder *builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
|
||||||
|
|
||||||
|
|
||||||
g_variant_builder_add(builder, "{sv}", "Metadata", metadata);
|
g_variant_builder_add(builder, "{sv}", "Metadata", metadata);
|
||||||
|
|
||||||
g_dbus_connection_emit_signal(dbus_conn,
|
g_dbus_connection_emit_signal(
|
||||||
|
dbus_conn,
|
||||||
NULL,
|
NULL,
|
||||||
"/org/mpris/MediaPlayer2",
|
"/org/mpris/MediaPlayer2",
|
||||||
"org.freedesktop.DBus.Properties",
|
"org.freedesktop.DBus.Properties",
|
||||||
|
@ -331,10 +358,16 @@ static const GDBusInterfaceVTable main_mpris_interface_vtable = {
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) {
|
void on_main_mpris_bus_acquired(
|
||||||
(void) name; (void) user_data;
|
GDBusConnection * connection,
|
||||||
|
const gchar * name,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
(void) name;
|
||||||
|
(void) user_data;
|
||||||
dbus_conn = connection;
|
dbus_conn = connection;
|
||||||
g_dbus_connection_register_object(dbus_conn,
|
g_dbus_connection_register_object(
|
||||||
|
dbus_conn,
|
||||||
"/org/mpris/MediaPlayer2",
|
"/org/mpris/MediaPlayer2",
|
||||||
introspection_data->interfaces[0],
|
introspection_data->interfaces[0],
|
||||||
&main_mpris_interface_vtable,
|
&main_mpris_interface_vtable,
|
||||||
|
@ -343,7 +376,8 @@ void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
g_dbus_connection_register_object(dbus_conn,
|
g_dbus_connection_register_object(
|
||||||
|
dbus_conn,
|
||||||
"/org/mpris/MediaPlayer2",
|
"/org/mpris/MediaPlayer2",
|
||||||
introspection_data->interfaces[1],
|
introspection_data->interfaces[1],
|
||||||
&main_mpris_interface_vtable,
|
&main_mpris_interface_vtable,
|
||||||
|
@ -357,7 +391,8 @@ void setup_mpris_interfaces() {
|
||||||
introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
|
||||||
g_assert(introspection_data != 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",
|
"org.mpris.MediaPlayer2.koto",
|
||||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||||
on_main_mpris_bus_acquired,
|
on_main_mpris_bus_acquired,
|
||||||
|
|
|
@ -22,10 +22,50 @@
|
||||||
#include "../indexer/structs.h"
|
#include "../indexer/structs.h"
|
||||||
|
|
||||||
void koto_update_mpris_playback_state(GstState state);
|
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 koto_update_mpris_info_for_track(KotoIndexedTrack * track);
|
||||||
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);
|
void koto_update_mpris_info_for_track_with_metadata(
|
||||||
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);
|
KotoIndexedTrack * track,
|
||||||
void on_main_mpris_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data);
|
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();
|
void setup_mpris_interfaces();
|
||||||
|
|
|
@ -22,27 +22,27 @@
|
||||||
#include "../playlist/playlist.h"
|
#include "../playlist/playlist.h"
|
||||||
#include "add-remove-track-popover.h"
|
#include "add-remove-track-popover.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
|
|
||||||
struct _KotoAddRemoveTrackPopover {
|
struct _KotoAddRemoveTrackPopover {
|
||||||
GtkPopover parent_instance;
|
GtkPopover parent_instance;
|
||||||
GtkWidget *list_box;
|
GtkWidget * list_box;
|
||||||
GHashTable *checkbox_to_playlist_uuid;
|
GHashTable * checkbox_to_playlist_uuid;
|
||||||
GHashTable *playlist_uuid_to_checkbox;
|
GHashTable * playlist_uuid_to_checkbox;
|
||||||
GList *tracks;
|
GList * tracks;
|
||||||
|
|
||||||
GHashTable *checkbox_to_signal_ids;
|
GHashTable * checkbox_to_signal_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, GTK_TYPE_POPOVER);
|
G_DEFINE_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, GTK_TYPE_POPOVER);
|
||||||
|
|
||||||
KotoAddRemoveTrackPopover *koto_add_remove_track_popup = NULL;
|
KotoAddRemoveTrackPopover * koto_add_remove_track_popup = NULL;
|
||||||
|
|
||||||
static void koto_add_remove_track_popover_class_init(KotoAddRemoveTrackPopoverClass *c) {
|
static void koto_add_remove_track_popover_class_init(KotoAddRemoveTrackPopoverClass * c) {
|
||||||
(void) c;
|
(void) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_add_remove_track_popover_init(KotoAddRemoveTrackPopover *self) {
|
static void koto_add_remove_track_popover_init(KotoAddRemoveTrackPopover * self) {
|
||||||
self->list_box = gtk_list_box_new(); // Create our new GtkListBox
|
self->list_box = gtk_list_box_new(); // Create our new GtkListBox
|
||||||
gtk_list_box_set_selection_mode(GTK_LIST_BOX(self->list_box), GTK_SELECTION_NONE);
|
gtk_list_box_set_selection_mode(GTK_LIST_BOX(self->list_box), GTK_SELECTION_NONE);
|
||||||
|
|
||||||
|
@ -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);
|
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)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -67,24 +70,29 @@ void koto_add_remove_track_popover_add_playlist(KotoAddRemoveTrackPopover *self,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *playlist_uuid = koto_playlist_get_uuid(playlist); // Get the UUID of the playlist
|
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
|
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);
|
g_free(playlist_uuid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkWidget *playlist_button = gtk_check_button_new_with_label(koto_playlist_get_name(playlist)); // Create our GtkCheckButton
|
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->checkbox_to_playlist_uuid, playlist_button, playlist_uuid);
|
||||||
g_hash_table_insert(self->playlist_uuid_to_checkbox, playlist_uuid, playlist_button);
|
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);
|
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
|
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
|
gtk_list_box_append(GTK_LIST_BOX(self->list_box), playlist_button); // Add the playlist to the list box
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_add_remove_track_popover_clear_tracks(KotoAddRemoveTrackPopover *self) {
|
void koto_add_remove_track_popover_clear_tracks(KotoAddRemoveTrackPopover * self) {
|
||||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +115,8 @@ void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *se
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkCheckButton *btn = GTK_CHECK_BUTTON(g_hash_table_lookup(self->playlist_uuid_to_checkbox, playlist_uuid)); // Get the check button
|
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
|
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
|
g_hash_table_remove(self->checkbox_to_playlist_uuid, btn); // Remove uuid based on btn
|
||||||
|
@ -114,31 +126,38 @@ void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *se
|
||||||
g_hash_table_remove(self->playlist_uuid_to_checkbox, playlist_uuid);
|
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(
|
||||||
KotoAddRemoveTrackPopover *self = user_data;
|
GtkCheckButton * btn,
|
||||||
|
gpointer user_data
|
||||||
|
) {
|
||||||
|
KotoAddRemoveTrackPopover * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean should_add = gtk_check_button_get_active(btn); // Get the now active state
|
gboolean should_add = gtk_check_button_get_active(btn); // Get the now active state
|
||||||
gchar *playlist_uuid = g_hash_table_lookup(self->checkbox_to_playlist_uuid, btn); // Get the playlist UUID for this button
|
gchar * playlist_uuid = g_hash_table_lookup(self->checkbox_to_playlist_uuid, btn); // Get the playlist UUID for this button
|
||||||
|
|
||||||
|
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid); // Get the playlist
|
||||||
|
|
||||||
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
|
if (!KOTO_IS_PLAYLIST(playlist)) { // Failed to get the playlist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *pos;
|
GList * pos;
|
||||||
|
|
||||||
|
|
||||||
for (pos = self->tracks; pos != NULL; pos = pos->next) { // Iterate over our KotoIndexedTracks
|
for (pos = self->tracks; pos != NULL; pos = pos->next) { // Iterate over our KotoIndexedTracks
|
||||||
KotoIndexedTrack *track = pos->data;
|
KotoIndexedTrack * track = pos->data;
|
||||||
|
|
||||||
if (!KOTO_INDEXED_TRACK(track)) { // Not a track
|
if (!KOTO_INDEXED_TRACK(track)) { // Not a track
|
||||||
continue; // Skip this
|
continue; // Skip this
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *track_uuid = koto_indexed_track_get_uuid(track); // Get the track
|
gchar * track_uuid = koto_indexed_track_get_uuid(track); // Get the track
|
||||||
|
|
||||||
if (should_add) { // Should be adding
|
if (should_add) { // Should be adding
|
||||||
koto_playlist_add_track_by_uuid(playlist, track_uuid, FALSE, TRUE); // Add the track to the playlist
|
koto_playlist_add_track_by_uuid(playlist, track_uuid, FALSE, TRUE); // Add the track to the playlist
|
||||||
|
@ -150,9 +169,14 @@ void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn
|
||||||
gtk_popover_popdown(GTK_POPOVER(self)); // Temporary to hopefully prevent a bork
|
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;
|
(void) carto;
|
||||||
KotoAddRemoveTrackPopover *self = user_data;
|
KotoAddRemoveTrackPopover * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -161,9 +185,14 @@ void koto_add_remove_track_popover_handle_playlist_added(KotoCartographer *carto
|
||||||
koto_add_remove_track_popover_add_playlist(self, playlist);
|
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;
|
(void) carto;
|
||||||
KotoAddRemoveTrackPopover *self = user_data;
|
KotoAddRemoveTrackPopover * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
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);
|
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)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
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));
|
GtkWidget* existing_parent = gtk_widget_get_parent(GTK_WIDGET(self));
|
||||||
|
|
||||||
|
|
||||||
if (existing_parent != NULL) {
|
if (existing_parent != NULL) {
|
||||||
g_object_ref(GTK_WIDGET(self)); // Increment widget ref since unparent will do an unref
|
g_object_ref(GTK_WIDGET(self)); // Increment widget ref since unparent will do an unref
|
||||||
gtk_widget_unparent(GTK_WIDGET(self)); // Unparent the popup
|
gtk_widget_unparent(GTK_WIDGET(self)); // Unparent the popup
|
||||||
|
@ -192,30 +226,35 @@ void koto_add_remove_track_popover_set_pointing_to_widget(KotoAddRemoveTrackPopo
|
||||||
gtk_popover_set_position(GTK_POPOVER(self), pos);
|
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)) {
|
if (!KOTO_JS_ADD_REMOVE_TRACK_POPOVER(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint tracks_len = g_list_length(tracks);
|
gint tracks_len = g_list_length(tracks);
|
||||||
|
|
||||||
|
|
||||||
if (tracks_len == 0) { // No tracks
|
if (tracks_len == 0) { // No tracks
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->tracks = g_list_copy(tracks);
|
self->tracks = g_list_copy(tracks);
|
||||||
GHashTable *playlists = koto_cartographer_get_playlists(koto_maps); // Get our playlists
|
GHashTable * playlists = koto_cartographer_get_playlists(koto_maps); // Get our playlists
|
||||||
GHashTableIter playlists_iter;
|
GHashTableIter playlists_iter;
|
||||||
gpointer uuid, playlist_ptr;
|
gpointer uuid, playlist_ptr;
|
||||||
|
|
||||||
|
|
||||||
g_hash_table_iter_init(&playlists_iter, playlists); // Init our HashTable iterator
|
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
|
while (g_hash_table_iter_next(&playlists_iter, &uuid, &playlist_ptr)) { // While we are iterating through our playlists
|
||||||
KotoPlaylist *playlist = playlist_ptr;
|
KotoPlaylist * playlist = playlist_ptr;
|
||||||
gboolean should_be_checked = FALSE;
|
gboolean should_be_checked = FALSE;
|
||||||
|
|
||||||
if (tracks_len > 1) { // More than one track
|
if (tracks_len > 1) { // More than one track
|
||||||
GList *pos;
|
GList * pos;
|
||||||
for (pos = self->tracks; pos != NULL; pos = pos->next) { // Iterate over our tracks
|
for (pos = self->tracks; pos != NULL; pos = pos->next) { // Iterate over our tracks
|
||||||
should_be_checked = (koto_playlist_get_position_of_track(playlist, pos->data) != -1);
|
should_be_checked = (koto_playlist_get_position_of_track(playlist, pos->data) != -1);
|
||||||
|
|
||||||
|
@ -224,7 +263,7 @@ void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
KotoIndexedTrack *track = g_list_nth_data(self->tracks, 0); // Get the first track
|
KotoIndexedTrack * track = g_list_nth_data(self->tracks, 0); // Get the first track
|
||||||
|
|
||||||
if (KOTO_IS_INDEXED_TRACK(track)) {
|
if (KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
gint pos = koto_playlist_get_position_of_track(playlist, track);
|
gint pos = koto_playlist_get_position_of_track(playlist, track);
|
||||||
|
@ -232,7 +271,7 @@ void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GtkCheckButton *playlist_check = g_hash_table_lookup(self->playlist_uuid_to_checkbox, uuid); // Get the GtkCheckButton for this playlist
|
GtkCheckButton * playlist_check = g_hash_table_lookup(self->playlist_uuid_to_checkbox, uuid); // Get the GtkCheckButton for this playlist
|
||||||
|
|
||||||
if (GTK_IS_CHECK_BUTTON(playlist_check)) { // Is a checkbox
|
if (GTK_IS_CHECK_BUTTON(playlist_check)) { // Is a checkbox
|
||||||
gpointer sig_id_ptr = g_hash_table_lookup(self->checkbox_to_signal_ids, playlist_check);
|
gpointer sig_id_ptr = g_hash_table_lookup(self->checkbox_to_signal_ids, playlist_check);
|
||||||
|
@ -244,6 +283,6 @@ void koto_add_remove_track_popover_set_tracks(KotoAddRemoveTrackPopover *self, G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoAddRemoveTrackPopover* koto_add_remove_track_popover_new() {
|
KotoAddRemoveTrackPopover * koto_add_remove_track_popover_new() {
|
||||||
return g_object_new(KOTO_TYPE_ADD_REMOVE_TRACK_POPOVER, NULL);
|
return g_object_new(KOTO_TYPE_ADD_REMOVE_TRACK_POPOVER, NULL);
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_ADD_REMOVE_TRACK_POPOVER koto_add_remove_track_popover_get_type()
|
#define KOTO_TYPE_ADD_REMOVE_TRACK_POPOVER koto_add_remove_track_popover_get_type()
|
||||||
G_DECLARE_FINAL_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, KOTO, ADD_REMOVE_TRACK_POPOVER, GtkPopover);
|
G_DECLARE_FINAL_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, KOTO, ADD_REMOVE_TRACK_POPOVER, GtkPopover);
|
||||||
|
@ -33,16 +33,48 @@ G_DECLARE_FINAL_TYPE(KotoAddRemoveTrackPopover, koto_add_remove_track_popover, K
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions
|
* Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoAddRemoveTrackPopover* koto_add_remove_track_popover_new();
|
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_clear_tracks(KotoAddRemoveTrackPopover *self);
|
void koto_add_remove_track_popover_add_playlist(
|
||||||
void koto_add_remove_track_popover_remove_playlist(KotoAddRemoveTrackPopover *self, gchar *playlist_uuid);
|
KotoAddRemoveTrackPopover * self,
|
||||||
void koto_add_remove_track_popover_handle_checkbutton_toggle(GtkCheckButton *btn, gpointer user_data);
|
KotoPlaylist * playlist
|
||||||
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_clear_tracks(KotoAddRemoveTrackPopover * self);
|
||||||
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
|
G_END_DECLS
|
|
@ -24,8 +24,8 @@
|
||||||
#include "../koto-window.h"
|
#include "../koto-window.h"
|
||||||
#include "create-modify-dialog.h"
|
#include "create-modify-dialog.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern KotoWindow *main_window;
|
extern KotoWindow * main_window;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_DIALOG_0,
|
PROP_DIALOG_0,
|
||||||
|
@ -33,29 +33,44 @@ enum {
|
||||||
N_PROPS
|
N_PROPS
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *dialog_props[N_PROPS] = { NULL, };
|
static GParamSpec * dialog_props[N_PROPS] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct _KotoCreateModifyPlaylistDialog {
|
struct _KotoCreateModifyPlaylistDialog {
|
||||||
GtkBox parent_instance;
|
GtkBox parent_instance;
|
||||||
GtkWidget *playlist_image;
|
GtkWidget * playlist_image;
|
||||||
GtkWidget *name_entry;
|
GtkWidget * name_entry;
|
||||||
|
|
||||||
GtkWidget *create_button;
|
GtkWidget * create_button;
|
||||||
|
|
||||||
gchar *playlist_image_path;
|
gchar * playlist_image_path;
|
||||||
gchar *playlist_uuid;
|
gchar * playlist_uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist_dialog, GTK_TYPE_BOX);
|
G_DEFINE_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist_dialog, GTK_TYPE_BOX);
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog *playlist_create_modify_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_class_init(KotoCreateModifyPlaylistDialogClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_create_modify_playlist_dialog_set_property;
|
gobject_class->set_property = koto_create_modify_playlist_dialog_set_property;
|
||||||
gobject_class->get_property = koto_create_modify_playlist_dialog_get_property;
|
gobject_class->get_property = koto_create_modify_playlist_dialog_get_property;
|
||||||
|
@ -65,13 +80,13 @@ static void koto_create_modify_playlist_dialog_class_init(KotoCreateModifyPlayli
|
||||||
"Playlist UUID",
|
"Playlist UUID",
|
||||||
"Playlist UUID",
|
"Playlist UUID",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPS, dialog_props);
|
g_object_class_install_properties(gobject_class, N_PROPS, dialog_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDialog *self) {
|
static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDialog * self) {
|
||||||
self->playlist_image_path = NULL;
|
self->playlist_image_path = NULL;
|
||||||
|
|
||||||
gtk_widget_set_halign(GTK_WIDGET(self), GTK_ALIGN_CENTER);
|
gtk_widget_set_halign(GTK_WIDGET(self), GTK_ALIGN_CENTER);
|
||||||
|
@ -82,11 +97,15 @@ static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDial
|
||||||
gtk_widget_set_size_request(self->playlist_image, 220, 220);
|
gtk_widget_set_size_request(self->playlist_image, 220, 220);
|
||||||
gtk_box_append(GTK_BOX(self), self->playlist_image); // Add our image
|
gtk_box_append(GTK_BOX(self), self->playlist_image); // Add our image
|
||||||
|
|
||||||
GtkDropTarget *target = gtk_drop_target_new(G_TYPE_FILE, GDK_ACTION_COPY);
|
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);
|
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));
|
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
|
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
|
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);
|
g_signal_connect(GTK_EVENT_CONTROLLER(image_click_controller), "pressed", G_CALLBACK(koto_create_modify_playlist_dialog_handle_image_click), self);
|
||||||
|
|
||||||
|
@ -105,8 +124,14 @@ static void koto_create_modify_playlist_dialog_init(KotoCreateModifyPlaylistDial
|
||||||
gtk_box_append(GTK_BOX(self), self->create_button); // Add the create button
|
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(
|
||||||
KotoCreateModifyPlaylistDialog *self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoCreateModifyPlaylistDialog * self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PLAYLIST_UUID:
|
case PROP_PLAYLIST_UUID:
|
||||||
|
@ -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(
|
||||||
KotoCreateModifyPlaylistDialog *self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
GObject * obj,
|
||||||
(void) self; (void) val;
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoCreateModifyPlaylistDialog * self = KOTO_CREATE_MODIFY_PLAYLIST_DIALOG(obj);
|
||||||
|
|
||||||
|
|
||||||
|
(void) self;
|
||||||
|
(void) val;
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_PLAYLIST_UUID:
|
case PROP_PLAYLIST_UUID:
|
||||||
|
@ -132,19 +165,26 @@ 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
|
if (response != GTK_RESPONSE_ACCEPT) { // Not accept
|
||||||
g_object_unref(native);
|
g_object_unref(native);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog *self = user_data;
|
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFile *file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
GFile * file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(native));
|
||||||
gchar *file_path = g_file_get_path(file); // Get the absolute path
|
gchar * file_path = g_file_get_path(file); // Get the absolute path
|
||||||
|
|
||||||
|
|
||||||
if (file_path != NULL) {
|
if (file_path != NULL) {
|
||||||
self->playlist_image_path = g_strdup(file_path);
|
self->playlist_image_path = g_strdup(file_path);
|
||||||
|
@ -156,10 +196,14 @@ void koto_create_modify_playlist_dialog_handle_chooser_response(GtkNativeDialog
|
||||||
g_object_unref(native);
|
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;
|
(void) button;
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog *self = user_data;
|
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
||||||
return;
|
return;
|
||||||
|
@ -170,9 +214,10 @@ void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, g
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist *playlist = NULL;
|
KotoPlaylist * playlist = NULL;
|
||||||
gboolean modify_existing_playlist = koto_utils_is_string_valid(self->playlist_uuid);
|
gboolean modify_existing_playlist = koto_utils_is_string_valid(self->playlist_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (modify_existing_playlist) { // Modifying an existing playlist
|
if (modify_existing_playlist) { // Modifying an existing playlist
|
||||||
playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->playlist_uuid);
|
playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, self->playlist_uuid);
|
||||||
} else { // Creating a new playlist
|
} else { // Creating a new playlist
|
||||||
|
@ -196,21 +241,32 @@ void koto_create_modify_playlist_dialog_handle_create_click(GtkButton *button, g
|
||||||
koto_window_hide_dialogs(main_window); // Hide the dialogs
|
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) {
|
gboolean koto_create_modify_playlist_dialog_handle_drop(
|
||||||
(void) target; (void) x; (void) y;
|
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
|
if (!G_VALUE_HOLDS(val, G_TYPE_FILE)) { // Not a file
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog *self = user_data;
|
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) { // No dialog
|
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) { // No dialog
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFile *dropped_file = g_value_get_object(val); // Get the GValue
|
GFile * dropped_file = g_value_get_object(val); // Get the GValue
|
||||||
gchar *file_path = g_file_get_path(dropped_file); // Get the absolute path
|
gchar * file_path = g_file_get_path(dropped_file); // Get the absolute path
|
||||||
|
|
||||||
|
|
||||||
g_object_unref(dropped_file); // Unref the file
|
g_object_unref(dropped_file); // Unref the file
|
||||||
|
|
||||||
if (file_path == NULL) {
|
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);
|
magic_t magic_cookie = magic_open(MAGIC_MIME);
|
||||||
|
|
||||||
|
|
||||||
if (magic_cookie == NULL) {
|
if (magic_cookie == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -227,7 +284,8 @@ gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, c
|
||||||
goto cookie_closure;
|
goto cookie_closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *mime_type = magic_file(magic_cookie, file_path);
|
const char * mime_type = magic_file(magic_cookie, file_path);
|
||||||
|
|
||||||
|
|
||||||
if ((mime_type != NULL) && g_str_has_prefix(mime_type, "image/")) { // Is an image
|
if ((mime_type != NULL) && g_str_has_prefix(mime_type, "image/")) { // Is an image
|
||||||
self->playlist_image_path = g_strdup(file_path);
|
self->playlist_image_path = g_strdup(file_path);
|
||||||
|
@ -237,21 +295,32 @@ gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, c
|
||||||
}
|
}
|
||||||
|
|
||||||
cookie_closure:
|
cookie_closure:
|
||||||
magic_close(magic_cookie);
|
magic_close(magic_cookie);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
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_image_click(
|
||||||
(void) gesture; (void) n_press; (void) x; (void) y;
|
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;
|
KotoCreateModifyPlaylistDialog * self = user_data;
|
||||||
|
|
||||||
GtkFileChooserNative* chooser = koto_utils_create_image_file_chooser("Choose playlist image");
|
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);
|
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
|
gtk_native_dialog_show(GTK_NATIVE_DIALOG(chooser)); // Show our file chooser
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog *self) {
|
void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog * self) {
|
||||||
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
if (!KOTO_IS_CURRENT_MODIFY_PLAYLIST(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -262,12 +331,16 @@ void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog *se
|
||||||
gtk_button_set_label(GTK_BUTTON(self->create_button), "Create");
|
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
|
if (!koto_utils_is_string_valid(playlist_uuid)) { // Not a valid playlist UUID string
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist *playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid);
|
KotoPlaylist * playlist = koto_cartographer_get_playlist_by_uuid(koto_maps, playlist_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_PLAYLIST(playlist)) {
|
if (!KOTO_IS_PLAYLIST(playlist)) {
|
||||||
return;
|
return;
|
||||||
|
@ -277,7 +350,8 @@ void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlayli
|
||||||
gtk_entry_buffer_set_text(gtk_entry_get_buffer(GTK_ENTRY(self->name_entry)), koto_playlist_get_name(playlist), -1); // Update the input buffer
|
gtk_entry_buffer_set_text(gtk_entry_get_buffer(GTK_ENTRY(self->name_entry)), koto_playlist_get_name(playlist), -1); // Update the input buffer
|
||||||
gtk_entry_set_placeholder_text(GTK_ENTRY(self->name_entry), ""); // Clear placeholder
|
gtk_entry_set_placeholder_text(GTK_ENTRY(self->name_entry), ""); // Clear placeholder
|
||||||
|
|
||||||
gchar *art = koto_playlist_get_artwork(playlist);
|
gchar * art = koto_playlist_get_artwork(playlist);
|
||||||
|
|
||||||
|
|
||||||
if (!koto_utils_is_string_valid(art)) { // If art is not defined
|
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
|
gtk_image_set_from_icon_name(GTK_IMAGE(self->playlist_image), "insert-image-symbolic"); // Reset the image
|
||||||
|
@ -289,13 +363,8 @@ void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlayli
|
||||||
gtk_button_set_label(GTK_BUTTON(self->create_button), "Save");
|
gtk_button_set_label(GTK_BUTTON(self->create_button), "Save");
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog* koto_create_modify_playlist_dialog_new(char *playlist_uuid) {
|
KotoCreateModifyPlaylistDialog * koto_create_modify_playlist_dialog_new(char * playlist_uuid) {
|
||||||
(void) playlist_uuid;
|
(void) playlist_uuid;
|
||||||
|
|
||||||
return g_object_new(KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG,
|
return g_object_new(KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG, "orientation", GTK_ORIENTATION_VERTICAL, "spacing", 40, NULL);
|
||||||
"orientation",
|
|
||||||
GTK_ORIENTATION_VERTICAL,
|
|
||||||
"spacing",
|
|
||||||
40,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG koto_create_modify_playlist_dialog_get_type()
|
#define KOTO_TYPE_CREATE_MODIFY_PLAYLIST_DIALOG koto_create_modify_playlist_dialog_get_type()
|
||||||
G_DECLARE_FINAL_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist_dialog, KOTO, CREATE_MODIFY_PLAYLIST_DIALOG, GtkBox);
|
G_DECLARE_FINAL_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist_dialog, KOTO, CREATE_MODIFY_PLAYLIST_DIALOG, GtkBox);
|
||||||
|
@ -31,14 +31,42 @@ G_DECLARE_FINAL_TYPE(KotoCreateModifyPlaylistDialog, koto_create_modify_playlist
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions
|
* Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoCreateModifyPlaylistDialog* koto_create_modify_playlist_dialog_new();
|
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);
|
void koto_create_modify_playlist_dialog_handle_chooser_response(
|
||||||
gboolean koto_create_modify_playlist_dialog_handle_drop(GtkDropTarget *target, const GValue *val, double x, double y, gpointer user_data);
|
GtkNativeDialog * native,
|
||||||
void koto_create_modify_playlist_dialog_handle_image_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data);
|
int response,
|
||||||
void koto_create_modify_playlist_dialog_reset(KotoCreateModifyPlaylistDialog *self);
|
gpointer user_data
|
||||||
void koto_create_modify_playlist_dialog_set_playlist_uuid(KotoCreateModifyPlaylistDialog *self, gchar *playlist_uuid);
|
);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -24,22 +24,37 @@ enum {
|
||||||
N_PROPERTIES
|
N_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
KotoCurrentPlaylist *current_playlist = NULL;
|
KotoCurrentPlaylist * current_playlist = NULL;
|
||||||
|
|
||||||
struct _KotoCurrentPlaylist {
|
struct _KotoCurrentPlaylist {
|
||||||
GObject parent_class;
|
GObject parent_class;
|
||||||
KotoPlaylist *current_playlist;
|
KotoPlaylist * current_playlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoCurrentPlaylist, koto_current_playlist, G_TYPE_OBJECT);
|
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_get_property(
|
||||||
static void koto_current_playlist_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
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;
|
||||||
|
|
||||||
|
|
||||||
static void koto_current_playlist_class_init(KotoCurrentPlaylistClass *c) {
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
gobject_class = G_OBJECT_CLASS(c);
|
gobject_class = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_current_playlist_set_property;
|
gobject_class->set_property = koto_current_playlist_set_property;
|
||||||
gobject_class->get_property = koto_current_playlist_get_property;
|
gobject_class->get_property = koto_current_playlist_get_property;
|
||||||
|
@ -49,18 +64,24 @@ static void koto_current_playlist_class_init(KotoCurrentPlaylistClass *c) {
|
||||||
"Current Playlist",
|
"Current Playlist",
|
||||||
"Current Playlist",
|
"Current Playlist",
|
||||||
KOTO_TYPE_PLAYLIST,
|
KOTO_TYPE_PLAYLIST,
|
||||||
G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_current_playlist_init(KotoCurrentPlaylist *self) {
|
static void koto_current_playlist_init(KotoCurrentPlaylist * self) {
|
||||||
self->current_playlist = NULL;
|
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(
|
||||||
KotoCurrentPlaylist *self = KOTO_CURRENT_PLAYLIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoCurrentPlaylist * self = KOTO_CURRENT_PLAYLIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_CURRENT_PLAYLIST:
|
case PROP_CURRENT_PLAYLIST:
|
||||||
|
@ -72,8 +93,14 @@ 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(
|
||||||
KotoCurrentPlaylist *self = KOTO_CURRENT_PLAYLIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoCurrentPlaylist * self = KOTO_CURRENT_PLAYLIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_CURRENT_PLAYLIST:
|
case PROP_CURRENT_PLAYLIST:
|
||||||
|
@ -85,11 +112,14 @@ void koto_current_playlist_set_property(GObject *obj, guint prop_id, const GValu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist* koto_current_playlist_get_playlist(KotoCurrentPlaylist *self) {
|
KotoPlaylist * koto_current_playlist_get_playlist(KotoCurrentPlaylist * self) {
|
||||||
return self->current_playlist;
|
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)) {
|
if (!KOTO_IS_CURRENT_PLAYLIST(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +129,7 @@ void koto_current_playlist_set_playlist(KotoCurrentPlaylist *self, KotoPlaylist
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->current_playlist != NULL && KOTO_IS_PLAYLIST(self->current_playlist)) {
|
if (self->current_playlist != NULL && KOTO_IS_PLAYLIST(self->current_playlist)) {
|
||||||
gboolean *is_temp = FALSE;
|
gboolean * is_temp = FALSE;
|
||||||
g_object_get(self->current_playlist, "ephemeral", &is_temp, NULL); // Get the current ephemeral value
|
g_object_get(self->current_playlist, "ephemeral", &is_temp, NULL); // Get the current ephemeral value
|
||||||
|
|
||||||
if (is_temp) { // Is a temporary playlist
|
if (is_temp) { // Is a temporary playlist
|
||||||
|
@ -118,6 +148,6 @@ void koto_current_playlist_set_playlist(KotoCurrentPlaylist *self, KotoPlaylist
|
||||||
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_CURRENT_PLAYLIST]);
|
g_object_notify_by_pspec(G_OBJECT(self), props[PROP_CURRENT_PLAYLIST]);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoCurrentPlaylist* koto_current_playlist_new() {
|
KotoCurrentPlaylist * koto_current_playlist_new() {
|
||||||
return g_object_new(KOTO_TYPE_CURRENT_PLAYLIST, NULL);
|
return g_object_new(KOTO_TYPE_CURRENT_PLAYLIST, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_CURRENT_PLAYLIST koto_current_playlist_get_type()
|
#define KOTO_TYPE_CURRENT_PLAYLIST koto_current_playlist_get_type()
|
||||||
G_DECLARE_FINAL_TYPE(KotoCurrentPlaylist, koto_current_playlist, KOTO, CURRENT_PLAYLIST, GObject);
|
G_DECLARE_FINAL_TYPE(KotoCurrentPlaylist, koto_current_playlist, KOTO, CURRENT_PLAYLIST, GObject);
|
||||||
|
@ -31,10 +31,15 @@ G_DECLARE_FINAL_TYPE(KotoCurrentPlaylist, koto_current_playlist, KOTO, CURRENT_P
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current Playlist Functions
|
* Current Playlist Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoCurrentPlaylist* koto_current_playlist_new();
|
KotoCurrentPlaylist * koto_current_playlist_new();
|
||||||
KotoPlaylist* koto_current_playlist_get_playlist(KotoCurrentPlaylist *self);
|
|
||||||
void koto_current_playlist_set_playlist(KotoCurrentPlaylist *self, KotoPlaylist *playlist);
|
KotoPlaylist * koto_current_playlist_get_playlist(KotoCurrentPlaylist * self);
|
||||||
|
|
||||||
|
void koto_current_playlist_set_playlist(
|
||||||
|
KotoCurrentPlaylist * self,
|
||||||
|
KotoPlaylist * playlist
|
||||||
|
);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#include "../koto-utils.h"
|
#include "../koto-utils.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
|
||||||
extern KotoCartographer *koto_maps;
|
extern KotoCartographer * koto_maps;
|
||||||
extern sqlite3 *koto_db;
|
extern sqlite3 * koto_db;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
@ -46,11 +46,11 @@ enum {
|
||||||
|
|
||||||
struct _KotoPlaylist {
|
struct _KotoPlaylist {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
gchar *uuid;
|
gchar * uuid;
|
||||||
gchar *name;
|
gchar * name;
|
||||||
gchar *art_path;
|
gchar * art_path;
|
||||||
gint current_position;
|
gint current_position;
|
||||||
gchar *current_uuid;
|
gchar * current_uuid;
|
||||||
|
|
||||||
KotoPreferredModelType model;
|
KotoPreferredModelType model;
|
||||||
|
|
||||||
|
@ -58,32 +58,56 @@ struct _KotoPlaylist {
|
||||||
gboolean is_shuffle_enabled;
|
gboolean is_shuffle_enabled;
|
||||||
gboolean finalized;
|
gboolean finalized;
|
||||||
|
|
||||||
GListStore *store;
|
GListStore * store;
|
||||||
GQueue *sorted_tracks;
|
GQueue * sorted_tracks;
|
||||||
|
|
||||||
GQueue *tracks; // This is effectively our vanilla value that should never change
|
GQueue * tracks; // This is effectively our vanilla value that should never change
|
||||||
GQueue *played_tracks;
|
GQueue * played_tracks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _KotoPlaylistClass {
|
struct _KotoPlaylistClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (* modified) (KotoPlaylist *playlist);
|
void (* modified) (KotoPlaylist * playlist);
|
||||||
void (* track_added) (KotoPlaylist *playlist, gchar *track_uuid);
|
void (* track_added) (
|
||||||
void (* track_load_finalized) (KotoPlaylist *playlist);
|
KotoPlaylist * playlist,
|
||||||
void (* track_removed) (KotoPlaylist *playlist, gchar *track_uuid);
|
gchar * track_uuid
|
||||||
|
);
|
||||||
|
void (* track_load_finalized) (KotoPlaylist * playlist);
|
||||||
|
void (* track_removed) (
|
||||||
|
KotoPlaylist * playlist,
|
||||||
|
gchar * track_uuid
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE(KotoPlaylist, koto_playlist, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(KotoPlaylist, koto_playlist, G_TYPE_OBJECT);
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPERTIES] = { NULL };
|
static GParamSpec * props[N_PROPERTIES] = {
|
||||||
static guint playlist_signals[N_SIGNALS] = { 0 };
|
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_class_init(KotoPlaylistClass * c) {
|
||||||
|
GObjectClass * gobject_class;
|
||||||
|
|
||||||
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 = G_OBJECT_CLASS(c);
|
||||||
gobject_class->set_property = koto_playlist_set_property;
|
gobject_class->set_property = koto_playlist_set_property;
|
||||||
gobject_class->get_property = koto_playlist_get_property;
|
gobject_class->get_property = koto_playlist_get_property;
|
||||||
|
@ -93,7 +117,7 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
||||||
"UUID of the Playlist",
|
"UUID of the Playlist",
|
||||||
"UUID of the Playlist",
|
"UUID of the Playlist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_NAME] = g_param_spec_string(
|
props[PROP_NAME] = g_param_spec_string(
|
||||||
|
@ -101,7 +125,7 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
||||||
"Name of the Playlist",
|
"Name of the Playlist",
|
||||||
"Name of the Playlist",
|
"Name of the Playlist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_ART_PATH] = g_param_spec_string(
|
props[PROP_ART_PATH] = g_param_spec_string(
|
||||||
|
@ -109,7 +133,7 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
||||||
"Path to any associated artwork of the Playlist",
|
"Path to any associated artwork of the Playlist",
|
||||||
"Path to any associated artwork of the Playlist",
|
"Path to any associated artwork of the Playlist",
|
||||||
NULL,
|
NULL,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_EPHEMERAL] = g_param_spec_boolean(
|
props[PROP_EPHEMERAL] = g_param_spec_boolean(
|
||||||
|
@ -117,7 +141,7 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
||||||
"Is the playlist ephemeral (temporary)",
|
"Is the playlist ephemeral (temporary)",
|
||||||
"Is the playlist ephemeral (temporary)",
|
"Is the playlist ephemeral (temporary)",
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
props[PROP_IS_SHUFFLE_ENABLED] = g_param_spec_boolean(
|
props[PROP_IS_SHUFFLE_ENABLED] = g_param_spec_boolean(
|
||||||
|
@ -125,7 +149,7 @@ static void koto_playlist_class_init(KotoPlaylistClass *c) {
|
||||||
"Is shuffling enabled",
|
"Is shuffling enabled",
|
||||||
"Is shuffling enabled",
|
"Is shuffling enabled",
|
||||||
FALSE,
|
FALSE,
|
||||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||||
|
@ -181,8 +205,14 @@ 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(
|
||||||
KotoPlaylist *self = KOTO_PLAYLIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPlaylist * self = KOTO_PLAYLIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -206,8 +236,14 @@ 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(
|
||||||
KotoPlaylist *self = KOTO_PLAYLIST(obj);
|
GObject * obj,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue * val,
|
||||||
|
GParamSpec * spec
|
||||||
|
) {
|
||||||
|
KotoPlaylist * self = KOTO_PLAYLIST(obj);
|
||||||
|
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_UUID:
|
case PROP_UUID:
|
||||||
|
@ -231,7 +267,7 @@ static void koto_playlist_set_property(GObject *obj, guint prop_id, const GValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void koto_playlist_init(KotoPlaylist *self) {
|
static void koto_playlist_init(KotoPlaylist * self) {
|
||||||
self->current_position = -1; // Default to -1 so first time incrementing puts it at 0
|
self->current_position = -1; // Default to -1 so first time incrementing puts it at 0
|
||||||
self->current_uuid = NULL;
|
self->current_uuid = NULL;
|
||||||
self->model = KOTO_PREFERRED_MODEL_TYPE_DEFAULT; // Default to default model
|
self->model = KOTO_PREFERRED_MODEL_TYPE_DEFAULT; // Default to default model
|
||||||
|
@ -245,7 +281,10 @@ static void koto_playlist_init(KotoPlaylist *self) {
|
||||||
self->store = g_list_store_new(KOTO_TYPE_INDEXED_TRACK);
|
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
|
if (g_queue_index(self->played_tracks, uuid) != -1) { // Already added
|
||||||
return;
|
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
|
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);
|
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(
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, uuid); // Get the track
|
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)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GList *found_tracks_uuids = g_queue_find_custom(self->tracks, uuid, koto_playlist_compare_track_uuids);
|
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
|
if (found_tracks_uuids != NULL) { // Is somewhere in the tracks already
|
||||||
g_list_free(found_tracks_uuids);
|
g_list_free(found_tracks_uuids);
|
||||||
return;
|
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(
|
||||||
GList *sort_user_data = NULL;
|
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, GUINT_TO_POINTER(preferred_model)); // Prepend our preferred model first
|
||||||
sort_user_data = g_list_prepend(sort_user_data, self); // Prepend ourself
|
sort_user_data = g_list_prepend(sort_user_data, self); // Prepend ourself
|
||||||
|
|
||||||
|
@ -307,16 +364,16 @@ void koto_playlist_apply_model(KotoPlaylist *self, KotoPreferredModelType prefer
|
||||||
self->model = preferred_model; // Update our preferred model
|
self->model = preferred_model; // Update our preferred model
|
||||||
|
|
||||||
/*if (self->current_position != -1) { // Have a position set
|
/*if (self->current_position != -1) { // Have a position set
|
||||||
koto_playlist_set_track_as_current(self, self->current_uuid); // Update the position based on the new model just by setting it as current again
|
koto_playlist_set_track_as_current(self, self->current_uuid); // Update the position based on the new model just by setting it as current again
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_commit(KotoPlaylist *self) {
|
void koto_playlist_commit(KotoPlaylist * self) {
|
||||||
if (self->ephemeral) { // Temporary playlist
|
if (self->ephemeral) { // Temporary playlist
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar *commit_op = g_strdup_printf(
|
gchar * commit_op = g_strdup_printf(
|
||||||
"INSERT INTO playlist_meta(id, name, art_path, preferred_model)"
|
"INSERT INTO playlist_meta(id, name, art_path, preferred_model)"
|
||||||
"VALUES('%s', quote(\"%s\"), quote(\"%s\"), 0)"
|
"VALUES('%s', quote(\"%s\"), quote(\"%s\"), 0)"
|
||||||
"ON CONFLICT(id) DO UPDATE SET name=excluded.name, art_path=excluded.art_path;",
|
"ON CONFLICT(id) DO UPDATE SET name=excluded.name, art_path=excluded.art_path;",
|
||||||
|
@ -325,9 +382,10 @@ void koto_playlist_commit(KotoPlaylist *self) {
|
||||||
self->art_path
|
self->art_path
|
||||||
);
|
);
|
||||||
|
|
||||||
gchar *commit_op_errmsg = NULL;
|
gchar * commit_op_errmsg = NULL;
|
||||||
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
int rc = sqlite3_exec(koto_db, commit_op, 0, 0, &commit_op_errmsg);
|
||||||
|
|
||||||
|
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_warning("Failed to save playlist: %s", commit_op_errmsg);
|
g_warning("Failed to save playlist: %s", commit_op_errmsg);
|
||||||
} else { // Successfully saved our playlist
|
} else { // Successfully saved our playlist
|
||||||
|
@ -338,49 +396,59 @@ void koto_playlist_commit(KotoPlaylist *self) {
|
||||||
g_free(commit_op_errmsg);
|
g_free(commit_op_errmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_commit_tracks(gpointer data, gpointer user_data) {
|
void koto_playlist_commit_tracks(
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, data); // Get the track
|
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
|
if (track == NULL) { // Not a track
|
||||||
KotoPlaylist *self = user_data;
|
KotoPlaylist * self = user_data;
|
||||||
gchar *playlist_uuid = self->uuid; // Get the playlist UUID
|
gchar * playlist_uuid = self->uuid; // Get the playlist UUID
|
||||||
|
|
||||||
gchar *current_track = g_queue_peek_nth(self->tracks, self->current_position); // Get the UUID of the current track
|
gchar * current_track = g_queue_peek_nth(self->tracks, self->current_position); // Get the UUID of the current track
|
||||||
//koto_indexed_track_save_to_playlist(track, playlist_uuid, (data == current_track) ? 1 : 0); // Call to save the playlist to the track
|
//koto_indexed_track_save_to_playlist(track, playlist_uuid, (data == current_track) ? 1 : 0); // Call to save the playlist to the track
|
||||||
g_free(playlist_uuid);
|
g_free(playlist_uuid);
|
||||||
g_free(current_track);
|
g_free(current_track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
return g_strcmp0(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_get_artwork(KotoPlaylist *self) {
|
gchar * koto_playlist_get_artwork(KotoPlaylist * self) {
|
||||||
return (self->art_path == NULL) ? NULL : g_strdup(self->art_path); // Return a duplicate of our art path
|
return (self->art_path == NULL) ? NULL : g_strdup(self->art_path); // Return a duplicate of our art path
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPreferredModelType koto_playlist_get_current_model(KotoPlaylist *self) {
|
KotoPreferredModelType koto_playlist_get_current_model(KotoPlaylist * self) {
|
||||||
return self->model;
|
return self->model;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint koto_playlist_get_current_position(KotoPlaylist *self) {
|
guint koto_playlist_get_current_position(KotoPlaylist * self) {
|
||||||
return self->current_position;
|
return self->current_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean koto_playlist_get_is_finalized(KotoPlaylist *self) {
|
gboolean koto_playlist_get_is_finalized(KotoPlaylist * self) {
|
||||||
return self->finalized;
|
return self->finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint koto_playlist_get_length(KotoPlaylist *self) {
|
guint koto_playlist_get_length(KotoPlaylist * self) {
|
||||||
return g_queue_get_length(self->tracks); // Get the length of the tracks
|
return g_queue_get_length(self->tracks); // Get the length of the tracks
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_get_name(KotoPlaylist *self) {
|
gchar * koto_playlist_get_name(KotoPlaylist * self) {
|
||||||
return (self->name == NULL) ? NULL : g_strdup(self->name);
|
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)) {
|
if (!KOTO_IS_PLAYLIST(self)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -396,17 +464,19 @@ gint koto_playlist_get_position_of_track(KotoPlaylist *self, KotoIndexedTrack *t
|
||||||
gint position = -1;
|
gint position = -1;
|
||||||
guint found_pos = 0;
|
guint found_pos = 0;
|
||||||
|
|
||||||
if (g_list_store_find(self->store , track, &found_pos)) { // Found the item
|
|
||||||
|
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
|
position = (gint) found_pos; // Cast our found position from guint to gint
|
||||||
}
|
}
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_get_random_track(KotoPlaylist *self) {
|
gchar * koto_playlist_get_random_track(KotoPlaylist * self) {
|
||||||
gchar *track_uuid = NULL;
|
gchar * track_uuid = NULL;
|
||||||
guint tracks_len = g_queue_get_length(self->sorted_tracks);
|
guint tracks_len = g_queue_get_length(self->sorted_tracks);
|
||||||
|
|
||||||
|
|
||||||
if (tracks_len == g_queue_get_length(self->played_tracks)) { // Played all 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
|
track_uuid = g_list_nth_data(self->sorted_tracks->head, 0); // Get the first
|
||||||
g_queue_clear(self->played_tracks); // Clear our played tracks
|
g_queue_clear(self->played_tracks); // Clear our played tracks
|
||||||
|
@ -414,10 +484,10 @@ gchar* koto_playlist_get_random_track(KotoPlaylist *self) {
|
||||||
GRand* rando_calrissian = g_rand_new(); // Create a new RNG
|
GRand* rando_calrissian = g_rand_new(); // Create a new RNG
|
||||||
guint attempt = 0;
|
guint attempt = 0;
|
||||||
|
|
||||||
while (track_uuid == NULL) { // Haven't selected a track yet
|
while (track_uuid == NULL) { // Haven't selected a track yet
|
||||||
attempt++;
|
attempt++;
|
||||||
gint32 selected_item = g_rand_int_range(rando_calrissian, 0, (gint32) tracks_len);
|
gint32 selected_item = g_rand_int_range(rando_calrissian, 0, (gint32) tracks_len);
|
||||||
gchar *selected_track = g_queue_peek_nth(self->sorted_tracks, (guint) selected_item); // Get the UUID of the selected item
|
gchar * selected_track = g_queue_peek_nth(self->sorted_tracks, (guint) selected_item); // Get the UUID of the selected item
|
||||||
|
|
||||||
if (g_queue_index(self->played_tracks, selected_track) == -1) { // Haven't played the track
|
if (g_queue_index(self->played_tracks, selected_track) == -1) { // Haven't played the track
|
||||||
self->current_position = (gint) selected_item;
|
self->current_position = (gint) selected_item;
|
||||||
|
@ -436,25 +506,25 @@ gchar* koto_playlist_get_random_track(KotoPlaylist *self) {
|
||||||
return track_uuid;
|
return track_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
GListStore* koto_playlist_get_store(KotoPlaylist *self) {
|
GListStore * koto_playlist_get_store(KotoPlaylist * self) {
|
||||||
return self->store;
|
return self->store;
|
||||||
}
|
}
|
||||||
|
|
||||||
GQueue* koto_playlist_get_tracks(KotoPlaylist *self) {
|
GQueue * koto_playlist_get_tracks(KotoPlaylist * self) {
|
||||||
return self->tracks;
|
return self->tracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_get_uuid(KotoPlaylist *self) {
|
gchar * koto_playlist_get_uuid(KotoPlaylist * self) {
|
||||||
return g_strdup(self->uuid);
|
return g_strdup(self->uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_go_to_next(KotoPlaylist *self) {
|
gchar * koto_playlist_go_to_next(KotoPlaylist * self) {
|
||||||
if (!KOTO_IS_PLAYLIST(self)) {
|
if (!KOTO_IS_PLAYLIST(self)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->is_shuffle_enabled) { // Shuffling enabled
|
if (self->is_shuffle_enabled) { // Shuffling enabled
|
||||||
gchar *random_track_uuid = koto_playlist_get_random_track(self); // Get a random track
|
gchar * random_track_uuid = koto_playlist_get_random_track(self); // Get a random track
|
||||||
koto_playlist_add_to_played_tracks(self, random_track_uuid);
|
koto_playlist_add_to_played_tracks(self, random_track_uuid);
|
||||||
return random_track_uuid;
|
return random_track_uuid;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +532,7 @@ gchar* koto_playlist_go_to_next(KotoPlaylist *self) {
|
||||||
if (!koto_utils_is_string_valid(self->current_uuid)) { // No valid UUID yet
|
if (!koto_utils_is_string_valid(self->current_uuid)) { // No valid UUID yet
|
||||||
self->current_position++;
|
self->current_position++;
|
||||||
} else { // Have a UUID currently
|
} else { // Have a UUID currently
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, self->current_uuid);
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, self->current_uuid);
|
||||||
|
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -474,7 +544,7 @@ gchar* koto_playlist_go_to_next(KotoPlaylist *self) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->current_position = pos_of_song+1; // Increment our position based on position of song
|
self->current_position = pos_of_song + 1; // Increment our position based on position of song
|
||||||
}
|
}
|
||||||
|
|
||||||
self->current_uuid = g_queue_peek_nth(self->sorted_tracks, self->current_position);
|
self->current_uuid = g_queue_peek_nth(self->sorted_tracks, self->current_position);
|
||||||
|
@ -483,7 +553,7 @@ gchar* koto_playlist_go_to_next(KotoPlaylist *self) {
|
||||||
return self->current_uuid;
|
return self->current_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* koto_playlist_go_to_previous(KotoPlaylist *self) {
|
gchar * koto_playlist_go_to_previous(KotoPlaylist * self) {
|
||||||
if (self->is_shuffle_enabled) { // Shuffling enabled
|
if (self->is_shuffle_enabled) { // Shuffling enabled
|
||||||
return koto_playlist_get_random_track(self); // Get a random track
|
return koto_playlist_get_random_track(self); // Get a random track
|
||||||
}
|
}
|
||||||
|
@ -492,7 +562,8 @@ gchar* koto_playlist_go_to_previous(KotoPlaylist *self) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, self->current_uuid);
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, self->current_uuid);
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
if (!KOTO_IS_INDEXED_TRACK(track)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -500,6 +571,7 @@ gchar* koto_playlist_go_to_previous(KotoPlaylist *self) {
|
||||||
|
|
||||||
gint pos_of_song = koto_playlist_get_position_of_track(self, track); // Get the position of the current track based on the current model
|
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) {
|
if (pos_of_song == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -510,14 +582,14 @@ gchar* koto_playlist_go_to_previous(KotoPlaylist *self) {
|
||||||
return self->current_uuid;
|
return self->current_uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_mark_as_finalized(KotoPlaylist *self) {
|
void koto_playlist_mark_as_finalized(KotoPlaylist * self) {
|
||||||
if (self->finalized) { // Already finalized
|
if (self->finalized) { // Already finalized
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->finalized = TRUE;
|
self->finalized = TRUE;
|
||||||
koto_playlist_apply_model(self, self->model); // Re-apply our model to enforce mass sort
|
koto_playlist_apply_model(self, self->model); // Re-apply our model to enforce mass sort
|
||||||
|
|
||||||
g_signal_emit(
|
g_signal_emit(
|
||||||
self,
|
self,
|
||||||
playlist_signals[SIGNAL_TRACK_LOAD_FINALIZED],
|
playlist_signals[SIGNAL_TRACK_LOAD_FINALIZED],
|
||||||
|
@ -525,24 +597,34 @@ 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(
|
||||||
KotoIndexedTrack *first_track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) first_item);
|
gconstpointer first_item,
|
||||||
KotoIndexedTrack *second_track = koto_cartographer_get_track_by_uuid(koto_maps, (gchar*) second_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);
|
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(
|
||||||
KotoIndexedTrack *first_track = (KotoIndexedTrack*) first_item;
|
gconstpointer first_item,
|
||||||
KotoIndexedTrack *second_track = (KotoIndexedTrack*) second_item;
|
gconstpointer second_item,
|
||||||
|
gpointer data_list
|
||||||
|
) {
|
||||||
|
KotoIndexedTrack * first_track = (KotoIndexedTrack*) first_item;
|
||||||
|
KotoIndexedTrack * second_track = (KotoIndexedTrack*) second_item;
|
||||||
|
|
||||||
GList* ptr_list = data_list;
|
GList* ptr_list = data_list;
|
||||||
KotoPlaylist *self = g_list_nth_data(ptr_list, 0); // First item in the GPtrArray is a pointer to our playlist
|
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
|
KotoPreferredModelType model = GPOINTER_TO_UINT(g_list_nth_data(ptr_list, 1)); // Second item in the GPtrArray is a pointer to our KotoPreferredModelType
|
||||||
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(model == KOTO_PREFERRED_MODEL_TYPE_DEFAULT) || // Newest first model
|
(model == KOTO_PREFERRED_MODEL_TYPE_DEFAULT) || // Newest first model
|
||||||
(model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) // Oldest first
|
(model == KOTO_PREFERRED_MODEL_TYPE_OLDEST_FIRST) // Oldest first
|
||||||
) {
|
) {
|
||||||
gint first_track_pos = g_queue_index(self->tracks, koto_indexed_track_get_uuid(first_track));
|
gint first_track_pos = g_queue_index(self->tracks, koto_indexed_track_get_uuid(first_track));
|
||||||
gint second_track_pos = g_queue_index(self->tracks, koto_indexed_track_get_uuid(second_track));
|
gint second_track_pos = g_queue_index(self->tracks, koto_indexed_track_get_uuid(second_track));
|
||||||
|
@ -563,8 +645,8 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM) { // Sort by album name
|
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ALBUM) { // Sort by album name
|
||||||
gchar *first_album_uuid = NULL;
|
gchar * first_album_uuid = NULL;
|
||||||
gchar *second_album_uuid = NULL;
|
gchar * second_album_uuid = NULL;
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
first_track,
|
first_track,
|
||||||
|
@ -586,8 +668,8 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
return 0; // Don't get too granular, just consider them equal
|
return 0; // Don't get too granular, just consider them equal
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoIndexedAlbum *first_album = koto_cartographer_get_album_by_uuid(koto_maps, first_album_uuid);
|
KotoIndexedAlbum * first_album = koto_cartographer_get_album_by_uuid(koto_maps, first_album_uuid);
|
||||||
KotoIndexedAlbum *second_album = koto_cartographer_get_album_by_uuid(koto_maps, second_album_uuid);
|
KotoIndexedAlbum * second_album = koto_cartographer_get_album_by_uuid(koto_maps, second_album_uuid);
|
||||||
|
|
||||||
g_free(first_album_uuid);
|
g_free(first_album_uuid);
|
||||||
g_free(second_album_uuid);
|
g_free(second_album_uuid);
|
||||||
|
@ -600,8 +682,8 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST) { // Sort by artist name
|
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_ARTIST) { // Sort by artist name
|
||||||
gchar *first_artist_uuid = NULL;
|
gchar * first_artist_uuid = NULL;
|
||||||
gchar *second_artist_uuid = NULL;
|
gchar * second_artist_uuid = NULL;
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
first_track,
|
first_track,
|
||||||
|
@ -617,8 +699,8 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
KotoIndexedArtist *first_artist = koto_cartographer_get_artist_by_uuid(koto_maps, first_artist_uuid);
|
KotoIndexedArtist * first_artist = koto_cartographer_get_artist_by_uuid(koto_maps, first_artist_uuid);
|
||||||
KotoIndexedArtist *second_artist = koto_cartographer_get_artist_by_uuid(koto_maps, second_artist_uuid);
|
KotoIndexedArtist * second_artist = koto_cartographer_get_artist_by_uuid(koto_maps, second_artist_uuid);
|
||||||
|
|
||||||
g_free(first_artist_uuid);
|
g_free(first_artist_uuid);
|
||||||
g_free(second_artist_uuid);
|
g_free(second_artist_uuid);
|
||||||
|
@ -631,8 +713,8 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME) { // Track name
|
if (model == KOTO_PREFERRED_MODEL_TYPE_SORT_BY_TRACK_NAME) { // Track name
|
||||||
gchar *first_track_name = NULL;
|
gchar * first_track_name = NULL;
|
||||||
gchar *second_track_name = NULL;
|
gchar * second_track_name = NULL;
|
||||||
|
|
||||||
g_object_get(
|
g_object_get(
|
||||||
first_track,
|
first_track,
|
||||||
|
@ -658,28 +740,37 @@ gint koto_playlist_model_sort_by_track(gconstpointer first_item, gconstpointer s
|
||||||
return 0;
|
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);
|
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)) {
|
if (!KOTO_IS_PLAYLIST(self)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gint file_index = g_queue_index(self->tracks, uuid); // Get the position of this uuid
|
gint file_index = g_queue_index(self->tracks, uuid); // Get the position of this uuid
|
||||||
|
|
||||||
|
|
||||||
if (file_index != -1) { // Have in tracks
|
if (file_index != -1) { // Have in tracks
|
||||||
g_queue_pop_nth(self->tracks, file_index); // Remove nth where it is the file index
|
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
|
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
|
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
|
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
|
KotoIndexedTrack * track = koto_cartographer_get_track_by_uuid(koto_maps, uuid); // Get the track
|
||||||
|
|
||||||
|
|
||||||
if (!KOTO_IS_INDEXED_TRACK(track)) { // Is not a track
|
if (!KOTO_IS_INDEXED_TRACK(track)) { // Is not a track
|
||||||
return;
|
return;
|
||||||
|
@ -687,6 +778,7 @@ void koto_playlist_remove_track_by_uuid(KotoPlaylist *self, gchar *uuid) {
|
||||||
|
|
||||||
guint position = 0;
|
guint position = 0;
|
||||||
|
|
||||||
|
|
||||||
if (g_list_store_find(self->store, track, &position)) { // Got the position
|
if (g_list_store_find(self->store, track, &position)) { // Got the position
|
||||||
g_list_store_remove(self->store, position); // Remove from the store
|
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) {
|
if (path == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
magic_t cookie = magic_open(MAGIC_MIME); // Create our magic cookie so we can validate if what we are setting is an image
|
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
|
if (cookie == NULL) { // Failed to allocate
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -716,7 +812,8 @@ void koto_playlist_set_artwork(KotoPlaylist *self, const gchar *path) {
|
||||||
goto free_cookie;
|
goto free_cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gchar *mime_type = magic_file(cookie, path); // Get the mimetype for this file
|
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
|
if ((mime_type == NULL) || !g_str_has_prefix(mime_type, "image/")) { // Failed to get our mimetype or not an image
|
||||||
goto free_cookie;
|
goto free_cookie;
|
||||||
|
@ -737,10 +834,13 @@ void koto_playlist_set_artwork(KotoPlaylist *self, const gchar *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free_cookie:
|
free_cookie:
|
||||||
magic_close(cookie); // Close and free the cookie to the cookie monster
|
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) {
|
if (name == NULL) {
|
||||||
return;
|
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;
|
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
|
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
|
if (position_of_track != -1) { // In tracks
|
||||||
self->current_position = position_of_track;
|
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
|
if (uuid == NULL) { // No actual UUID
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -784,9 +894,13 @@ void koto_playlist_set_uuid(KotoPlaylist *self, const gchar *uuid) {
|
||||||
self->uuid = g_strdup(uuid); // Set the new 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(
|
||||||
gchar *track_uuid = (gchar *) data;
|
gpointer data,
|
||||||
KotoIndexedTrack *track = koto_cartographer_get_track_by_uuid(koto_maps, track_uuid);
|
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
|
if (!KOTO_IS_INDEXED_TRACK(track)) { // Not a track
|
||||||
return;
|
return;
|
||||||
|
@ -795,20 +909,24 @@ void koto_playlist_tracks_queue_push_to_store(gpointer data, gpointer user_data)
|
||||||
g_list_store_append(G_LIST_STORE(user_data), track);
|
g_list_store_append(G_LIST_STORE(user_data), track);
|
||||||
}
|
}
|
||||||
|
|
||||||
void koto_playlist_unmap(KotoPlaylist *self) {
|
void koto_playlist_unmap(KotoPlaylist * self) {
|
||||||
koto_cartographer_remove_playlist_by_uuid(koto_maps, self->uuid); // Remove from our cartographer
|
koto_cartographer_remove_playlist_by_uuid(koto_maps, self->uuid); // Remove from our cartographer
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist* koto_playlist_new() {
|
KotoPlaylist * koto_playlist_new() {
|
||||||
return g_object_new(KOTO_TYPE_PLAYLIST,
|
return g_object_new(
|
||||||
"uuid", g_uuid_string_random(),
|
KOTO_TYPE_PLAYLIST,
|
||||||
|
"uuid",
|
||||||
|
g_uuid_string_random(),
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
KotoPlaylist* koto_playlist_new_with_uuid(const gchar *uuid) {
|
KotoPlaylist * koto_playlist_new_with_uuid(const gchar * uuid) {
|
||||||
return g_object_new(KOTO_TYPE_PLAYLIST,
|
return g_object_new(
|
||||||
"uuid", uuid,
|
KOTO_TYPE_PLAYLIST,
|
||||||
|
"uuid",
|
||||||
|
uuid,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ typedef enum {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type Definition
|
* Type Definition
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#define KOTO_TYPE_PLAYLIST koto_playlist_get_type()
|
#define KOTO_TYPE_PLAYLIST koto_playlist_get_type()
|
||||||
#define KOTO_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), KOTO_TYPE_PLAYLIST, KotoPlaylist))
|
#define KOTO_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), KOTO_TYPE_PLAYLIST, KotoPlaylist))
|
||||||
#define KOTO_IS_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYLIST))
|
#define KOTO_IS_PLAYLIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), KOTO_TYPE_PLAYLIST))
|
||||||
|
|
||||||
typedef struct _KotoPlaylist KotoPlaylist;
|
typedef struct _KotoPlaylist KotoPlaylist;
|
||||||
|
@ -46,41 +46,131 @@ GType koto_playlist_get_type(void) G_GNUC_CONST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playlist Functions
|
* Playlist Functions
|
||||||
**/
|
**/
|
||||||
|
|
||||||
KotoPlaylist* koto_playlist_new();
|
KotoPlaylist * koto_playlist_new();
|
||||||
KotoPlaylist* koto_playlist_new_with_uuid(const gchar *uuid);
|
|
||||||
void koto_playlist_add_to_played_tracks(KotoPlaylist *self, gchar *uuid);
|
KotoPlaylist * koto_playlist_new_with_uuid(const 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_add_to_played_tracks(
|
||||||
void koto_playlist_apply_model(KotoPlaylist *self, KotoPreferredModelType preferred_model);
|
KotoPlaylist * self,
|
||||||
void koto_playlist_commit(KotoPlaylist *self);
|
gchar * uuid
|
||||||
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);
|
void koto_playlist_add_track(
|
||||||
KotoPreferredModelType koto_playlist_get_current_model(KotoPlaylist *self);
|
KotoPlaylist * self,
|
||||||
guint koto_playlist_get_current_position(KotoPlaylist *self);
|
KotoIndexedTrack * track,
|
||||||
guint koto_playlist_get_length(KotoPlaylist *self);
|
gboolean current,
|
||||||
gboolean koto_playlist_get_is_finalized(KotoPlaylist *self);
|
gboolean commit_to_table
|
||||||
gchar* koto_playlist_get_name(KotoPlaylist *self);
|
);
|
||||||
gint koto_playlist_get_position_of_track(KotoPlaylist *self, KotoIndexedTrack *track);
|
|
||||||
GListStore* koto_playlist_get_store(KotoPlaylist *self);
|
void koto_playlist_add_track_by_uuid(
|
||||||
GQueue* koto_playlist_get_tracks(KotoPlaylist *self);
|
KotoPlaylist * self,
|
||||||
gchar* koto_playlist_get_uuid(KotoPlaylist *self);
|
gchar * uuid,
|
||||||
gchar* koto_playlist_go_to_next(KotoPlaylist *self);
|
gboolean current,
|
||||||
gchar* koto_playlist_go_to_previous(KotoPlaylist *self);
|
gboolean commit_to_table
|
||||||
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_apply_model(
|
||||||
void koto_playlist_remove_from_played_tracks(KotoPlaylist *self, gchar *uuid);
|
KotoPlaylist * self,
|
||||||
void koto_playlist_remove_track_by_uuid(KotoPlaylist *self, gchar *uuid);
|
KotoPreferredModelType preferred_model
|
||||||
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_commit(KotoPlaylist * self);
|
||||||
void koto_playlist_set_position(KotoPlaylist *self, gint position);
|
|
||||||
void koto_playlist_set_track_as_current(KotoPlaylist *self, gchar *track_uuid);
|
void koto_playlist_commit_tracks(
|
||||||
void koto_playlist_set_uuid(KotoPlaylist *self, const gchar *uuid);
|
gpointer data,
|
||||||
void koto_playlist_tracks_queue_push_to_store(gpointer data, gpointer user_data);
|
gpointer user_data
|
||||||
void koto_playlist_unmap(KotoPlaylist *self);
|
);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
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_unmap(KotoPlaylist * self);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue