diff options
Diffstat (limited to 'src/media-player-user.vala')
-rw-r--r-- | src/media-player-user.vala | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/src/media-player-user.vala b/src/media-player-user.vala new file mode 100644 index 0000000..dfe6229 --- /dev/null +++ b/src/media-player-user.vala @@ -0,0 +1,239 @@ +/* + * Copyright © 2014 Canonical Ltd. + * + * 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 + * the Free Software Foundation; version 3. + * + * 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Ted Gould <ted@canonical.com> + */ + +public class MediaPlayerUser : MediaPlayer { + Act.UserManager accounts_manager = Act.UserManager.get_default(); + string username; + Act.User? actuser = null; + AccountsServiceSoundSettings? proxy = 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); + }); + } + + ~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(); + + /* Remove source */ + return false; + } + + /* 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; + return name_cache; + } else { + return ""; + } + } + } + string state_cache; + public override string state { + get { + if (proxy_is_valid()) { + state_cache = this.proxy.state; + 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 { } + } + + /* Control functions through unity-greeter-session-broadcast */ + public override void activate () { + /* TODO: */ + } + public override void play_pause () { + /* TODO: */ + } + public override void next () { + /* TODO: */ + } + public override void previous () { + /* TODO: */ + } + + /* 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) { + } +} |