aboutsummaryrefslogtreecommitdiff
path: root/src/media-player-user.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/media-player-user.vala')
-rw-r--r--src/media-player-user.vala239
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) {
+ }
+}