This commit is contained in:
Erica Z 2024-10-12 13:36:47 +00:00
parent f8287e9ade
commit cc1da96fef
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 // this is the index of the song that will play on next on_stream_start
private uint next_stream_index; 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_next (Song? song);
public signal void play_now (Song song);
public signal void now_playing (Song song);
construct { construct {
this.songs = new ListStore (typeof (Song)); this.songs = new ListStore (typeof (Song));
@ -69,4 +70,20 @@ public class Wavelet.PlayQueue : Adw.NavigationPage {
this.play_next (song); this.play_next (song);
this.play_now (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)); assert (this.playbin.query_duration (Gst.Format.TIME, out new_duration));
this.duration = new_duration; this.duration = new_duration;
string? next_uri = null;
this.next_uri_lock.lock (); 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 = null;
this.next_uri_locked_in = null;
this.next_uri_lock.unlock (); this.next_uri_lock.unlock ();
this.stream_started (); this.stream_started ();
@ -164,6 +172,11 @@ class Playbin : Object {
this.play_now_queued = null; 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); yield this.set_state (Gst.State.READY);
this.playbin.uri = uri; this.playbin.uri = uri;
yield this.set_state (Gst.State.PLAYING); yield this.set_state (Gst.State.PLAYING);
@ -179,6 +192,7 @@ class Playbin : Object {
Mutex next_uri_lock; Mutex next_uri_lock;
string? next_uri; string? next_uri;
string? next_uri_locked_in;
public void set_next_uri (string? next_uri) { public void set_next_uri (string? next_uri) {
this.next_uri_lock.lock (); this.next_uri_lock.lock ();
@ -191,10 +205,19 @@ class Playbin : Object {
private void on_about_to_finish (dynamic Gst.Element playbin) { private void on_about_to_finish (dynamic Gst.Element playbin) {
this.next_uri_lock.lock (); this.next_uri_lock.lock ();
string? next_uri = this.next_uri; string? next_uri = this.next_uri;
this.next_uri_locked_in = next_uri;
this.next_uri_lock.unlock (); this.next_uri_lock.unlock ();
if (next_uri != null) { if (next_uri != null) {
playbin.uri = next_uri; 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 { Button {
icon-name: "media-skip-backward"; icon-name: "media-skip-backward";
valign: center; valign: center;
clicked => $on_skip_backward_clicked ();
} }
Button { Button {
icon-name: "media-playback-start"; icon-name: bind $play_button_icon_name (template.playing) as <string>;
valign: center; valign: center;
clicked => $on_play_pause_clicked (); clicked => $on_play_pause_clicked ();
@ -189,6 +191,8 @@ template $WaveletWindow: Adw.ApplicationWindow {
Button { Button {
icon-name: "media-skip-forward"; icon-name: "media-skip-forward";
valign: center; valign: center;
clicked => $on_skip_forward_clicked ();
} }
Button { Button {

View file

@ -30,6 +30,8 @@ public class Wavelet.Window : Adw.ApplicationWindow {
[GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks; [GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks;
[GtkChild] public unowned Gtk.Button mute; [GtkChild] public unowned Gtk.Button mute;
public bool playing { get; private set; default = false; }
[GtkChild] private unowned Gtk.Scale play_position; [GtkChild] private unowned Gtk.Scale play_position;
public int64 position { get; private set; } 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); playbin.stream_started.connect (this.play_queue.on_stream_start);
this.play_queue.now_playing.connect ((song) => { this.play_queue.now_playing.connect ((song) => {
this.playing = true;
this.song = song; this.song = song;
}); });
@ -148,9 +151,6 @@ public class Wavelet.Window : Adw.ApplicationWindow {
return "%02d:%02d".printf (s/60, s%60); 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 // same timeout logic as https://code.videolan.org/videolan/npapi-vlc/blob/6eae0ffb9cbaf8f6e04423de2ff38daabdf7cae3/npapi/vlcplugin_gtk.cpp#L312
private uint seek_timeout_id = 0; private uint seek_timeout_id = 0;
[GtkCallback] private bool on_play_position_seek (Gtk.Range range, Gtk.ScrollType scroll_type, double value) { [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; 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 ();
}
} }