api -> subsonic

This commit is contained in:
Erica Z 2024-10-16 13:02:32 +02:00
parent e9bfd056c8
commit 19dd3b13e2
7 changed files with 37 additions and 38 deletions

View file

@ -1,5 +1,3 @@
Subsonic public_api;
public class Audrey.Application : Adw.Application {
public Application () {
Object (

View file

@ -1,10 +1,10 @@
audrey_sources = [
'api.vala',
'application.vala',
'globalconf.vala',
'main.vala',
'mpris.vala',
'playbin.vala',
'subsonic.vala',
'ui/play_queue.vala',
'ui/setup.vala',
'ui/window.vala',

View file

@ -25,14 +25,14 @@ class Playbin : GLib.Object {
public PlaybinState state { get; private set; default = PlaybinState.STOPPED; }
public Song? current_song { get; private set; default = null; }
public Subsonic.Song? current_song { get; private set; default = null; }
// true if a timer should update the position property
private bool update_position = false;
public int64 position { get; private set; default = 0; }
public int64 duration { get; private set; default = 1; } // if 0, the seekbar vanishes
public Subsonic api { get; set; default = null; }
public Subsonic.Client api { get; set; default = null; }
// sent when a new song starts playing
// continues: whether the track is a gapless continuation
@ -109,7 +109,7 @@ class Playbin : GLib.Object {
// we're in luck, about-to-finish hasn't been triggered yet
// we can get away with replacing it
if (this.current_position+1 < play_queue.get_n_items ()) {
Song song = (Song) play_queue.get_item (this.current_position+1);
var song = (Subsonic.Song) play_queue.get_item (this.current_position+1);
this.next_uri.push (this.api.stream_uri (song.id));
} else {
this.next_uri.push ("");
@ -182,7 +182,7 @@ class Playbin : GLib.Object {
this.next_gapless = true;
}
var now_playing = (Song) play_queue.get_item (this.current_position);
var now_playing = (Subsonic.Song) play_queue.get_item (this.current_position);
if (this.api.stream_uri (now_playing.id) == (string) this.playbin.current_uri) {
if (continues) {
this.current_song = now_playing;
@ -190,7 +190,7 @@ class Playbin : GLib.Object {
}
if (this.current_position+1 < play_queue.get_n_items ()) {
Song song = (Song) play_queue.get_item (this.current_position+1);
var song = (Subsonic.Song) play_queue.get_item (this.current_position+1);
this.next_uri.push (this.api.stream_uri (song.id));
} else {
this.next_uri.push ("");
@ -230,7 +230,7 @@ class Playbin : GLib.Object {
this.current_position = position;
this.playbin.set_state (Gst.State.READY);
var song = (Song) this.play_queue.get_item (position);
var song = (Subsonic.Song) this.play_queue.get_item (position);
this.playbin.uri = this.api.stream_uri (song.id);
this.playbin.set_state (Gst.State.PLAYING);
this.next_gapless = false;

View file

@ -1,11 +1,11 @@
errordomain SubsonicError {
public errordomain Subsonic.Error {
BAD_AUTHN,
ERROR,
}
public delegate void SongCallback (Song song);
public delegate void Subsonic.SongCallback (Song song);
public class Artist : Object, Json.Serializable {
public class Subsonic.Artist : Object {
public string index;
public string id;
public string name { get; private set; }
@ -38,7 +38,7 @@ public class Artist : Object, Json.Serializable {
}
}
public class Album : Object {
public class Subsonic.Album : Object {
public string id;
public string name;
@ -53,7 +53,7 @@ public class Album : Object {
}
}
public class Song : Object {
public class Subsonic.Song : Object {
public string id { get; private set; }
public string title { get; private set; }
public string album { get; private set; }
@ -89,7 +89,7 @@ public class Song : Object {
}
}
public struct API.PlayQueue {
public struct Subsonic.PlayQueue {
public string current;
public int64 position;
public DateTime changed;
@ -128,7 +128,7 @@ public struct API.PlayQueue {
}
}
public class Subsonic : Object {
public class Subsonic.Client : Object {
public ListStore artist_list;
public ListStore album_list;
public ListStore song_list;
@ -137,7 +137,7 @@ public class Subsonic : Object {
private string url;
private string parameters;
public Subsonic.with_token (string url, string username, string token, string salt) {
public Client.with_token (string url, string username, string token, string salt) {
this.url = url;
this.parameters = @"u=$(Uri.escape_string(username))&t=$(Uri.escape_string(token))&s=$(Uri.escape_string(salt))&v=1.16.1&c=eu.callcc.audrey";
@ -149,7 +149,7 @@ public class Subsonic : Object {
this.song_list = new ListStore (typeof (Song));
}
private void unwrap_response (Json.Reader reader) throws Error {
private void unwrap_response (Json.Reader reader) throws GLib.Error {
reader.read_member ("subsonic-response");
reader.read_member ("status");
@ -157,15 +157,15 @@ public class Subsonic : Object {
reader.end_member ();
reader.read_member ("error");
reader.read_member ("message");
throw new SubsonicError.ERROR (reader.get_string_value () ?? "???");
throw new Subsonic.Error.ERROR (reader.get_string_value () ?? "???");
}
reader.end_member();
}
public async void ping () throws Error {
public async void ping () throws GLib.Error {
var msg = new Soup.Message ("GET", @"$(this.url)/rest/ping?f=json&$(this.parameters)");
if (msg == null) {
throw new SubsonicError.BAD_AUTHN ("Bad message");
throw new Subsonic.Error.BAD_AUTHN ("Bad message");
}
var bytes = yield this.session.send_and_read_async (msg, Priority.DEFAULT, null);
@ -178,7 +178,7 @@ public class Subsonic : Object {
this.unwrap_response (reader);
}
public async void scrobble (string id) throws Error {
public async void scrobble (string id) throws GLib.Error {
var msg = new Soup.Message ("GET", @"$(this.url)/rest/scrobble?id=$(Uri.escape_string (id))&f=json&$(this.parameters)");
assert (msg != null);
@ -192,7 +192,7 @@ public class Subsonic : Object {
this.unwrap_response (reader);
}
public async void get_random_songs (string? parameters, SongCallback callback) throws Error {
public async void get_random_songs (string? parameters, SongCallback callback) throws GLib.Error {
string str_parameters;
if (parameters == null) {
str_parameters = "";
@ -232,7 +232,7 @@ public class Subsonic : Object {
return @"$(this.url)/rest/getCoverArt?id=$(Uri.escape_string(id))&$(this.parameters)";
}
public async Gdk.Pixbuf cover_art (string id, Cancellable cancellable) throws Error {
public async Gdk.Pixbuf cover_art (string id, Cancellable cancellable) throws GLib.Error {
var msg = new Soup.Message("GET", this.cover_art_uri (id));
assert (msg != null);

View file

@ -34,8 +34,8 @@ template $UiPlayQueue: Adw.NavigationPage {
template ColumnViewCell {
child: Label {
halign: start;
label: bind template.item as <$Song>.title;
tooltip-text: bind template.item as <$Song>.title;
label: bind template.item as <$SubsonicSong>.title;
tooltip-text: bind template.item as <$SubsonicSong>.title;
ellipsize: end;
};
}
@ -50,8 +50,8 @@ template $UiPlayQueue: Adw.NavigationPage {
template ColumnViewCell {
child: Label {
halign: start;
label: bind template.item as <$Song>.artist;
tooltip-text: bind template.item as <$Song>.artist;
label: bind template.item as <$SubsonicSong>.artist;
tooltip-text: bind template.item as <$SubsonicSong>.artist;
ellipsize: end;
};
}

View file

@ -29,7 +29,7 @@ public class Ui.Setup : Adw.PreferencesDialog {
public string token;
public string salt;
public signal void connected (Subsonic api);
public signal void connected (Subsonic.Client api);
private static Secret.Schema secret_schema = new Secret.Schema (
"eu.callcc.audrey",
@ -49,7 +49,7 @@ public class Ui.Setup : Adw.PreferencesDialog {
string new_token, new_salt;
salt_password (this.password, out new_token, out new_salt);
var api = new Subsonic.with_token (
var api = new Subsonic.Client.with_token (
this.server_url,
this.username,
new_token,

View file

@ -9,6 +9,8 @@ class Ui.Window : Adw.ApplicationWindow {
private Setup setup;
private Subsonic.Client api;
public int64 position { get; private set; }
public double volume {
@ -25,7 +27,7 @@ class Ui.Window : Adw.ApplicationWindow {
public Gdk.Paintable playing_cover_art { get; set; }
public Playbin playbin { get; private set; default = new Playbin (); }
public ListStore play_queue_store { get; private set; default = new ListStore (typeof (Song)); }
public ListStore play_queue_store { get; private set; default = new ListStore (typeof (Subsonic.Song)); }
public Window (Gtk.Application app) {
Object (application: app);
@ -56,6 +58,7 @@ class Ui.Window : Adw.ApplicationWindow {
this.setup = new Setup ();
this.setup.connected.connect ((api) => {
this.api = api;
this.playbin.api = api;
this.playbin.now_playing.connect ((continues) => {
@ -70,8 +73,6 @@ class Ui.Window : Adw.ApplicationWindow {
this.playbin.select_track (position);
});
public_api = api;
this.shuffle_all_tracks.sensitive = true;
this.shuffle_all_tracks.activated.connect (() => {
this.shuffle_all_tracks.sensitive = false;
@ -105,9 +106,9 @@ class Ui.Window : Adw.ApplicationWindow {
this.cover_art_loading = true;
string song_id = playbin.current_song.id;
public_api.cover_art.begin (song_id, this.cancel_loading_art, (obj, res) => {
this.api.cover_art.begin (song_id, this.cancel_loading_art, (obj, res) => {
try {
this.playing_cover_art = Gdk.Texture.for_pixbuf (public_api.cover_art.end (res));
this.playing_cover_art = Gdk.Texture.for_pixbuf (this.api.cover_art.end (res));
this.cover_art_loading = false;
} catch (Error e) {
if (!(e is IOError.CANCELLED)) {
@ -215,15 +216,15 @@ class Ui.Window : Adw.ApplicationWindow {
this.seek_impl (new_position);
}
[GtkCallback] private string song_title (Song? song) {
[GtkCallback] private string song_title (Subsonic.Song? song) {
return song == null ? "" : song.title;
}
[GtkCallback] private string song_artist (Song? song) {
[GtkCallback] private string song_artist (Subsonic.Song? song) {
return song == null ? "" : song.artist;
}
[GtkCallback] private string song_album (Song? song) {
[GtkCallback] private string song_album (Subsonic.Song? song) {
return song == null ? "" : song.album;
}
}