[GtkTemplate (ui = "/eu/callcc/audrey/window.ui")] class Ui.Window : Adw.ApplicationWindow { [GtkChild] public unowned Ui.PlayQueue play_queue; [GtkChild] public unowned Ui.Playbar playbar; //[GtkChild] public unowned Adw.ButtonRow shuffle_all_tracks; private Setup setup; private Subsonic.Client api; public int volume { get { return this.playbin.volume; } set { this.playbin.volume = value; } } public bool mute { get { return this.playbin.mute; } set { this.playbin.mute = value; } } public PlaybinSong? song { get; private set; } public Gdk.Paintable? playing_cover_art { get; set; default = null; } private Cancellable cancel_loading_art; public bool cover_art_loading { get; set; default = false; } public Playbin playbin { get; private set; default = new Playbin (); } public Window (Gtk.Application app) { Object (application: app); } private Mpris mpris; private MprisPlayer mpris_player; private void now_playing (PlaybinSong song) { this.song = song; // api.scrobble.begin (this.song.id); TODO if (this.cancel_loading_art != null) { this.cancel_loading_art.cancel (); } this.cancel_loading_art = new GLib.Cancellable (); this.playing_cover_art = null; // TODO: preload next art somehow this.cover_art_loading = true; string song_id = this.song.id; this.api.cover_art.begin (song_id, -1, Priority.DEFAULT, this.cancel_loading_art, (obj, res) => { try { 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)) { warning ("could not load cover for %s: %s", song_id, e.message); this.cover_art_loading = false; } } }); } construct { Bus.own_name ( BusType.SESSION, "org.mpris.MediaPlayer2.audrey", BusNameOwnerFlags.NONE, (conn) => { try { this.mpris = new Mpris (this); this.mpris_player = new MprisPlayer (conn, this.playbin); conn.register_object ("/org/mpris/MediaPlayer2", this.mpris); conn.register_object ("/org/mpris/MediaPlayer2", this.mpris_player); } catch (IOError e) { error ("could not register dbus service: %s", e.message); } }, () => {}, () => { error ("could not acquire dbus name"); }); this.setup = new Setup (); this.setup.connected.connect ((api) => { this.api = api; this.playbin.api = api; this.mpris_player.api = api; this.can_click_shuffle_all = true; }); this.setup.load (); this.playbin.new_track.connect (() => { this.now_playing (this.playbin.play_queue.get_item (this.playbin.play_queue_position) as PlaybinSong); }); this.playbin.stopped.connect (() => { this.playing_cover_art = null; this.song = null; }); } [GtkCallback] private void show_setup_dialog () { this.setup.present (this); } public bool can_click_shuffle_all { get; private set; default = false; } [GtkCallback] private void shuffle_all () { this.can_click_shuffle_all = false; this.playbin.clear (); api.get_random_songs.begin (null, (song) => { this.playbin.append_track (song); }, (obj, res) => { try { api.get_random_songs.end (res); } catch (Error e) { error ("could not get random songs: %s", e.message); } this.can_click_shuffle_all = true; this.playbin.select_track (0); }); } [GtkCallback] private bool show_playbar_cover_art (string? stack_child) { return stack_child != "play-queue"; } public override bool close_request () { // stop playback on close this.playbin.stop (); return false; } ~Window () { debug ("destroying main window"); } }