2024-10-12 20:52:29 +00:00
|
|
|
[GtkTemplate (ui = "/eu/callcc/audrey/play_queue.ui")]
|
|
|
|
public class PlayQueue : Adw.NavigationPage {
|
2024-10-12 13:12:51 +00:00
|
|
|
public ListStore songs { get; private set; }
|
2024-10-12 12:57:37 +00:00
|
|
|
|
2024-10-12 16:35:42 +00:00
|
|
|
public uint selected_index { get; set; }
|
2024-10-12 12:57:37 +00:00
|
|
|
// this is the index of the song that will play on next on_stream_start
|
|
|
|
private uint next_stream_index;
|
2024-10-10 09:53:52 +00:00
|
|
|
|
2024-10-12 13:36:47 +00:00
|
|
|
public signal void play_next (Song? song);
|
2024-10-10 20:04:55 +00:00
|
|
|
public signal void play_now (Song song);
|
2024-10-12 13:36:47 +00:00
|
|
|
|
2024-10-12 12:28:05 +00:00
|
|
|
public signal void now_playing (Song song);
|
2024-10-10 20:04:55 +00:00
|
|
|
|
2024-10-12 16:35:42 +00:00
|
|
|
private bool ignore_selection = false;
|
|
|
|
|
|
|
|
[GtkChild] private unowned Gtk.SingleSelection selection;
|
|
|
|
|
|
|
|
public bool can_clear_all { get; private set; default = false; }
|
|
|
|
|
2024-10-10 09:53:52 +00:00
|
|
|
construct {
|
|
|
|
this.songs = new ListStore (typeof (Song));
|
2024-10-12 12:57:37 +00:00
|
|
|
this.next_stream_index = 0;
|
2024-10-10 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
2024-10-12 16:35:42 +00:00
|
|
|
[GtkCallback] public void clear () {
|
2024-10-10 09:53:52 +00:00
|
|
|
this.songs.remove_all ();
|
2024-10-12 16:35:42 +00:00
|
|
|
this.can_clear_all = false;
|
2024-10-10 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void queue (Song song) {
|
2024-10-12 12:57:37 +00:00
|
|
|
uint new_index = this.songs.get_n_items ();
|
2024-10-10 09:53:52 +00:00
|
|
|
this.songs.append (song);
|
2024-10-12 12:57:37 +00:00
|
|
|
if (new_index == next_stream_index) {
|
|
|
|
this.play_next (song);
|
|
|
|
}
|
2024-10-12 16:35:42 +00:00
|
|
|
this.can_clear_all = true;
|
2024-10-10 09:53:52 +00:00
|
|
|
}
|
2024-10-11 06:57:01 +00:00
|
|
|
|
2024-10-12 16:35:42 +00:00
|
|
|
[GtkCallback] private void on_song_selected () {
|
|
|
|
this.selected_index = this.selection.selected; // manual bidi binding
|
|
|
|
if (this.ignore_selection) return;
|
|
|
|
this.pick_song (this.selected_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void pick_song (uint index) {
|
|
|
|
Song? song = (Song?) this.songs.get_item (index);
|
|
|
|
if (song != null) {
|
|
|
|
this.ignore_selection = true;
|
|
|
|
this.selected_index = index;
|
|
|
|
this.ignore_selection = false;
|
|
|
|
|
|
|
|
this.next_stream_index = index;
|
|
|
|
this.play_next (song);
|
|
|
|
this.play_now (song);
|
|
|
|
}
|
2024-10-11 08:22:05 +00:00
|
|
|
}
|
2024-10-12 12:28:05 +00:00
|
|
|
|
|
|
|
internal void on_stream_start (Playbin playbin) {
|
2024-10-12 12:57:37 +00:00
|
|
|
Song song = (Song) this.songs.get_item (this.next_stream_index);
|
2024-10-12 12:28:05 +00:00
|
|
|
this.now_playing (song);
|
|
|
|
|
2024-10-12 16:35:42 +00:00
|
|
|
this.ignore_selection = true;
|
|
|
|
this.selected_index = this.next_stream_index;
|
|
|
|
this.ignore_selection = false;
|
|
|
|
|
2024-10-12 12:57:37 +00:00
|
|
|
// prepare for next song ahead of time (gapless)
|
|
|
|
this.next_stream_index += 1;
|
|
|
|
Song? next_song = (Song?) this.songs.get_item (this.next_stream_index);
|
2024-10-12 12:28:05 +00:00
|
|
|
this.play_next (next_song);
|
|
|
|
}
|
2024-10-12 12:57:37 +00:00
|
|
|
|
|
|
|
internal void restart () {
|
2024-10-12 16:35:42 +00:00
|
|
|
this.pick_song (0);
|
2024-10-12 12:57:37 +00:00
|
|
|
}
|
2024-10-12 13:36:47 +00:00
|
|
|
|
|
|
|
public void skip_forward () {
|
2024-10-12 16:35:42 +00:00
|
|
|
this.pick_song (this.selected_index + 1);
|
2024-10-12 13:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void skip_backward () {
|
2024-10-12 16:35:42 +00:00
|
|
|
if (this.selected_index >= 1) {
|
|
|
|
this.pick_song (this.selected_index - 1);
|
2024-10-12 13:36:47 +00:00
|
|
|
}
|
2024-10-12 16:35:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
[GtkCallback] private void delete_cell_setup (Object object) {
|
|
|
|
Gtk.ColumnViewCell cell = (Gtk.ColumnViewCell) object;
|
|
|
|
Gtk.Button button = new Gtk.Button.from_icon_name ("edit-delete");
|
|
|
|
button.add_css_class ("flat");
|
|
|
|
cell.child = button;
|
|
|
|
button.clicked.connect (() => {
|
|
|
|
this.songs.remove (cell.position);
|
|
|
|
this.can_clear_all = this.songs.get_n_items() > 0;
|
|
|
|
});
|
2024-10-12 13:36:47 +00:00
|
|
|
}
|
2024-10-10 09:53:52 +00:00
|
|
|
}
|