remove many manual connections
This commit is contained in:
parent
84696ef1ca
commit
c5161b9c01
7 changed files with 108 additions and 98 deletions
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (
|
var api = new Wavelet.Subsonic.with_token (
|
||||||
this.server_url.get_text (),
|
this.server_url,
|
||||||
this.username.get_text (),
|
this.username,
|
||||||
new_token,
|
new_token,
|
||||||
new_salt);
|
new_salt);
|
||||||
|
|
||||||
api.ping.begin ((obj, res) => {
|
api.ping.begin ((obj, res) => {
|
||||||
try {
|
try {
|
||||||
api.ping.end (res);
|
api.ping.end (res);
|
||||||
this.status.set_subtitle (_("Connected"));
|
this.status = _("Connected");
|
||||||
this.token = new_token;
|
this.token = new_token;
|
||||||
this.salt = new_salt;
|
this.salt = new_salt;
|
||||||
this.save ();
|
this.save ();
|
||||||
this.validate.set_sensitive (false);
|
|
||||||
|
|
||||||
this.connected (api);
|
this.connected (api);
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
this.status.set_subtitle(@"$(_("Ping failed")): $(e.message)");
|
this.status = @"$(_("Ping failed")): $(e.message)";
|
||||||
this.validate.set_sensitive (true);
|
this.authn_can_validate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.server_url.set_sensitive (true);
|
this.authn_can_edit = 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 = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue