diff options
Diffstat (limited to 'src/media-player-user.vala')
-rw-r--r-- | src/media-player-user.vala | 563 |
1 files changed, 290 insertions, 273 deletions
diff --git a/src/media-player-user.vala b/src/media-player-user.vala index 0071b93..64e9bd5 100644 --- a/src/media-player-user.vala +++ b/src/media-player-user.vala @@ -1,5 +1,6 @@ /* * Copyright © 2014 Canonical Ltd. + * Copyright © 2021 Robert Tari * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,280 +16,296 @@ * * Authors: * Ted Gould <ted@canonical.com> + * Robert Tari <robert@tari.in> */ public class MediaPlayerUser : MediaPlayer { - Act.UserManager accounts_manager = Act.UserManager.get_default(); - string username; - Act.User? actuser = null; - AccountsServiceSoundSettings? proxy = null; - GreeterBroadcast? greeter = null; - - HashTable<string, bool> properties_queued = new HashTable<string, bool>(str_hash, str_equal); - uint properties_timeout = 0; - - /* Grab the user from the Accounts service and, when it is loaded then - set up a proxy to its sound settings */ - public MediaPlayerUser(string user) { - username = user; - - actuser = accounts_manager.get_user(user); - actuser.notify["is-loaded"].connect(() => { - debug("User loaded"); - - this.proxy = null; - - Bus.get_proxy.begin<AccountsServiceSoundSettings> ( - BusType.SYSTEM, - "org.freedesktop.Accounts", - actuser.get_object_path(), - DBusProxyFlags.GET_INVALIDATED_PROPERTIES, - null, - new_proxy); - }); - - Bus.get_proxy.begin<GreeterBroadcast> ( - BusType.SYSTEM, - "org.ayatana.Desktop.Greeter.Broadcast", - "/org/ayatana/Desktop/Greeter/Broadcast", - DBusProxyFlags.NONE, - null, - greeter_proxy_new); - } - - ~MediaPlayerUser () { - if (properties_timeout != 0) { - Source.remove(properties_timeout); - properties_timeout = 0; - } - } - - /* Ensure that we've collected all the changes so that we only signal - once for variables like 'track' */ - bool properties_idle () { - properties_timeout = 0; - - properties_queued.@foreach((key, value) => { - debug("Notifying '%s' changed", key); - this.notify_property(key); - }); - - properties_queued.remove_all(); - - return Source.REMOVE; - } - - /* Turns the DBus names into the object properties */ - void queue_property_notification (string dbus_property_name) { - if (properties_timeout == 0) { - properties_timeout = Idle.add(properties_idle); - } - - switch (dbus_property_name) { - case "Timestamp": - properties_queued.insert("name", true); - properties_queued.insert("icon", true); - properties_queued.insert("state", true); - properties_queued.insert("current-track", true); - properties_queued.insert("is-running", true); - break; - case "PlayerName": - properties_queued.insert("name", true); - break; - case "PlayerIcon": - properties_queued.insert("icon", true); - break; - case "State": - properties_queued.insert("state", true); - break; - case "Title": - case "Artist": - case "Album": - case "ArtUrl": - properties_queued.insert("current-track", true); - break; - } - } - - void new_proxy (GLib.Object? obj, AsyncResult res) { - try { - this.proxy = Bus.get_proxy.end (res); - - var gproxy = this.proxy as DBusProxy; - gproxy.g_properties_changed.connect ((proxy, changed, invalidated) => { - string key = ""; - Variant value; - VariantIter iter = new VariantIter(changed); - - while (iter.next("{sv}", &key, &value)) { - queue_property_notification(key); - } - - foreach (var invalid in invalidated) { - queue_property_notification(invalid); - } - }); - - debug("Notifying player is ready for user: %s", this.username); - this.notify_property("is-running"); - } catch (Error e) { - this.proxy = null; - warning("Unable to get proxy to user '%s' sound settings: %s", username, e.message); - } - } - - bool proxy_is_valid () { - if (this.proxy == null) { - return false; - } - - /* More than 10 minutes old */ - if (this.proxy.timestamp < GLib.get_monotonic_time() - 10 * 60 * 1000 * 1000) { - return false; - } - - return true; - } - - public override string id { - get { return username; } - } - - /* These values come from the proxy */ - string name_cache; - public override string name { - get { - if (proxy_is_valid()) { - name_cache = this.proxy.player_name; - debug("Player Name: %s", name_cache); - return name_cache; - } else { - return ""; - } - } - } - string state_cache; - public override string state { - get { - if (proxy_is_valid()) { - state_cache = this.proxy.state; - debug("State: %s", state_cache); - return state_cache; - } else { - return ""; - } - } - set { } - } - Icon icon_cache; - public override Icon? icon { - get { - if (proxy_is_valid()) { - icon_cache = Icon.deserialize(this.proxy.player_icon); - return icon_cache; - } else { - return null; - } - } - } - - /* Placeholder */ - public override string dbus_name { get { return ""; } } - - /* If it's shown externally it's running */ - public override bool is_running { get { return proxy_is_valid(); } } - /* A bit weird. Not sure how we should handle this. */ - public override bool can_raise { get { return true; } } - - /* Fill out the track based on the values in the proxy */ - MediaPlayer.Track track_cache; - public override MediaPlayer.Track? current_track { - get { - if (proxy_is_valid()) { - track_cache = new MediaPlayer.Track( - this.proxy.artist, - this.proxy.title, - this.proxy.album, - this.proxy.art_url - ); - return track_cache; - } else { - return null; - } - } - set { } - } - - void greeter_proxy_new (GLib.Object? obj, AsyncResult res) { - try { - this.greeter = Bus.get_proxy.end (res); - } catch (Error e) { - this.greeter = null; - warning("Unable to get greeter proxy: %s", e.message); - } - } - - /* Control functions through unity-greeter-session-broadcast */ - public override void activate () { - /* TODO: */ - } - public override void play_pause () { - debug("Play Pause for user: %s", this.username); - - if (this.greeter != null) { - this.greeter.RequestSoundPlayPause.begin(this.username, (obj, res) => { - try { - (obj as GreeterBroadcast).RequestSoundPlayPause.end(res); - } catch (Error e) { - warning("Unable to send play pause: %s", e.message); - } - }); - } else { - warning("No unity-greeter-session-broadcast to send play-pause"); - } - } - public override void next () { - debug("Next for user: %s", this.username); - - if (this.greeter != null) { - this.greeter.RequestSoundNext.begin(this.username, (obj, res) => { - try { - (obj as GreeterBroadcast).RequestSoundNext.end(res); - } catch (Error e) { - warning("Unable to send next: %s", e.message); - } - }); - } else { - warning("No unity-greeter-session-broadcast to send next"); - } - } - public override void previous () { - debug("Previous for user: %s", this.username); - - if (this.greeter != null) { - this.greeter.RequestSoundPrev.begin(this.username, (obj, res) => { - try { - (obj as GreeterBroadcast).RequestSoundPrev.end(res); - } catch (Error e) { - warning("Unable to send previous: %s", e.message); - } - }); - } else { - warning("No unity-greeter-session-broadcast to send previous"); - } - } - - /* Play list functions are all null as we don't support the - playlist feature on the greeter */ - public override uint get_n_playlists() { - return 0; - } - public override string get_playlist_id (int index) { - return ""; - } - public override string get_playlist_name (int index) { - return ""; - } - public override void activate_playlist_by_name (string playlist) { - } + Act.UserManager accounts_manager = Act.UserManager.get_default(); + string username; + Act.User? actuser = null; + AccountsServiceSoundSettings? proxy = null; + GreeterBroadcast? greeter = null; + + HashTable<string, bool> properties_queued = new HashTable<string, bool>(str_hash, str_equal); + uint properties_timeout = 0; + + /* Grab the user from the Accounts service and, when it is loaded then + set up a proxy to its sound settings */ + public MediaPlayerUser(string user) { + username = user; + + actuser = accounts_manager.get_user(user); + actuser.notify["is-loaded"].connect(() => { + debug("User loaded"); + + this.proxy = null; + + Bus.get_proxy.begin<AccountsServiceSoundSettings> ( + BusType.SYSTEM, + "org.freedesktop.Accounts", + actuser.get_object_path(), + DBusProxyFlags.GET_INVALIDATED_PROPERTIES, + null, + new_proxy); + }); + + Bus.get_proxy.begin<GreeterBroadcast> ( + BusType.SYSTEM, + "org.ayatana.Desktop.Greeter.Broadcast", + "/org/ayatana/Desktop/Greeter/Broadcast", + DBusProxyFlags.NONE, + null, + greeter_proxy_new); + } + + ~MediaPlayerUser () { + if (properties_timeout != 0) { + Source.remove(properties_timeout); + properties_timeout = 0; + } + } + + /* Ensure that we've collected all the changes so that we only signal + once for variables like 'track' */ + bool properties_idle () { + properties_timeout = 0; + + properties_queued.@foreach((key, value) => { + debug("Notifying '%s' changed", key); + this.notify_property(key); + }); + + properties_queued.remove_all(); + + return Source.REMOVE; + } + + /* Turns the DBus names into the object properties */ + void queue_property_notification (string dbus_property_name) { + if (properties_timeout == 0) { + properties_timeout = Idle.add(properties_idle); + } + + switch (dbus_property_name) { + case "Timestamp": + properties_queued.insert("name", true); + properties_queued.insert("icon", true); + properties_queued.insert("state", true); + properties_queued.insert("current-track", true); + properties_queued.insert("is-running", true); + break; + case "PlayerName": + properties_queued.insert("name", true); + break; + case "PlayerIcon": + properties_queued.insert("icon", true); + break; + case "State": + properties_queued.insert("state", true); + break; + case "Title": + case "Artist": + case "Album": + case "ArtUrl": + properties_queued.insert("current-track", true); + break; + } + } + + void new_proxy (GLib.Object? obj, AsyncResult res) { + try { + this.proxy = Bus.get_proxy.end (res); + + var gproxy = this.proxy as DBusProxy; + gproxy.g_properties_changed.connect ((proxy, changed, invalidated) => { + string key = ""; + Variant value; + VariantIter iter = new VariantIter(changed); + + while (iter.next("{sv}", &key, &value)) { + queue_property_notification(key); + } + + foreach (var invalid in invalidated) { + queue_property_notification(invalid); + } + }); + + debug("Notifying player is ready for user: %s", this.username); + this.notify_property("is-running"); + } catch (Error e) { + this.proxy = null; + warning("Unable to get proxy to user '%s' sound settings: %s", username, e.message); + } + } + + bool proxy_is_valid () { + if (this.proxy == null) { + return false; + } + + /* More than 10 minutes old */ + if (this.proxy.timestamp < GLib.get_monotonic_time() - 10 * 60 * 1000 * 1000) { + return false; + } + + return true; + } + + public override string id { + get { return username; } + } + + /* These values come from the proxy */ + string name_cache; + public override string name { + get { + if (proxy_is_valid()) { + name_cache = this.proxy.player_name; + debug("Player Name: %s", name_cache); + return name_cache; + } else { + return ""; + } + } + } + string state_cache; + public override string state { + get { + if (proxy_is_valid()) { + state_cache = this.proxy.state; + debug("State: %s", state_cache); + return state_cache; + } else { + return ""; + } + } + set { } + } + Icon icon_cache; + public override Icon? icon { + get { + if (proxy_is_valid()) { + icon_cache = Icon.deserialize(this.proxy.player_icon); + return icon_cache; + } else { + return null; + } + } + } + + /* Placeholder */ + public override string dbus_name { get { return ""; } } + + /* If it's shown externally it's running */ + public override bool is_running { get { return proxy_is_valid(); } } + /* A bit weird. Not sure how we should handle this. */ + public override bool can_raise { get { return true; } } + + /* Fill out the track based on the values in the proxy */ + MediaPlayer.Track track_cache; + public override MediaPlayer.Track? current_track { + get { + if (proxy_is_valid()) { + track_cache = new MediaPlayer.Track( + this.proxy.artist, + this.proxy.title, + this.proxy.album, + this.proxy.art_url + ); + return track_cache; + } else { + return null; + } + } + set { } + } + + void greeter_proxy_new (GLib.Object? obj, AsyncResult res) { + try { + this.greeter = Bus.get_proxy.end (res); + } catch (Error e) { + this.greeter = null; + warning("Unable to get greeter proxy: %s", e.message); + } + } + + /* Control functions through unity-greeter-session-broadcast */ + public override void activate () { + /* TODO: */ + } + public override void play_pause () { + debug("Play Pause for user: %s", this.username); + + if (this.greeter != null) { + this.greeter.RequestSoundPlayPause.begin(this.username, (obj, res) => { + try { + var broadcasts = (obj as GreeterBroadcast); + + if (broadcasts != null) + { + broadcasts.RequestSoundPlayPause.end(res); + } + } catch (Error e) { + warning("Unable to send play pause: %s", e.message); + } + }); + } else { + warning("No unity-greeter-session-broadcast to send play-pause"); + } + } + public override void next () { + debug("Next for user: %s", this.username); + + if (this.greeter != null) { + this.greeter.RequestSoundNext.begin(this.username, (obj, res) => { + try { + var broadcasts = (obj as GreeterBroadcast); + + if (broadcasts != null) + { + broadcasts.RequestSoundNext.end(res); + } + } catch (Error e) { + warning("Unable to send next: %s", e.message); + } + }); + } else { + warning("No unity-greeter-session-broadcast to send next"); + } + } + public override void previous () { + debug("Previous for user: %s", this.username); + + if (this.greeter != null) { + this.greeter.RequestSoundPrev.begin(this.username, (obj, res) => { + try { + var broadcasts = (obj as GreeterBroadcast); + + if (broadcasts != null) + { + broadcasts.RequestSoundPrev.end(res); + } + } catch (Error e) { + warning("Unable to send previous: %s", e.message); + } + }); + } else { + warning("No unity-greeter-session-broadcast to send previous"); + } + } + + /* Play list functions are all null as we don't support the + playlist feature on the greeter */ + public override uint get_n_playlists() { + return 0; + } + public override string get_playlist_id (int index) { + return ""; + } + public override string get_playlist_name (int index) { + return ""; + } + public override void activate_playlist_by_name (string playlist) { + } } |