Skip to content
Snippets Groups Projects
Select Git revision
  • master default
1 result

DeviceManager.vala

Blame
    • gyan000's avatar
      9312067d
      GH-3 - Stop auto-pairing. · 9312067d
      gyan000 authored
      * Now we have to use the main switch button to start a pairing.
      * If device is unpaired from mobile device, switch button now turn off.
      * If device was unpaired when EOSConnect was not active, switch button 
      is off.
      9312067d
      History
      GH-3 - Stop auto-pairing.
      gyan000 authored
      * Now we have to use the main switch button to start a pairing.
      * If device is unpaired from mobile device, switch button now turn off.
      * If device was unpaired when EOSConnect was not active, switch button 
      is off.
    DeviceManager.vala 10.96 KiB
    /**
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License version 2 as
     * published by the Free Software Foundation.
     *
     * 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, write to the Free Software Foundation, Inc.,
     * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * AUTHORS
     * Maciek Borzecki <maciek.borzecki (at] gmail.com>
     * gyan000 <gyan000 (at] ijaz.fr>
     */
    using Gee;
    using EOSConnect;
    
    namespace MConnect {
    
        public class DeviceManager : GLib.Object {
    
            public signal void found_new_device (Device dev);
            public signal void device_connected (Device dev);
            public signal void device_deconnected (Device dev);
            public signal void device_pair_changed (Device dev);
            public signal void device_capability_added (Device dev, string capability, PacketHandlerInterface handler);
    
            public const string DEVICES_CACHE_FILE = "devices";
    
            public DeviceManager () {
                debug ("Device manager.");
                var notification_monitor = new NotificationMonitor ();
                notification_monitor.notification_received.connect (on_local_notification_received);
                notification_monitor.notification_closed.connect (on_local_notification_closed);
            }
    
            /**
             * Obtain path to devices cache file
             */
            private string get_cache_file () {
                var cache_file = Path.build_filename (Core.get_cache_dir (), DEVICES_CACHE_FILE);
                debug ("Cache file: %s", cache_file);
    
                // make sure that cache dir exists
                DirUtils.create_with_parents (Core.get_cache_dir (), 0700);
    
                return cache_file;
            }
    
            /**
             * Load known devices from cache and attempt pairing.
             */
            public void load_cache () {
                var cache_file = this.get_cache_file ();
    
                debug ("Try loading devices from device cache %s", cache_file);
    
                var kf = new KeyFile ();
                try {
                    kf.load_from_file (cache_file, KeyFileFlags.NONE);
    
                    string[] groups = kf.get_groups ();
    
                    foreach (string group in groups) {
                        var dev = Device.new_from_cache (kf, group);
                        if (dev != null) {
                            debug ("device %s from cache", dev.to_string ());
                            handle_device (dev);
                        }
                    }
                } catch (Error e) {
                    debug ("Error loading cache file: %s", e.message);
                }
            }
    
            public void handle_discovered_device (DiscoveredDevice discovered_dev) {
                debug ("Found device: %s", discovered_dev.to_string ());
                var new_dev = new Device.from_discovered_device (discovered_dev);
                handle_device (new_dev);
            }
    
            public void handle_device (Device new_dev) {
                try {
                    var is_new = false;
                    string unique = new_dev.to_unique_string ();
                    debug ("Device key: %s", unique);
    
                    if (Core.instance ().devices_map.has_key (unique) == false) {
                        debug ("Adding new device with key: %s", unique);
                        Core.instance ().devices_map.@set (unique, new_dev);
                        is_new = true;
                    } else {
                        debug ("Device %s already present", unique);
                        this.device_connected (Core.instance ().devices_map.@get (unique));
                    }
    
                    var dev = Core.instance ().devices_map.@get (unique);
    
                    // Notify everyone that a new device appeared
                    if (is_new) {
                        // Make sure that this happens before we update device data so that
                        // all subscribeds of found_new_device() signal have a chance to
                        // setup eveything they need.
                        this.found_new_device (dev);
                        dev.capability_added.connect (this.device_capability_added_cb);
                        dev.capability_removed.connect (this.device_capability_removed_cb);
                    }
    
                    // Update device information
                    dev.update_from_device (new_dev);
    
                    debug ("Allowed? %s", dev.allowed.to_string ());
                    // check if device is whitelisted in configuration
                    if (!dev.allowed && device_allowed_in_config (dev)) {
                        dev.allowed = true;
                    }
    
                    this.update_cache ();
    
                    if (dev.allowed) {
                        this.activate_device (dev);
                    } else {
                        warning ("Skipping device %s activation, device not allowed", dev.to_string ());
                    }
                }
                catch (Error e) {
                    warning ("Error: %s", e.message);
                }
            }
    
            /**
             * allow_device:
             * @path: device object path
             *
             * Allow given device
             */
            public void allow_device (Device dev) {
                dev.allowed = true;
                update_cache ();
                activate_device (dev);
            }
    
            /**
             * disallow_device:
             * @path: device object path
             *
             * Disallow given device
             */
            public void disallow_device (Device dev) {
                dev.allowed = false;
                update_cache ();
            }
    
            private void on_local_notification_received (DBusMessage message, uint32 id) {
                try {
                    var notification = new Notification.from_message (message, id);
                    if (!notification.get_is_valid () || notification.app_name in Notification.EXCEPTIONS) {
                        return;
                    }
    
                    foreach (Device device in Core.instance ().devices_map.values) {
                        if (device.has_capability_handler (NotificationHandler.NOTIFICATION)) {
                            NotificationHandler notification_handler = (NotificationHandler)device.get_path_capability_handler(
                                NotificationHandler.NOTIFICATION);
    
                            notification_handler.send_notification (device, message, id);
                        }
                    }
                } catch (Error e) {
                    warning ("Error: %s", e.message);
                }
            }
    
            private void on_local_notification_closed (Notification notification) {
                try {
    
                    print ("\n>>%S\n", notification.id);
    
                    // var notification = new Notification.from_message (message, id);
                    // Core.instance ().application.withdraw_notification (notification_id);
    
                    // if (!notification.get_is_valid () || notification.app_name in Notification.EXCEPTIONS) {
                    //     return;
                    // }
                    //
                    // foreach (Device device in Core.instance ().devices_map.values) {
                    //     if (device.has_capability_handler (NotificationHandler.NOTIFICATION)) {
                    //         NotificationHandler notification_handler = (NotificationHandler)device.get_path_capability_handler(
                    //             NotificationHandler.NOTIFICATION);
                    //
                    //         notification_handler.send_notification (device, message, id);
                    //     }
                    // }
                } catch (Error e) {
                    warning ("Error: %s", e.message);
                }
            }
    
            /**
             * Update contents of device cache
             */
            private void update_cache () {
                try {
                    if (Core.instance ().devices_map.size == 0)
                        return;
    
                    var kf = new KeyFile ();
    
                    foreach (var dev in Core.instance ().devices_map.values) {
                        dev.to_cache (kf, dev.name);
                    }
    
                    debug("Saving to cache.");
                    FileUtils.set_contents (get_cache_file (), kf.to_data ());
                } catch (FileError e) {
                    warning ("Failed to save to cache file %s: %s", get_cache_file (), e.message);
                } catch (Error e) {
                    warning ("Error: %s", e.message);
                }
            }
    
            private void activate_device (Device dev) {
                info ("Activating device %s, active: %s", dev.to_string (), dev.is_active.to_string ());
    
                if (!dev.is_active) {
                    dev.paired.connect (this.device_paired);
                    dev.disconnected.connect (this.device_disconnected);
                    dev.activate ();
                }
            }
    
            /**
             * device_allowed_in_config:
             * @dev device
             *
             * Returns true if a matching device is enabled via configuration file.
             */
            private bool device_allowed_in_config (Device dev) throws Error {
                if (dev.allowed)
                    return true;
    
                // var core = Core.instance ();
    
                // var in_config = core.config.is_device_allowed (dev.name, dev.device_type);
                // return in_config;
                return true;
            }
    
            private void device_paired (Device dev, bool status) {
                info ("Device %s pair status change: %s", dev.to_string (), status.to_string ());
    
                update_cache ();
    
                if (status == false) {
                    // we're no longer interested in paired signal
                    dev.paired.disconnect (this.device_paired);
                    // we're not paired anymore, deactivate if needed
                    dev.deactivate ();
                }
    
                device_pair_changed (dev);
            }
    
            private void device_capability_added_cb (Device dev, string cap) {
                try {
                    info ("Capability %s added to device %s", cap, dev.to_string ());
    
                    if (dev.has_capability_handler (cap)) {
                        return;
                    }
    
                    var core = Core.instance ();
                    var h = core.handlers.get_capability_handler (cap);
                    if (h != null) {
                        dev.register_capability_handler (cap, h);
                        device_capability_added (dev, cap, h);
                    } else {
                        warning ("No handler for capability %s", cap);
                    }
                }
                catch (Error e) {
                    warning ("Error: %s", e.message);
                }
            }
    
            private void device_capability_removed_cb (Device dev, string cap) {
                info ("Capability %s removed from device %s", cap, dev.to_string ());
            }
    
            private void device_disconnected (Device dev) {
                debug ("Device %s got disconnected", dev.to_string ());
    
                dev.paired.disconnect (this.device_paired);
                dev.disconnected.disconnect (this.device_disconnected);
                device_deconnected (dev);
            }
        }
    }