propertify more things

This commit is contained in:
Erica Z 2024-10-15 22:29:14 +02:00
parent c9b67977e0
commit db0fee7d92
2 changed files with 66 additions and 62 deletions

View file

@ -29,10 +29,8 @@ class Playbin : Object {
private bool update_position = false; private bool update_position = false;
public int64 position { get; private set; } public int64 position { get; private set; }
public int64 duration { get; private set; }
public Subsonic api { get; set; } public Subsonic api { get; set; }
private ListModel play_queue;
public signal void now_playing (uint index, Song song, int64 duration); public signal void now_playing (uint index, Song song, int64 duration);
private uint playing_index; private uint playing_index;
@ -43,9 +41,58 @@ class Playbin : Object {
source.user_agent = "audrey/linux"; source.user_agent = "audrey/linux";
} }
public Playbin (ListModel play_queue) { private void on_play_queue_items_changed (ListModel play_queue, uint position, uint removed, uint added) {
this.play_queue = play_queue; if (this.state == PlaybinState.STOPPED) {
return;
}
if (this.playing_index >= position) {
if (this.playing_index < position+removed) {
// current track was removed, start playing something else
// TODO check if it was actually reordered
this.begin_playback (position);
} else {
// unaffected
// fix up playing index though
this.playing_index += added;
this.playing_index -= removed;
}
} else if (this.playing_index+1 == position) {
// next track was changed
// try to fix up gapless transition
string? next_uri = this.next_uri.try_pop ();
if (next_uri != null) {
// we're in luck, about-to-finish hasn't been triggered yet
// we can get away with replacing it
if (this.playing_index+1 < play_queue.get_n_items ()) {
Song song = (Song) play_queue.get_item (this.playing_index+1);
this.next_uri.push (this.api.stream_uri (song.id));
} else {
this.next_uri.push ("");
}
} else {
// about-to-finish already triggered
// we'll need to stop the new track when it starts playing
assert (false); // TODO
}
}
}
private ListModel _play_queue = null;
private ulong _play_queue_items_changed;
public ListModel play_queue {
get { return _play_queue; }
set {
if (_play_queue != null) {
SignalHandler.disconnect (_play_queue, _play_queue_items_changed);
}
_play_queue = value;
_play_queue_items_changed = value.items_changed.connect (on_play_queue_items_changed);
}
}
public Playbin () {
this.next_uri = new AsyncQueue<string> (); this.next_uri = new AsyncQueue<string> ();
this.next_uri.push (""); this.next_uri.push ("");
@ -58,50 +105,12 @@ class Playbin : Object {
this.playbin.source_setup.connect (this.source_setup); this.playbin.source_setup.connect (this.source_setup);
this.playbin.about_to_finish.connect (this.about_to_finish); this.playbin.about_to_finish.connect (this.about_to_finish);
play_queue.items_changed.connect ((play_queue, position, removed, added) => { // regularly update position
if (this.state == PlaybinState.STOPPED) {
return;
}
if (this.playing_index >= position) {
if (this.playing_index < position+removed) {
// current track was removed, start playing something else
// TODO check if it was actually reordered
this.begin_playback (position);
} else {
// unaffected
// fix up playing index though
this.playing_index += added;
this.playing_index -= removed;
}
} else if (this.playing_index+1 == position) {
// next track was changed
// try to fix up gapless transition
string? next_uri = this.next_uri.try_pop ();
if (next_uri != null) {
// we're in luck, about-to-finish hasn't been triggered yet
// we can get away with replacing it
if (this.playing_index+1 < play_queue.get_n_items ()) {
Song song = (Song) play_queue.get_item (this.playing_index+1);
this.next_uri.push (this.api.stream_uri (song.id));
} else {
this.next_uri.push ("");
}
} else {
// about-to-finish already triggered
// we'll need to stop the new track when it starts playing
assert (false); // TODO
}
}
});
// regularly update position/duration
Timeout.add (500, () => { Timeout.add (500, () => {
if (this.update_position) { if (this.update_position) {
int64 new_position; int64 new_position;
if (this.playbin.query_position (Gst.Format.TIME, out new_position)) { if (this.playbin.query_position (Gst.Format.TIME, out new_position)) {
this.position = new_position < this.duration ? new_position : this.duration; this.position = new_position;
} else { } else {
this.position = 0; this.position = 0;
} }
@ -129,12 +138,8 @@ class Playbin : Object {
}); });
bus.message["stream-start"].connect ((message) => { bus.message["stream-start"].connect ((message) => {
int64 new_duration; int64 duration;
if (this.playbin.query_duration (Gst.Format.TIME, out new_duration)) { assert (this.playbin.query_duration (Gst.Format.TIME, out duration));
this.duration = new_duration;
} else {
warning ("could not obtain new stream duration");
}
this.position = 0; this.position = 0;
@ -145,7 +150,13 @@ class Playbin : Object {
this.next_gapless = true; this.next_gapless = true;
} }
this.now_playing (this.playing_index, (Song) play_queue.get_item (this.playing_index), this.duration); var now_playing = (Song) play_queue.get_item (this.playing_index);
if (this.api.stream_uri (now_playing.id) != (string) this.playbin.current_uri) {
// edge case
assert (false); // TODO
}
this.now_playing (this.playing_index, now_playing, duration);
if (this.playing_index+1 < play_queue.get_n_items ()) { if (this.playing_index+1 < play_queue.get_n_items ()) {
Song song = (Song) play_queue.get_item (this.playing_index+1); Song song = (Song) play_queue.get_item (this.playing_index+1);

View file

@ -27,9 +27,7 @@ class Ui.Window : Adw.ApplicationWindow {
public bool cover_art_loading { get; set; default = false; } public bool cover_art_loading { get; set; default = false; }
public Gdk.Paintable playing_cover_art { get; set; } public Gdk.Paintable playing_cover_art { get; set; }
private Gdk.Paintable next_cover_art = null; internal Playbin playbin = new Playbin ();
internal Playbin playbin;
public PlayQueueSelection play_queue_model { get; private set; default = new PlayQueueSelection (); } public PlayQueueSelection play_queue_model { get; private set; default = new PlayQueueSelection (); }
public Window (Gtk.Application app) { public Window (Gtk.Application app) {
@ -39,11 +37,6 @@ class Ui.Window : Adw.ApplicationWindow {
provider.load_from_resource("/eu/callcc/audrey/audrey.css"); provider.load_from_resource("/eu/callcc/audrey/audrey.css");
Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
this.close_request.connect (() => {
app.quit ();
return false;
});
} }
construct { construct {
@ -61,9 +54,9 @@ class Ui.Window : Adw.ApplicationWindow {
() => {}, () => {},
() => { error ("could not acquire dbus name"); }); () => { error ("could not acquire dbus name"); });
this.setup = new Setup (); this.playbin.play_queue = this.play_queue_model;
this.playbin = new Playbin (this.play_queue_model); this.setup = new Setup ();
this.setup.connected.connect ((api) => { this.setup.connected.connect ((api) => {
this.playbin.api = api; this.playbin.api = api;
@ -218,7 +211,7 @@ class Ui.Window : Adw.ApplicationWindow {
[GtkCallback] private void seek_forward () { [GtkCallback] private void seek_forward () {
// 10 seconds // 10 seconds
int64 new_position = position + (int64)10 * 1000 * 1000000; int64 new_position = position + (int64)10 * 1000 * 1000000;
if (new_position > this.playbin.duration) new_position = this.playbin.duration; if (new_position > this.duration) new_position = this.duration;
this.seek_impl (new_position); this.seek_impl (new_position);
} }
} }