This commit is contained in:
me 2024-10-12 13:36:47 +00:00
parent 71429fa5b4
commit 8a22d255c6
4 changed files with 72 additions and 6 deletions

View file

@ -25,9 +25,10 @@ public class Wavelet.PlayQueue : Adw.NavigationPage {
// this is the index of the song that will play on next on_stream_start
private uint next_stream_index;
public signal void play_now (Song song);
public signal void now_playing (Song song);
public signal void play_next (Song? song);
public signal void play_now (Song song);
public signal void now_playing (Song song);
construct {
this.songs = new ListStore (typeof (Song));
@ -69,4 +70,20 @@ public class Wavelet.PlayQueue : Adw.NavigationPage {
this.play_next (song);
this.play_now (song);
}
public void skip_forward () {
Song song = (Song) this.songs.get_item (this.next_stream_index);
this.play_now (song);
}
public void skip_backward () {
if (this.next_stream_index <= 1) {
this.next_stream_index = 0;
} else {
this.next_stream_index -= 2;
}
Song song = (Song) this.songs.get_item (this.next_stream_index);
this.play_next (song);
this.play_now (song);
}
}

View file

@ -86,8 +86,16 @@ class Playbin : Object {
assert (this.playbin.query_duration (Gst.Format.TIME, out new_duration));
this.duration = new_duration;
string? next_uri = null;
this.next_uri_lock.lock ();
if (this.next_uri != this.next_uri_locked_in) {
// WHOOPS! didn't actually switch to the track the play queue wanted
// FIXME as it arises
assert (false);
}
this.next_uri = null;
this.next_uri_locked_in = null;
this.next_uri_lock.unlock ();
this.stream_started ();
@ -164,6 +172,11 @@ class Playbin : Object {
this.play_now_queued = null;
}
// pretend this track was locked in by about-to-finish before
this.next_uri_lock.lock ();
this.next_uri_locked_in = uri;
this.next_uri_lock.unlock ();
yield this.set_state (Gst.State.READY);
this.playbin.uri = uri;
yield this.set_state (Gst.State.PLAYING);
@ -179,6 +192,7 @@ class Playbin : Object {
Mutex next_uri_lock;
string? next_uri;
string? next_uri_locked_in;
public void set_next_uri (string? next_uri) {
this.next_uri_lock.lock ();
@ -191,10 +205,19 @@ class Playbin : Object {
private void on_about_to_finish (dynamic Gst.Element playbin) {
this.next_uri_lock.lock ();
string? next_uri = this.next_uri;
this.next_uri_locked_in = next_uri;
this.next_uri_lock.unlock ();
if (next_uri != null) {
playbin.uri = next_uri;
}
}
public void pause () {
this.playbin.set_state (Gst.State.PAUSED);
}
public void play () {
this.playbin.set_state (Gst.State.PLAYING);
}
}

View file

@ -177,10 +177,12 @@ template $WaveletWindow: Adw.ApplicationWindow {
Button {
icon-name: "media-skip-backward";
valign: center;
clicked => $on_skip_backward_clicked ();
}
Button {
icon-name: "media-playback-start";
icon-name: bind $play_button_icon_name (template.playing) as <string>;
valign: center;
clicked => $on_play_pause_clicked ();
@ -189,6 +191,8 @@ template $WaveletWindow: Adw.ApplicationWindow {
Button {
icon-name: "media-skip-forward";
valign: center;
clicked => $on_skip_forward_clicked ();
}
Button {

View file

@ -30,6 +30,8 @@ public class Wavelet.Window : Adw.ApplicationWindow {
[GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks;
[GtkChild] public unowned Gtk.Button mute;
public bool playing { get; private set; default = false; }
[GtkChild] private unowned Gtk.Scale play_position;
public int64 position { get; private set; }
@ -74,6 +76,7 @@ public class Wavelet.Window : Adw.ApplicationWindow {
playbin.stream_started.connect (this.play_queue.on_stream_start);
this.play_queue.now_playing.connect ((song) => {
this.playing = true;
this.song = song;
});
@ -148,9 +151,6 @@ public class Wavelet.Window : Adw.ApplicationWindow {
return "%02d:%02d".printf (s/60, s%60);
}
[GtkCallback] private void on_play_pause_clicked () {
}
// same timeout logic as https://code.videolan.org/videolan/npapi-vlc/blob/6eae0ffb9cbaf8f6e04423de2ff38daabdf7cae3/npapi/vlcplugin_gtk.cpp#L312
private uint seek_timeout_id = 0;
[GtkCallback] private bool on_play_position_seek (Gtk.Range range, Gtk.ScrollType scroll_type, double value) {
@ -164,4 +164,26 @@ public class Wavelet.Window : Adw.ApplicationWindow {
}
return false;
}
[GtkCallback] private void on_play_pause_clicked () {
if (this.playing) {
this.playbin.pause();
this.playing = false;
} else {
this.playbin.play();
this.playing = true;
}
}
[GtkCallback] private string play_button_icon_name (bool playing) {
return playing ? "media-playback-pause" : "media-playback-start";
}
[GtkCallback] private void on_skip_forward_clicked () {
this.play_queue.skip_forward ();
}
[GtkCallback] private void on_skip_backward_clicked () {
this.play_queue.skip_backward ();
}
}