Port to GTK4, start implementation of Local Music view, Artist and Album Views.
This commit is contained in:
parent
8948a8ec9f
commit
588a68b2cc
28 changed files with 1103 additions and 270 deletions
169
src/pages/music/album-view.c
Normal file
169
src/pages/music/album-view.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* album-view.c
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <glib-2.0/glib.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/album.h"
|
||||
#include "../../indexer/artist.h"
|
||||
#include "../../koto-track-item.h"
|
||||
#include "album-view.h"
|
||||
#include "koto-config.h"
|
||||
#include "koto-utils.h"
|
||||
|
||||
struct _KotoAlbumView {
|
||||
GObject parent_instance;
|
||||
KotoIndexedAlbum *album;
|
||||
GtkWidget *main;
|
||||
GtkWidget *album_tracks_box;
|
||||
GtkWidget *tracks;
|
||||
|
||||
GtkWidget *album_label;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoAlbumView, koto_album_view, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ALBUM,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_album_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
|
||||
static void koto_album_view_class_init(KotoAlbumViewClass *c) {
|
||||
GObjectClass *gobject_class;
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->set_property = koto_album_view_set_property;
|
||||
gobject_class->get_property = koto_album_view_get_property;
|
||||
|
||||
props[PROP_ALBUM] = g_param_spec_object(
|
||||
"album",
|
||||
"Album",
|
||||
"Album",
|
||||
KOTO_TYPE_INDEXED_ALBUM,
|
||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
||||
);
|
||||
|
||||
g_object_class_install_properties(gobject_class, N_PROPERTIES, props);
|
||||
}
|
||||
|
||||
static void koto_album_view_init(KotoAlbumView *self) {
|
||||
self->main = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_set_can_focus(self->main, FALSE);
|
||||
self->album_tracks_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
|
||||
self->tracks = gtk_list_box_new(); // Create our list of our tracks
|
||||
gtk_list_box_set_sort_func(GTK_LIST_BOX(self->tracks), koto_album_view_sort_tracks, NULL, NULL); // Ensure we can sort our tracks
|
||||
gtk_widget_set_size_request(self->tracks, 600, -1);
|
||||
|
||||
gtk_box_append(GTK_BOX(self->main), self->album_tracks_box); // Add the tracks box to the art info combo box
|
||||
gtk_box_append(GTK_BOX(self->album_tracks_box), self->tracks); // Add the tracks list box to the albums tracks box
|
||||
}
|
||||
|
||||
GtkWidget* koto_album_view_get_main(KotoAlbumView *self) {
|
||||
return self->main;
|
||||
}
|
||||
|
||||
static void koto_album_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) {
|
||||
KotoAlbumView *self = KOTO_ALBUM_VIEW(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ALBUM:
|
||||
g_value_set_object(val, self->album);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koto_album_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
KotoAlbumView *self = KOTO_ALBUM_VIEW(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ALBUM:
|
||||
koto_album_view_set_album(self, (KotoIndexedAlbum*) g_value_get_object(val));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album) {
|
||||
if (album == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->album = album;
|
||||
|
||||
gchar *album_art = koto_indexed_album_get_album_art(self->album); // Get the art for the album
|
||||
GtkWidget *art_image = koto_utils_create_image_from_filepath(album_art, "audio-x-generic-symbolic", 220, 220);
|
||||
|
||||
gtk_box_prepend(GTK_BOX(self->main), art_image); // Prepend the image to the art info box
|
||||
|
||||
gchar *album_name;
|
||||
g_object_get(album, "name", &album_name, NULL); // Get the album name
|
||||
|
||||
self->album_label = gtk_label_new(album_name);
|
||||
gtk_box_prepend(GTK_BOX(self->album_tracks_box), self->album_label); // Prepend our new label to the album + tracks box
|
||||
|
||||
GList *t;
|
||||
for (t = koto_indexed_album_get_files(self->album); t != NULL; t = t->next) { // For each file / track
|
||||
KotoIndexedFile *file = (KotoIndexedFile*) t->data;
|
||||
KotoTrackItem *track_item = koto_track_item_new(file); // Create our new track item
|
||||
gtk_list_box_prepend(GTK_LIST_BOX(self->tracks), GTK_WIDGET(track_item)); // Add to our tracks list box
|
||||
}
|
||||
}
|
||||
|
||||
int koto_album_view_sort_tracks(GtkListBoxRow *track1, GtkListBoxRow *track2, gpointer user_data) {
|
||||
(void) user_data;
|
||||
KotoTrackItem *track1_item = KOTO_TRACK_ITEM(gtk_list_box_row_get_child(track1));
|
||||
KotoTrackItem *track2_item = KOTO_TRACK_ITEM(gtk_list_box_row_get_child(track2));
|
||||
|
||||
KotoIndexedFile *track1_file;
|
||||
KotoIndexedFile *track2_file;
|
||||
|
||||
g_object_get(track1_item, "track", &track1_file, NULL);
|
||||
g_object_get(track2_item, "track", &track2_file, NULL);
|
||||
|
||||
guint16 *track1_pos;
|
||||
guint16 *track2_pos;
|
||||
|
||||
g_object_get(track1_file, "position", &track1_pos, NULL);
|
||||
g_object_get(track2_file, "position", &track2_pos, NULL);
|
||||
|
||||
if (track1_pos == track2_pos) { // Identical positions (like reported as 0)
|
||||
gchar *track1_name;
|
||||
gchar *track2_name;
|
||||
|
||||
g_object_get(track1_file, "parsed-name", &track1_name, NULL);
|
||||
g_object_get(track2_file, "parsed-name", &track2_name, NULL);
|
||||
|
||||
return g_utf8_collate(track1_name, track2_name);
|
||||
} else if (track1_pos < track2_pos) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum *album) {
|
||||
return g_object_new(KOTO_TYPE_ALBUM_VIEW, "album", album, NULL);
|
||||
}
|
36
src/pages/music/album-view.h
Normal file
36
src/pages/music/album-view.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* album-view.h
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-2.0/glib-object.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/album.h"
|
||||
#include "../../indexer/artist.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define KOTO_TYPE_ALBUM_VIEW (koto_album_view_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE(KotoAlbumView, koto_album_view, KOTO, ALBUM_VIEW, GObject)
|
||||
|
||||
KotoAlbumView* koto_album_view_new(KotoIndexedAlbum *album);
|
||||
GtkWidget* koto_album_view_get_main(KotoAlbumView *self);
|
||||
void koto_album_view_set_album(KotoAlbumView *self, KotoIndexedAlbum *album);
|
||||
int koto_album_view_sort_tracks(GtkListBoxRow *track1, GtkListBoxRow *track2, gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
167
src/pages/music/artist-view.c
Normal file
167
src/pages/music/artist-view.c
Normal file
|
@ -0,0 +1,167 @@
|
|||
/* artist-view.c
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <glib-2.0/glib.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/album.h"
|
||||
#include "../../indexer/artist.h"
|
||||
#include "album-view.h"
|
||||
#include "artist-view.h"
|
||||
#include "koto-config.h"
|
||||
#include "koto-utils.h"
|
||||
|
||||
struct _KotoArtistView {
|
||||
GObject parent_instance;
|
||||
KotoIndexedArtist *artist;
|
||||
GtkWidget *scrolled_window;
|
||||
GtkWidget *content;
|
||||
GtkWidget *albums_strip;
|
||||
GtkWidget *album_list;
|
||||
|
||||
GHashTable *albums_to_component;
|
||||
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoArtistView, koto_artist_view, G_TYPE_OBJECT);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ARTIST,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
static void koto_artist_view_constructed(GObject *obj);
|
||||
static void koto_artist_view_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec);
|
||||
static void koto_artist_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec);
|
||||
|
||||
static void koto_artist_view_class_init(KotoArtistViewClass *c) {
|
||||
GObjectClass *gobject_class;
|
||||
gobject_class = G_OBJECT_CLASS(c);
|
||||
gobject_class->constructed = koto_artist_view_constructed;
|
||||
gobject_class->set_property = koto_artist_view_set_property;
|
||||
gobject_class->get_property = koto_artist_view_get_property;
|
||||
|
||||
props[PROP_ARTIST] = g_param_spec_object(
|
||||
"artist",
|
||||
"Artist",
|
||||
"Artist",
|
||||
KOTO_TYPE_INDEXED_ARTIST,
|
||||
G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
||||
);
|
||||
|
||||
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) {
|
||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST:
|
||||
g_value_set_object(val, self->artist);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koto_artist_view_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ARTIST:
|
||||
koto_artist_view_add_artist(self, (KotoIndexedArtist*) g_value_get_object(val));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koto_artist_view_init(KotoArtistView *self) {
|
||||
self->artist = NULL;
|
||||
self->constructed = FALSE;
|
||||
}
|
||||
|
||||
static void koto_artist_view_constructed(GObject *obj) {
|
||||
KotoArtistView *self = KOTO_ARTIST_VIEW(obj);
|
||||
self->albums_to_component = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
self->scrolled_window = gtk_scrolled_window_new(); // Create our scrolled window
|
||||
self->content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); // Create our content as a GtkBox
|
||||
|
||||
gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(self->scrolled_window), TRUE);
|
||||
gtk_scrolled_window_set_propagate_natural_width(GTK_SCROLLED_WINDOW(self->scrolled_window), TRUE);
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->scrolled_window), self->content); // Add the content as the widget for the scrolled window
|
||||
|
||||
self->albums_strip = gtk_flow_box_new(); // Create our album strip
|
||||
gtk_flow_box_set_activate_on_single_click(GTK_FLOW_BOX(self->albums_strip), TRUE);
|
||||
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(self->albums_strip), GTK_SELECTION_NONE);
|
||||
|
||||
self->album_list = gtk_flow_box_new(); // Create our list of albums as a flow box
|
||||
gtk_flow_box_set_activate_on_single_click(GTK_FLOW_BOX(self->album_list), FALSE);
|
||||
gtk_flow_box_set_selection_mode(GTK_FLOW_BOX(self->album_list), GTK_SELECTION_NONE);
|
||||
|
||||
gtk_box_prepend(GTK_BOX(self->content), self->albums_strip); // Add the strip
|
||||
gtk_box_append(GTK_BOX(self->content), self->album_list); // Add the list
|
||||
|
||||
gtk_widget_set_hexpand(GTK_WIDGET(self->albums_strip), TRUE);
|
||||
gtk_widget_set_hexpand(GTK_WIDGET(self->album_list), TRUE);
|
||||
|
||||
G_OBJECT_CLASS (koto_artist_view_parent_class)->constructed (obj);
|
||||
self->constructed = TRUE;
|
||||
}
|
||||
|
||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album) {
|
||||
gchar *album_art = koto_indexed_album_get_album_art(album); // Get the art for the album
|
||||
|
||||
GtkWidget *art_image = koto_utils_create_image_from_filepath(album_art, "audio-x-generic-symbolic", 220, 220);
|
||||
gtk_flow_box_insert(GTK_FLOW_BOX(self->albums_strip), art_image, -1); // Append the album art
|
||||
|
||||
KotoAlbumView* album_view = koto_album_view_new(album); // Create our new album view
|
||||
GtkWidget* album_view_main = koto_album_view_get_main(album_view);
|
||||
gtk_flow_box_insert(GTK_FLOW_BOX(self->album_list), album_view_main, -1); // Append the album view to the album list
|
||||
}
|
||||
|
||||
void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist) {
|
||||
if (artist == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
self->artist = artist;
|
||||
|
||||
if (!self->constructed) {
|
||||
return;
|
||||
}
|
||||
|
||||
GList *albums = koto_indexed_artist_get_albums(self->artist); // Get the albums
|
||||
|
||||
GList *a;
|
||||
for (a = albums; a != NULL; a = a->next) {
|
||||
KotoIndexedAlbum *album = (KotoIndexedAlbum*) a->data;
|
||||
koto_artist_view_add_album(self, album); // Add the album
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget* koto_artist_view_get_main(KotoArtistView *self) {
|
||||
return self->scrolled_window;
|
||||
}
|
||||
|
||||
KotoArtistView* koto_artist_view_new() {
|
||||
return g_object_new(KOTO_TYPE_ARTIST_VIEW, NULL);
|
||||
}
|
36
src/pages/music/artist-view.h
Normal file
36
src/pages/music/artist-view.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* artist-view.h
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-2.0/glib-object.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/album.h"
|
||||
#include "../../indexer/artist.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define KOTO_TYPE_ARTIST_VIEW (koto_artist_view_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (KotoArtistView, koto_artist_view, KOTO, ARTIST_VIEW, GObject)
|
||||
|
||||
KotoArtistView* koto_artist_view_new();
|
||||
void koto_artist_view_add_album(KotoArtistView *self, KotoIndexedAlbum *album);
|
||||
void koto_artist_view_add_artist(KotoArtistView *self, KotoIndexedArtist *artist);
|
||||
GtkWidget* koto_artist_view_get_main(KotoArtistView *self);
|
||||
|
||||
G_END_DECLS
|
227
src/pages/music/music-local.c
Normal file
227
src/pages/music/music-local.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
/* music-local.c
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <glib-2.0/glib.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/file-indexer.h"
|
||||
#include "koto-button.h"
|
||||
#include "koto-config.h"
|
||||
#include "music-local.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_LIB,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static GParamSpec *props[N_PROPERTIES] = { NULL, };
|
||||
|
||||
struct _KotoPageMusicLocal {
|
||||
GtkBox parent_instance;
|
||||
GtkWidget *scrolled_window;
|
||||
GtkWidget *artist_list;
|
||||
GtkWidget *stack;
|
||||
|
||||
KotoIndexedLibrary *lib;
|
||||
gboolean constructed;
|
||||
};
|
||||
|
||||
struct _KotoPageMusicLocalClass {
|
||||
GtkBoxClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE(KotoPageMusicLocal, koto_page_music_local, GTK_TYPE_BOX);
|
||||
|
||||
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->constructed = koto_page_music_local_constructed;
|
||||
gobject_class->set_property = koto_page_music_local_set_property;
|
||||
gobject_class->get_property = koto_page_music_local_get_property;
|
||||
|
||||
props[PROP_LIB] = g_param_spec_object(
|
||||
"lib",
|
||||
"Library",
|
||||
"Library",
|
||||
KOTO_TYPE_INDEXED_LIBRARY,
|
||||
G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE
|
||||
);
|
||||
|
||||
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) {
|
||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LIB:
|
||||
g_value_set_object(val, self->lib);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koto_page_music_local_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) {
|
||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_LIB:
|
||||
koto_page_music_local_set_library(self, (KotoIndexedLibrary*) g_value_get_object(val));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void koto_page_music_local_init(KotoPageMusicLocal *self) {
|
||||
self->lib = NULL;
|
||||
self->constructed = FALSE;
|
||||
}
|
||||
|
||||
static void koto_page_music_local_constructed(GObject *obj) {
|
||||
KotoPageMusicLocal *self = KOTO_PAGE_MUSIC_LOCAL(obj);
|
||||
gtk_widget_add_css_class(GTK_WIDGET(self), "page-music-local");
|
||||
gtk_widget_set_hexpand(GTK_WIDGET(self), TRUE);
|
||||
|
||||
G_OBJECT_CLASS (koto_page_music_local_parent_class)->constructed (obj);
|
||||
self->constructed = TRUE;
|
||||
}
|
||||
|
||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist) {
|
||||
gchar *artist_name;
|
||||
g_object_get(artist, "name", &artist_name, NULL);
|
||||
KotoButton *artist_button = koto_button_new_plain(artist_name);
|
||||
gtk_list_box_prepend(GTK_LIST_BOX(self->artist_list), GTK_WIDGET(artist_button));
|
||||
|
||||
KotoArtistView *artist_view = koto_artist_view_new(); // Create our new artist view
|
||||
koto_artist_view_add_artist(artist_view, artist); // Add the artist
|
||||
gtk_stack_add_named(GTK_STACK(self->stack), koto_artist_view_get_main(artist_view), artist_name);
|
||||
|
||||
GtkGesture *controller = gtk_gesture_click_new(); // Create a new GtkGestureClick
|
||||
g_signal_connect(controller, "pressed", G_CALLBACK(koto_page_music_local_handle_artist_click), self);
|
||||
gtk_widget_add_controller(GTK_WIDGET(artist_button), GTK_EVENT_CONTROLLER(controller));
|
||||
}
|
||||
|
||||
void koto_page_music_local_handle_artist_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data) {
|
||||
(void) n_press; (void) x; (void) y;
|
||||
KotoPageMusicLocal *self = (KotoPageMusicLocal*) data;
|
||||
GtkWidget *btn_widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); // Get the widget that applied to this gesture
|
||||
KotoButton *btn = KOTO_BUTTON(btn_widget);
|
||||
|
||||
gchar *artist_name;
|
||||
g_object_get(btn, "button-text", &artist_name, NULL);
|
||||
gtk_stack_set_visible_child_name(GTK_STACK(self->stack), artist_name);
|
||||
}
|
||||
|
||||
void koto_page_music_local_set_library(KotoPageMusicLocal *self, KotoIndexedLibrary *lib) {
|
||||
if (lib == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->lib != NULL) { // If lib is already set
|
||||
g_free(self->lib);
|
||||
}
|
||||
|
||||
self->lib = lib;
|
||||
|
||||
if (!self->constructed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GTK_IS_SCROLLED_WINDOW(self->scrolled_window)) {
|
||||
self->scrolled_window = gtk_scrolled_window_new();
|
||||
gtk_widget_add_css_class(self->scrolled_window, "artist-list");
|
||||
gtk_box_prepend(GTK_BOX(self), self->scrolled_window);
|
||||
}
|
||||
|
||||
if (GTK_IS_LIST_BOX(self->artist_list)) { // artist list is a list box
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->scrolled_window), NULL); // Set to null to maybe clear?
|
||||
g_object_unref(self->artist_list); // Unref
|
||||
}
|
||||
|
||||
if (GTK_IS_STACK(self->stack)) { // Stack is a Stack
|
||||
gtk_box_remove(GTK_BOX(self), GTK_WIDGET(self->stack)); // Destroy to free references
|
||||
}
|
||||
|
||||
self->artist_list = gtk_list_box_new(); // Create our artist list
|
||||
|
||||
gboolean list_created = GTK_IS_LIST_BOX(self->artist_list);
|
||||
|
||||
if (list_created) { // Successfully created our list
|
||||
gtk_list_box_set_activate_on_single_click(GTK_LIST_BOX(self->artist_list), TRUE);
|
||||
gtk_list_box_set_selection_mode(GTK_LIST_BOX(self->artist_list), GTK_SELECTION_BROWSE);
|
||||
gtk_list_box_set_sort_func(GTK_LIST_BOX(self->artist_list), koto_page_music_local_sort_artists, NULL, NULL); // Add our sort function
|
||||
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(self->scrolled_window), self->artist_list);
|
||||
gtk_widget_show(GTK_WIDGET(self->artist_list));
|
||||
}
|
||||
|
||||
gtk_scrolled_window_set_min_content_width(GTK_SCROLLED_WINDOW(self->scrolled_window), 300);
|
||||
gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(self->scrolled_window), FALSE);
|
||||
gtk_widget_set_size_request(GTK_WIDGET(self->artist_list), 300, -1);
|
||||
|
||||
self->stack = gtk_stack_new(); // Create a new stack
|
||||
gtk_widget_set_hexpand(self->stack, TRUE);
|
||||
gboolean stack_created = GTK_IS_STACK(self->stack);
|
||||
|
||||
if (list_created && stack_created) {
|
||||
GHashTableIter artist_list_iter;
|
||||
gpointer artist_key;
|
||||
gpointer artist_data;
|
||||
|
||||
GHashTable *artists = koto_indexed_library_get_artists(self->lib); // Get the artists
|
||||
|
||||
g_hash_table_iter_init(&artist_list_iter, artists);
|
||||
while (g_hash_table_iter_next(&artist_list_iter, &artist_key, &artist_data)) { // For each of the music artists
|
||||
KotoIndexedArtist *artist = (KotoIndexedArtist*) artist_data; // Cast our data as a KotoIndexedArtist
|
||||
koto_page_music_local_add_artist(self, artist);
|
||||
}
|
||||
}
|
||||
|
||||
if (stack_created) { // Successfully created our stack
|
||||
gtk_box_append(GTK_BOX(self), self->stack);
|
||||
}
|
||||
|
||||
gtk_widget_show(GTK_WIDGET(self));
|
||||
}
|
||||
|
||||
int koto_page_music_local_sort_artists(GtkListBoxRow *artist1, GtkListBoxRow *artist2, gpointer user_data) {
|
||||
(void) user_data;
|
||||
KotoButton *artist1_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist1));
|
||||
KotoButton *artist2_btn = KOTO_BUTTON(gtk_list_box_row_get_child(artist2));
|
||||
|
||||
gchar *artist1_text;
|
||||
gchar *artist2_text;
|
||||
|
||||
g_object_get(artist1_btn, "button-text", &artist1_text, NULL);
|
||||
g_object_get(artist2_btn, "button-text", &artist2_text, NULL);
|
||||
|
||||
return g_utf8_collate(artist1_text, artist2_text);
|
||||
}
|
||||
|
||||
KotoPageMusicLocal* koto_page_music_local_new() {
|
||||
return g_object_new(KOTO_TYPE_PAGE_MUSIC_LOCAL,
|
||||
"orientation", GTK_ORIENTATION_HORIZONTAL,
|
||||
NULL
|
||||
);
|
||||
}
|
38
src/pages/music/music-local.h
Normal file
38
src/pages/music/music-local.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* music-local.h
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-2.0/glib-object.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include "../../indexer/artist.h"
|
||||
#include "../../indexer/file-indexer.h"
|
||||
#include "artist-view.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#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)
|
||||
|
||||
KotoPageMusicLocal* koto_page_music_local_new();
|
||||
void koto_page_music_local_add_artist(KotoPageMusicLocal *self, KotoIndexedArtist *artist);
|
||||
void koto_page_music_local_handle_artist_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data);
|
||||
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
|
Loading…
Add table
Add a link
Reference in a new issue