diff --git a/src/api.vala b/src/api.vala index 698a77b..fb61c7b 100644 --- a/src/api.vala +++ b/src/api.vala @@ -19,7 +19,7 @@ */ errordomain SubsonicError { - FAILED + ERROR } public class Wavelet.Artist : Object, Json.Serializable { @@ -107,6 +107,45 @@ public class Wavelet.Song : Object { } } +public struct Wavelet.API.PlayQueue { + public string current; + public int64 position; + public DateTime changed; + public string changed_by; + public ListStore songs; + + internal PlayQueue.from_reader (Json.Reader reader) { + reader.read_member ("current"); + this.current = reader.get_string_value (); + reader.end_member (); + + reader.read_member ("position"); + this.position = reader.get_int_value (); + reader.end_member (); + + reader.read_member ("changed"); + this.changed = new DateTime.from_iso8601 (reader.get_string_value (), null); + reader.end_member (); + + reader.read_member ("changed_by"); + this.changed_by = reader.get_string_value (); + reader.end_member (); + + print("%s %lli %s %s\n",this.current, this.position, this.changed, this.changed_by); + + this.songs = new ListStore (typeof (Song)); + + reader.read_member ("song"); + for (int i = 0; i < reader.count_elements (); i += 1) { + reader.read_element (i); + this.songs.append (new Song (reader)); + reader.end_element (); + } + reader.end_member (); + assert (reader.get_error () == null); + } +} + public class Wavelet.Subsonic : Object { public ListStore artist_list; public ListStore album_list; @@ -146,7 +185,7 @@ public class Wavelet.Subsonic : Object { reader.end_member (); reader.read_member ("error"); reader.read_member ("message"); - throw new SubsonicError.FAILED (reader.get_string_value () ?? "???"); + throw new SubsonicError.ERROR (reader.get_string_value () ?? "???"); } reader.end_member(); } diff --git a/src/meson.build b/src/meson.build index 52b7294..f0cc18b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -3,6 +3,7 @@ wavelet_sources = [ 'application.vala', 'artist_list.vala', 'main.vala', + 'play_queue.vala', 'setup.vala', 'song_list.vala', 'window.vala', diff --git a/src/play_queue.ui b/src/play_queue.ui new file mode 100644 index 0000000..4218c20 --- /dev/null +++ b/src/play_queue.ui @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/play_queue.vala b/src/play_queue.vala new file mode 100644 index 0000000..cae0185 --- /dev/null +++ b/src/play_queue.vala @@ -0,0 +1,41 @@ +/* play_queue.vala + * + * Copyright 2024 Erica Z + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +[GtkTemplate (ui = "/eu/callcc/Wavelet/play_queue.ui")] +public class Wavelet.PlayQueue : Adw.NavigationPage { + [GtkChild] private unowned Gtk.ListView list_view; + + private ListStore songs; + private uint current; + + construct { + this.songs = new ListStore (typeof (Song)); + this.list_view.model = new Gtk.NoSelection (this.songs); + } + + public void clear () { + this.songs.remove_all (); + this.current = 0; + } + + public void queue (Song song) { + this.songs.append (song); + } +} diff --git a/src/play_queue_song.ui b/src/play_queue_song.ui new file mode 100644 index 0000000..2d7d76a --- /dev/null +++ b/src/play_queue_song.ui @@ -0,0 +1,17 @@ + + + + + + diff --git a/src/wavelet.gresource.xml b/src/wavelet.gresource.xml index c60b3f8..5a6d48f 100644 --- a/src/wavelet.gresource.xml +++ b/src/wavelet.gresource.xml @@ -4,6 +4,8 @@ artist_list.ui artist_list_artist.ui gtk/help-overlay.ui + play_queue.ui + play_queue_song.ui setup.ui song_list.ui song_list_song.ui diff --git a/src/window.ui b/src/window.ui index 3981608..6f29edf 100644 --- a/src/window.ui +++ b/src/window.ui @@ -8,9 +8,11 @@ 800 600 - + + vertical + true 100 @@ -18,13 +20,57 @@ - - - - - stack + + + + vertical + + + + + + + + 0 + Setup + + + + + + + + + 0 + Play queue + + + + + + + + + + + + + none + + + + Shuffle all tracks + media-playlist-shuffle + + + + + + + + @@ -58,6 +104,15 @@ + + + play_queue + Play queue + + + + + diff --git a/src/window.vala b/src/window.vala index db374b4..e7a2501 100644 --- a/src/window.vala +++ b/src/window.vala @@ -20,11 +20,29 @@ [GtkTemplate (ui = "/eu/callcc/Wavelet/window.ui")] public class Wavelet.Window : Adw.ApplicationWindow { + [GtkChild] private unowned Gtk.ListBox sidebar; + [GtkChild] private unowned Gtk.ListBoxRow sidebar_setup; + [GtkChild] private unowned Gtk.ListBoxRow sidebar_play_queue; + [GtkChild] private unowned Gtk.Stack stack; + [GtkChild] public unowned Wavelet.Setup setup; [GtkChild] public unowned Wavelet.ArtistList artist_list; [GtkChild] public unowned Wavelet.SongList song_list; + [GtkChild] public unowned Wavelet.PlayQueue play_queue; public Window (Gtk.Application app) { Object (application: app); } + + construct { + this.sidebar.row_activated.connect ((row) => { + if (row == this.sidebar_setup) { + this.stack.set_visible_child_name("setup"); + } else if (row == this.sidebar_play_queue) { + this.stack.set_visible_child_name("play_queue"); + } + }); + + this.sidebar.select_row (this.sidebar.get_row_at_index (0)); + } }