playbin refactor

This commit is contained in:
Erica Z 2024-10-13 09:56:28 +00:00
parent 4256778e95
commit 629bc782fc
2 changed files with 72 additions and 66 deletions

View file

@ -16,17 +16,17 @@ class Playbin : Object {
}
public bool mute {
get { return playbin.mute; }
set { playbin.mute = value; }
get { return this.playbin.mute; }
set { this.playbin.mute = value; }
}
public signal void set_position (int64 position);
public int64 position { get; private set; }
public int64 duration { get; private set; }
public signal void stream_started ();
public signal void stream_over ();
private void on_source_setup (Gst.Element playbin, dynamic Gst.Element source) {
private void source_setup (Gst.Element playbin, dynamic Gst.Element source) {
source.user_agent = "audrey/linux";
}
@ -34,79 +34,85 @@ class Playbin : Object {
this.playbin = Gst.ElementFactory.make ("playbin3", null);
assert (this.playbin != null);
this.playbin.source_setup.connect (this.on_source_setup);
this.playbin.source_setup.connect (this.source_setup);
this.playbin.about_to_finish.connect (this.about_to_finish);
// regularly update position
Timeout.add (500, () => {
int64 new_position;
if (this.playbin.query_position (Gst.Format.TIME, out new_position)) {
this.set_position (new_position < this.duration ? new_position : this.duration);
this.position = new_position < this.duration ? new_position : this.duration;
} else {
this.position = 0;
}
// keep rerunning
return true;
});
this.playbin.get_bus ().add_watch (Priority.DEFAULT, (bus, message) => {
// message.type actually seems to be flags
if (Gst.MessageType.ERROR in message.type) {
Error err;
string? debug;
message.parse_error (out err, out debug);
warning ("gst playbin bus error: %s", err.message);
}
var bus = this.playbin.get_bus ();
bus.add_signal_watch ();
if (Gst.MessageType.ASYNC_DONE in message.type) {
assert (this.async_done_callback != null);
var cb = (owned) this.async_done_callback;
assert (this.async_done_callback == null); // sanity check
cb ();
}
if (Gst.MessageType.STREAM_START in message.type) {
int64 new_duration;
assert (this.playbin.query_duration (Gst.Format.TIME, out new_duration));
this.duration = new_duration;
string? next_uri = null;
this.next_uri_lock.lock ();
next_uri = this.next_uri;
if (next_uri != (string) this.playbin.current_uri) {
this.next_uri_lock.unlock ();
// WHOOPS! didn't actually switch to the track the play queue wanted
// we can still fix this though
assert (next_uri != null);
this.playbin.set_state (Gst.State.READY);
this.playbin.uri = next_uri;
this.playbin.set_state (Gst.State.PLAYING);
// no one will ever know
} else {
this.next_uri = null;
this.next_uri_lock.unlock ();
this.stream_started ();
}
}
if (Gst.MessageType.EOS in message.type) {
string next_uri;
this.next_uri_lock.lock ();
next_uri = this.next_uri;
this.next_uri_lock.unlock ();
if (next_uri == null) {
// no next track was arranged, we're done
this.stream_over ();
}
}
return true;
bus.message["error"].connect ((message) => {
Error err;
string? debug;
message.parse_error (out err, out debug);
error ("gst playbin bus error: %s", err.message);
});
this.playbin.about_to_finish.connect (this.on_about_to_finish);
bus.message["warning"].connect ((message) => {
Error err;
string? debug;
message.parse_error (out err, out debug);
warning ("gst playbin bus warning: %s", err.message);
});
bus.message["async-done"].connect ((message) => {
assert (this.async_done_callback != null);
var cb = (owned) this.async_done_callback;
assert (this.async_done_callback == null); // sanity check
cb ();
});
bus.message["stream-start"].connect ((message) => {
int64 new_duration;
assert (this.playbin.query_duration (Gst.Format.TIME, out new_duration));
this.duration = new_duration;
string? next_uri = null;
this.next_uri_lock.lock ();
next_uri = this.next_uri;
if (next_uri != (string) this.playbin.current_uri) {
this.next_uri_lock.unlock ();
// WHOOPS! didn't actually switch to the track the play queue wanted
// we can still fix this though
assert (next_uri != null);
this.playbin.set_state (Gst.State.READY);
this.playbin.uri = next_uri;
this.playbin.set_state (Gst.State.PLAYING);
// no one will ever know
} else {
this.next_uri = null;
this.next_uri_lock.unlock ();
this.stream_started ();
}
});
bus.message["eos"].connect ((message) => {
string next_uri;
this.next_uri_lock.lock ();
next_uri = this.next_uri;
this.next_uri_lock.unlock ();
if (next_uri == null) {
// no next track was arranged, we're done
this.stream_over ();
}
});
}
private async void set_state (Gst.State state) {
@ -190,7 +196,7 @@ class Playbin : Object {
// called when uri can be switched for gapless playback
// need async queue because this might be called from a gstreamer thread
private void on_about_to_finish (dynamic Gst.Element playbin) {
private void about_to_finish (dynamic Gst.Element playbin) {
this.next_uri_lock.lock ();
string? next_uri = this.next_uri;
this.next_uri_lock.unlock ();

View file

@ -131,10 +131,10 @@ class Ui.Window : Adw.ApplicationWindow {
});
this.song = null;
this.playbin.set_position.connect ((sender, new_position) => {
this.playbin.notify["position"].connect (() => {
// only set if we aren't seeking
if (this.seek_timeout_id == 0) {
this.position = new_position;
this.position = this.playbin.position;
}
});
}