/* application.vala * * Copyright 2024 Erica Z * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * SPDX-License-Identifier: AGPL-3.0-or-later */ Sqlite.Database config_db; Gst.Element playbin; Wavelet.Subsonic public_api; public class Wavelet.Application : Adw.Application { public Application () { Object ( application_id: "eu.callcc.Wavelet", flags: ApplicationFlags.DEFAULT_FLAGS ); var app_config_dir = Path.build_filename (Environment.get_user_config_dir (), "wavelet"); try { File.new_build_filename (app_config_dir).make_directory_with_parents (); } catch (Error e) { // just ignore if the directory already existed } int ec = Sqlite.Database.open (Path.build_filename (app_config_dir, "config.db"), out config_db); assert (ec == Sqlite.OK); ec = config_db.exec (""" CREATE TABLE IF NOT EXISTS Setup (key UNIQUE, value); """, null, null); assert (ec == Sqlite.OK); } construct { ActionEntry[] action_entries = { { "about", this.on_about_action }, { "preferences", this.on_preferences_action }, { "quit", this.quit } }; this.add_action_entries (action_entries, this); this.set_accels_for_action ("app.quit", {"q"}); } public override void activate () { base.activate (); // FIXME edit back if issues var win = this.active_window ?? new Wavelet.Window (this); var win = new Wavelet.Window (this); win.present (); win.artist_list.set_loading (); win.song_list.set_loading (); playbin = Gst.ElementFactory.make ("playbin3", null); assert (playbin != null); win.notify["volume"].connect ((s, p) => { // gst docs: Volume sliders should usually use a cubic volume. ((Gst.Audio.StreamVolume) playbin).set_volume (Gst.Audio.StreamVolumeFormat.CUBIC, win.volume); }); win.mute.clicked.connect (() => { var vol = (Gst.Audio.StreamVolume) playbin; if (vol.get_mute ()) { win.show_unmute (); vol.set_mute (false); } else { win.show_mute (); vol.set_mute (true); } }); Timeout.add (100, () => { int64 position_ns; if (playbin.query_position (Gst.Format.TIME, out position_ns)) { win.play_position_ms = (int) (position_ns / 1000000); } return Source.CONTINUE; }); playbin.get_bus ().add_watch (Priority.DEFAULT, (bus, message) => { switch (message.type) { case Gst.MessageType.ASYNC_DONE: win.play_position.sensitive = true; int64 duration_ns; if (playbin.query_duration (Gst.Format.TIME, out duration_ns)) { win.play_position_ms = 0; win.play_duration_ms = (int) (duration_ns / 1000000); } else { warning ("could not query playbin duration after ASYNC_DONE"); } break; default: break; } return true; }); var next_queue = new AsyncQueue (); win.setup.connected.connect ((api) => { public_api = api; win.artist_list.model = api.artist_list; win.song_list.model = api.song_list; api.done_reloading.connect (() => { win.artist_list.set_ready (); win.song_list.set_ready (); }); //api.reload.begin (); win.shuffle_all_tracks.sensitive = true; win.shuffle_all_tracks.activated.connect (() => { win.shuffle_all_tracks.sensitive = false; win.play_queue.clear (); api.get_random_songs.begin (null, (song) => { win.play_queue.queue (song); }, (obj, res) => { try { api.get_random_songs.end (res); } catch (Error e) { error ("could not get random songs: %s", e.message); } win.shuffle_all_tracks.sensitive = true; }); }); win.play_queue.play_now.connect ((song) => { win.play_position.sensitive = false; playbin.set_state (Gst.State.READY); playbin.set ("uri", api.stream_uri (song.id)); playbin.set_state (Gst.State.PLAYING); win.song = song; }); }); win.setup.load (config_db); } private void on_about_action () { string[] developers = { "Erica Z" }; var about = new Adw.AboutDialog () { application_name = "wavelet", application_icon = "eu.callcc.Wavelet", developer_name = "Erica Z", translator_credits = _("translator-credits"), version = "0.1.0", developers = developers, copyright = "© 2024 Erica Z", }; about.present (this.active_window); } private void on_preferences_action () { message ("app.preferences action activated"); } }