remove many manual connections

This commit is contained in:
me 2024-10-11 08:22:05 +00:00
parent 9f2a2d2039
commit 45cbe8cb2c
7 changed files with 108 additions and 98 deletions

View file

@ -85,7 +85,7 @@ public class Wavelet.Application : Adw.Application {
Timeout.add (100, () => { Timeout.add (100, () => {
int64 position_ns; int64 position_ns;
if (playbin.query_position (Gst.Format.TIME, out position_ns)) { if (playbin.query_position (Gst.Format.TIME, out position_ns)) {
win.play_position_ms = position_ns / 1000000; win.play_position_ms = (int) (position_ns / 1000000);
} }
return Source.CONTINUE; return Source.CONTINUE;
}); });
@ -100,7 +100,7 @@ public class Wavelet.Application : Adw.Application {
print("%lld\n", duration_ns); print("%lld\n", duration_ns);
win.play_position_ms = 0; win.play_position_ms = 0;
win.play_duration_ms = duration_ns / 1000000; win.play_duration_ms = (int) (duration_ns / 1000000);
break; break;

View file

@ -12,6 +12,8 @@ template $WaveletPlayQueue: Adw.NavigationPage {
ListView list_view { ListView list_view {
single-click-activate: true; single-click-activate: true;
activate => $on_song_activate ();
factory: BuilderListItemFactory { factory: BuilderListItemFactory {
template ListItem { template ListItem {
child: Label { child: Label {

View file

@ -32,11 +32,6 @@ public class Wavelet.PlayQueue : Adw.NavigationPage {
this.current = 0; this.current = 0;
this.list_view.model = new Gtk.NoSelection (this.songs); this.list_view.model = new Gtk.NoSelection (this.songs);
this.list_view.activate.connect ((position) => {
this.current = position;
Song song = (Song) this.songs.get_item (position);
this.play_now (song);
});
} }
public void clear () { public void clear () {
@ -57,4 +52,10 @@ public class Wavelet.PlayQueue : Adw.NavigationPage {
public Song? peek () { public Song? peek () {
return (Song?) this.songs.get_item (this.current+1); return (Song?) this.songs.get_item (this.current+1);
} }
[GtkCallback] private void on_song_activate (uint position) {
this.current = position;
Song song = (Song) this.songs.get_item (position);
this.play_now (song);
}
} }

View file

@ -12,31 +12,52 @@ template $WaveletSetup: Adw.NavigationPage {
child: Adw.PreferencesGroup { child: Adw.PreferencesGroup {
title: _("Authentication"); title: _("Authentication");
Adw.EntryRow server_url { [header-suffix]
Gtk.Button {
styles [ "flat" ]
icon-name: "edit-undo";
sensitive: bind template.authn_can_validate;
}
Adw.EntryRow {
title: _("Server URL"); title: _("Server URL");
input-purpose: url; input-purpose: url;
sensitive: bind template.authn_can_edit;
text: bind template.server_url bidirectional;
changed => $on_authn_changed ();
} }
Adw.EntryRow username { Adw.EntryRow {
title: _("Username"); title: _("Username");
sensitive: bind template.authn_can_edit;
text: bind template.username bidirectional;
changed => $on_authn_changed ();
} }
Adw.PasswordEntryRow password { Adw.PasswordEntryRow {
title: _("Password"); title: _("Password");
sensitive: bind template.authn_can_edit;
text: bind template.password bidirectional;
changed => $on_authn_changed ();
} }
Adw.ActionRow status { Adw.ActionRow {
title: _("Status"); title: _("Status");
subtitle: _("Not connected"); subtitle: bind template.status;
styles [ styles [
"property", "property",
] ]
} }
Adw.ButtonRow validate { Adw.ButtonRow {
title: _("Connect and save"); title: _("Connect and save");
sensitive: false; sensitive: bind template.authn_can_validate;
activated => $on_authn_validate_activated ();
} }
}; };
} }

View file

@ -23,68 +23,56 @@ public extern void randomness (int N, void *P);
[GtkTemplate (ui = "/eu/callcc/Wavelet/setup.ui")] [GtkTemplate (ui = "/eu/callcc/Wavelet/setup.ui")]
public class Wavelet.Setup : Adw.NavigationPage { public class Wavelet.Setup : Adw.NavigationPage {
[GtkChild] private unowned Adw.EntryRow server_url; public string status { get; private set; default = _("Not connected"); }
[GtkChild] private unowned Adw.EntryRow username;
[GtkChild] private unowned Adw.PasswordEntryRow password;
[GtkChild] private unowned Adw.ActionRow status; public bool authn_can_edit { get; private set; default = true; }
[GtkChild] private unowned Adw.ButtonRow validate; public bool authn_can_validate { get; private set; default = false; }
private string token; public string server_url { get; set; default = ""; }
private string salt; public string username { get; set; default = ""; }
public string password { get; set; default = ""; }
public string token;
public string salt;
public signal void connected (Wavelet.Subsonic api); public signal void connected (Wavelet.Subsonic api);
construct { [GtkCallback] private void on_authn_changed () {
this.server_url.changed.connect (() => { this.authn_can_validate = true;
this.validate.set_sensitive (true); }
});
this.username.changed.connect (() => {
this.validate.set_sensitive (true);
});
this.password.changed.connect (() => {
this.validate.set_sensitive (true);
});
this.validate.activated.connect (() => { [GtkCallback] private void on_authn_validate_activated () {
this.server_url.set_sensitive (false); this.authn_can_validate = false;
this.username.set_sensitive (false); this.authn_can_edit = false;
this.password.set_sensitive (false); this.status = _("Connecting...");
this.status.set_subtitle (_("Connecting..."));
this.validate.set_sensitive (false);
string new_token, new_salt; string new_token, new_salt;
if (this.password.get_text () != "") { if (this.password != "") {
this.salt_password (this.password.get_text (), out new_token, out new_salt); this.salt_password (this.password, out new_token, out new_salt);
} else { } else {
new_token = this.token; new_token = this.token;
new_salt = this.salt; new_salt = this.salt;
}
var api = new Wavelet.Subsonic.with_token (
this.server_url,
this.username,
new_token,
new_salt);
api.ping.begin ((obj, res) => {
try {
api.ping.end (res);
this.status = _("Connected");
this.token = new_token;
this.salt = new_salt;
this.save ();
this.connected (api);
} catch (Error e) {
this.status = @"$(_("Ping failed")): $(e.message)";
this.authn_can_validate = true;
} }
var api = new Wavelet.Subsonic.with_token (
this.server_url.get_text (),
this.username.get_text (),
new_token,
new_salt);
api.ping.begin ((obj, res) => { this.authn_can_edit = true;
try {
api.ping.end (res);
this.status.set_subtitle (_("Connected"));
this.token = new_token;
this.salt = new_salt;
this.save ();
this.validate.set_sensitive (false);
this.connected (api);
} catch (Error e) {
this.status.set_subtitle(@"$(_("Ping failed")): $(e.message)");
this.validate.set_sensitive (true);
}
this.server_url.set_sensitive (true);
this.username.set_sensitive (true);
this.password.set_sensitive (true);
});
}); });
} }
@ -97,17 +85,17 @@ public class Wavelet.Setup : Adw.NavigationPage {
stmt.bind_text (1, "server_url"); stmt.bind_text (1, "server_url");
if (stmt.step () == Sqlite.ROW) { if (stmt.step () == Sqlite.ROW) {
this.server_url.set_text (stmt.column_text (0)); this.server_url = stmt.column_text (0);
} else { } else {
this.server_url.set_text (""); this.server_url = "";
} }
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
stmt.bind_text (1, "username"); stmt.bind_text (1, "username");
if (stmt.step () == Sqlite.ROW) { if (stmt.step () == Sqlite.ROW) {
this.username.set_text (stmt.column_text (0)); this.username = stmt.column_text (0);
} else { } else {
this.username.set_text (""); this.username = "";
} }
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
@ -127,11 +115,11 @@ public class Wavelet.Setup : Adw.NavigationPage {
} }
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
this.password.set_text (""); this.password = "";
this.validate.set_sensitive (false);
// first connection // first connection
this.validate.activate (); this.authn_can_validate = true;
this.on_authn_validate_activated ();
} }
private void salt_password (string password, out string token, out string salt) { private void salt_password (string password, out string token, out string salt) {
@ -159,12 +147,12 @@ public class Wavelet.Setup : Adw.NavigationPage {
assert (rc == Sqlite.OK); assert (rc == Sqlite.OK);
stmt.bind_text (1, "server_url"); stmt.bind_text (1, "server_url");
stmt.bind_text (2, this.server_url.get_text ()); stmt.bind_text (2, this.server_url);
assert (stmt.step () == Sqlite.DONE); assert (stmt.step () == Sqlite.DONE);
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
stmt.bind_text (1, "username"); stmt.bind_text (1, "username");
stmt.bind_text (2, this.username.get_text ()); stmt.bind_text (2, this.username);
assert (stmt.step () == Sqlite.DONE); assert (stmt.step () == Sqlite.DONE);
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
@ -178,6 +166,6 @@ public class Wavelet.Setup : Adw.NavigationPage {
assert (stmt.step () == Sqlite.DONE); assert (stmt.step () == Sqlite.DONE);
assert (stmt.reset () == Sqlite.OK); assert (stmt.reset () == Sqlite.OK);
this.password.set_text (""); this.password = "";
} }
} }

View file

@ -29,6 +29,8 @@ template $WaveletWindow: Adw.ApplicationWindow {
"navigation-sidebar", "navigation-sidebar",
] ]
row-activated => $on_sidebar_row_activated();
ListBoxRow sidebar_setup { ListBoxRow sidebar_setup {
Label { Label {
xalign: 0; xalign: 0;
@ -152,7 +154,7 @@ template $WaveletWindow: Adw.ApplicationWindow {
"numeric", "numeric",
] ]
label: "00:00"; label: bind $format_timestamp (template.play_position_ms) as <string>;
} }
Scale play_position { Scale play_position {
@ -173,7 +175,7 @@ template $WaveletWindow: Adw.ApplicationWindow {
"numeric", "numeric",
] ]
label: "00:00"; label: bind $format_timestamp (template.play_duration_ms) as <string>;
} }
} }
} }

View file

@ -36,8 +36,8 @@ public class Wavelet.Window : Adw.ApplicationWindow {
[GtkChild] public unowned Gtk.Scale play_position; [GtkChild] public unowned Gtk.Scale play_position;
[GtkChild] private unowned Gtk.Label play_duration; [GtkChild] private unowned Gtk.Label play_duration;
public int64 play_position_ms { get; set; default = 0; } public int play_position_ms { get; set; default = 0; }
public int64 play_duration_ms { get; set; default = 1; } public int play_duration_ms { get; set; default = 1; }
public double volume { get; set; default = 1.0; } public double volume { get; set; default = 1.0; }
@ -48,23 +48,6 @@ public class Wavelet.Window : Adw.ApplicationWindow {
} }
construct { construct {
this.notify["play-position-ms"].connect ((s, p) => {
int seconds = (int)(this.play_position_ms/1000);
this.play_position_label.label = "%02d:%02d".printf(seconds/60, seconds%60);
});
this.notify["play-duration-ms"].connect ((s, p) => {
int seconds = (int)(this.play_duration_ms/1000);
this.play_duration.label = "%02d:%02d".printf(seconds/60, seconds%60);
});
this.sidebar.row_activated.connect ((row) => {
if (row == this.sidebar_setup) {
this.stack.set_visible_child_name("setup");
} else if (row == this.sidebar_play_queue) {
this.stack.set_visible_child_name("play_queue");
}
});
this.sidebar.select_row (this.sidebar.get_row_at_index (0)); this.sidebar.select_row (this.sidebar.get_row_at_index (0));
} }
@ -75,4 +58,17 @@ public class Wavelet.Window : Adw.ApplicationWindow {
public void show_unmute () { public void show_unmute () {
this.mute.icon_name = "audio-volume-high"; this.mute.icon_name = "audio-volume-high";
} }
[GtkCallback] private void on_sidebar_row_activated (Gtk.ListBoxRow row) {
if (row == this.sidebar_setup) {
this.stack.set_visible_child_name("setup");
} else if (row == this.sidebar_play_queue) {
this.stack.set_visible_child_name("play_queue");
}
}
[GtkCallback] private string format_timestamp (int ms) {
int s = ms / 1000;
return "%02d:%02d".printf (s/60, s%60);
}
} }