~indicator-applet-developers/indicator-sound/trunk.16.04

« back to all changes in this revision

Viewing changes to src/volume-control-pulse.vala

  • Committer: Xavi Garcia Mena
  • Date: 2016-02-23 12:48:46 UTC
  • mto: This revision was merged to the branch mainline in revision 530.
  • Revision ID: xavi.garcia.mena@canonical.com-20160223124846-kn4canososqd1sr2
Created new class AccountsServiceAccess to hold all accounts service operations

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
using Notify;
23
23
using Gee;
24
24
 
25
 
[DBus (name="com.canonical.UnityGreeter.List")]
26
 
interface GreeterListInterface : Object
27
 
{
28
 
        public abstract async string get_active_entry () throws IOError;
29
 
        public signal void entry_selected (string entry_name);
30
 
}
31
 
 
32
25
public class VolumeControlPulse : VolumeControl
33
26
{
34
27
        private unowned PulseAudio.GLibMainLoop loop = null;
55
48
        private string? _objp_role_phone = null;
56
49
        private uint _pa_volume_sig_count = 0;
57
50
 
58
 
        private DBusProxy _user_proxy;
59
 
        private GreeterListInterface _greeter_proxy;
60
 
        private Cancellable _mute_cancellable;
61
 
        private Cancellable _volume_cancellable;
62
 
        private Cancellable _last_running_player_cancellable;
63
51
        private uint _local_volume_timer = 0;
64
52
        private uint _accountservice_volume_timer = 0;
65
53
        private bool _send_next_local_volume = false;
66
54
        private double _account_service_volume = 0.0;
67
55
        private VolumeControl.ActiveOutput _active_output = VolumeControl.ActiveOutput.SPEAKERS;
68
 
        private string _last_running_player = "";
 
56
        private AccountsServiceAccess _accounts_service_access;
69
57
 
70
58
        /** true when a microphone is active **/
71
59
        public override bool active_mic { get; private set; default = false; }
72
60
 
73
 
        public override string last_running_player 
74
 
        { 
75
 
                get 
76
 
                { 
77
 
                        return _last_running_player; 
78
 
                } 
79
 
                set 
80
 
                { 
81
 
                        sync_last_running_player_to_accountsservice.begin (value);
82
 
                } 
83
 
        }
84
 
 
85
 
        public VolumeControlPulse (IndicatorSound.Options options, PulseAudio.GLibMainLoop loop)
 
61
        public VolumeControlPulse (IndicatorSound.Options options, PulseAudio.GLibMainLoop loop, AccountsServiceAccess? accounts_service_access)
86
62
        {
87
63
                base(options);
88
64
 
91
67
 
92
68
                this.loop = loop;
93
69
 
94
 
                _mute_cancellable = new Cancellable ();
95
 
                _volume_cancellable = new Cancellable ();
96
 
                _last_running_player_cancellable = new Cancellable();
97
 
 
98
 
                setup_accountsservice.begin ();
99
 
 
 
70
                _accounts_service_access = accounts_service_access;
 
71
                this._accounts_service_access.notify["volume"].connect(() => {
 
72
                        if (this._accounts_service_access.volume >= 0) {
 
73
                                _account_service_volume = this._accounts_service_access.volume;
 
74
                                // we need to wait for this to settle.
 
75
                                start_account_service_volume_timer();
 
76
                        }
 
77
                });
100
78
                this.reconnect_to_pulse ();
101
79
        }
102
80
 
552
530
        public override void set_mute (bool mute)
553
531
        {
554
532
                if (set_mute_internal (mute))
555
 
                        sync_mute_to_accountsservice.begin (mute);
 
533
                        _accounts_service_access.mute = mute;
556
534
        }
557
535
 
558
536
        public void toggle_mute ()
788
766
        }
789
767
 
790
768
        /* AccountsService operations */
791
 
        private void accountsservice_props_changed_cb (DBusProxy proxy, Variant changed_properties, string[]? invalidated_properties)
792
 
        {
793
 
                Variant volume_variant = changed_properties.lookup_value ("Volume", VariantType.DOUBLE);
794
 
                if (volume_variant != null) {
795
 
                        var volume = volume_variant.get_double ();
796
 
                        if (volume >= 0) {
797
 
                                _account_service_volume = volume;
798
 
                                // we need to wait for this to settle.
799
 
                                start_account_service_volume_timer();
800
 
                        }
801
 
                }
802
 
 
803
 
                Variant mute_variant = changed_properties.lookup_value ("Muted", VariantType.BOOLEAN);
804
 
                if (mute_variant != null) {
805
 
                        var mute = mute_variant.get_boolean ();
806
 
                        set_mute_internal (mute);
807
 
                }
808
 
 
809
 
                Variant last_running_player_variant = changed_properties.lookup_value ("LastRunningPlayer", VariantType.STRING);
810
 
                if (last_running_player_variant != null) {
811
 
                        var last_player = last_running_player_variant.get_string ();
812
 
                        _last_running_player = last_player;
813
 
                        this.notify_property("last-running-player");
814
 
                }
815
 
        }
816
 
 
817
 
        private async void setup_user_proxy (string? username_in = null)
818
 
        {
819
 
                var username = username_in;
820
 
                _user_proxy = null;
821
 
 
822
 
                // Look up currently selected greeter user, if asked
823
 
                if (username == null) {
824
 
                        try {
825
 
                                username = yield _greeter_proxy.get_active_entry ();
826
 
                                if (username == "" || username == null)
827
 
                                        return;
828
 
                        } catch (GLib.Error e) {
829
 
                                warning ("unable to find Accounts path for user %s: %s", username, e.message);
830
 
                                return;
831
 
                        }
832
 
                }
833
 
 
834
 
                // Get master AccountsService object
835
 
                DBusProxy accounts_proxy;
836
 
                try {
837
 
                        accounts_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.DO_NOT_LOAD_PROPERTIES | DBusProxyFlags.DO_NOT_CONNECT_SIGNALS, null, "org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts");
838
 
                } catch (GLib.Error e) {
839
 
                        warning ("unable to get greeter proxy: %s", e.message);
840
 
                        return;
841
 
                }
842
 
 
843
 
                // Find user's AccountsService object
844
 
                try {
845
 
                        var user_path_variant = yield accounts_proxy.call ("FindUserByName", new Variant ("(s)", username), DBusCallFlags.NONE, -1);
846
 
                        string user_path;
847
 
                        user_path_variant.get ("(o)", out user_path);
848
 
                        _user_proxy = yield DBusProxy.create_for_bus (BusType.SYSTEM, DBusProxyFlags.GET_INVALIDATED_PROPERTIES, null, "org.freedesktop.Accounts", user_path, "com.ubuntu.AccountsService.Sound");
849
 
                } catch (GLib.Error e) {
850
 
                        warning ("unable to find Accounts path for user %s: %s", username, e.message);
851
 
                        return;
852
 
                }
853
 
 
854
 
                // Get current values and listen for changes
855
 
                _user_proxy.g_properties_changed.connect (accountsservice_props_changed_cb);
856
 
                try {
857
 
                        var props_variant = yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "GetAll", new Variant ("(s)", _user_proxy.get_interface_name ()), null, DBusCallFlags.NONE, -1);
858
 
                        Variant props;
859
 
                        props_variant.get ("(@a{sv})", out props);
860
 
                        accountsservice_props_changed_cb(_user_proxy, props, null);
861
 
                } catch (GLib.Error e) {
862
 
                        debug("Unable to get properties for user %s at first try: %s", username, e.message);
863
 
                }
864
 
        }
865
 
 
866
 
        private void greeter_user_changed (string username)
867
 
        {
868
 
                setup_user_proxy.begin (username);
869
 
        }
870
 
 
871
 
        private async void setup_accountsservice ()
872
 
        {
873
 
                if (Environment.get_variable ("XDG_SESSION_CLASS") == "greeter") {
874
 
                        try {
875
 
                                _greeter_proxy = yield Bus.get_proxy (BusType.SESSION, "com.canonical.UnityGreeter", "/list");
876
 
                        } catch (GLib.Error e) {
877
 
                                warning ("unable to get greeter proxy: %s", e.message);
878
 
                                return;
879
 
                        }
880
 
                        _greeter_proxy.entry_selected.connect (greeter_user_changed);
881
 
                        yield setup_user_proxy ();
882
 
                } else {
883
 
                        // We are in a user session.  We just need our own proxy
884
 
                        unowned string username = Environment.get_variable ("USER");
885
 
                        if (username != "" && username != null) {
886
 
                                yield setup_user_proxy (username);
887
 
                        }
888
 
                }
889
 
        }
890
 
 
891
 
        private async void sync_mute_to_accountsservice (bool mute)
892
 
        {
893
 
                if (_user_proxy == null)
894
 
                        return;
895
 
 
896
 
                _mute_cancellable.cancel ();
897
 
                _mute_cancellable.reset ();
898
 
 
899
 
                try {
900
 
                        yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Muted", new Variant ("b", mute)), null, DBusCallFlags.NONE, -1, _mute_cancellable);
901
 
                } catch (GLib.Error e) {
902
 
                        warning ("unable to sync mute to AccountsService: %s", e.message);
903
 
                }
904
 
        }
905
 
 
906
 
        private async void sync_last_running_player_to_accountsservice (string last_running_player)
907
 
        {
908
 
                if (_user_proxy == null)
909
 
                        return;
910
 
 
911
 
                _last_running_player_cancellable.cancel ();
912
 
                _last_running_player_cancellable.reset ();
913
 
 
914
 
                try {
915
 
                        yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "LastRunningPlayer", new Variant ("s", last_running_player)), null, DBusCallFlags.NONE, -1, _last_running_player_cancellable);
916
 
                } catch (GLib.Error e) {
917
 
                        warning ("unable to sync last running player to AccountsService: %s", e.message);
918
 
                }
919
 
                _last_running_player = last_running_player;
920
 
        }
921
 
 
922
 
        private async void sync_volume_to_accountsservice (VolumeControl.Volume volume)
923
 
        {
924
 
                if (_user_proxy == null)
925
 
                        return;
926
 
 
927
 
                _volume_cancellable.cancel ();
928
 
                _volume_cancellable.reset ();
929
 
 
930
 
                warning("Interface name: %s", _user_proxy.get_interface_name ());
931
 
                try {
932
 
                        yield _user_proxy.get_connection ().call (_user_proxy.get_name (), _user_proxy.get_object_path (), "org.freedesktop.DBus.Properties", "Set", new Variant ("(ssv)", _user_proxy.get_interface_name (), "Volume", new Variant ("d", volume.volume)), null, DBusCallFlags.NONE, -1, _volume_cancellable);
933
 
                } catch (GLib.Error e) {
934
 
                        warning ("unable to sync volume to AccountsService: %s", e.message);
935
 
                }
936
 
        }
937
769
 
938
770
        private void start_local_volume_timer()
939
771
        {
943
775
                stop_account_service_volume_timer();
944
776
 
945
777
                if (_local_volume_timer == 0) {
946
 
                        sync_volume_to_accountsservice.begin (_volume);
 
778
                        _accounts_service_access.volume = _volume.volume;
947
779
                        _local_volume_timer = Timeout.add_seconds (1, local_volume_changed_timeout);
948
780
                } else {
949
781
                        _send_next_local_volume = true;