From 947a9f7d10bc3c54939cfa72dab27b2e64034318 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 11:33:33 +0200 Subject: Create packet. --- parrot_zik/__init__.py | 0 parrot_zik/bluetooth_paired_devices.py | 107 ++++++++ parrot_zik/indicator.py | 254 ++++++++++++++++++ parrot_zik/message.py | 30 +++ parrot_zik/parrot_zik_model.py | 222 ++++++++++++++++ parrot_zik/parrot_zik_tray | 472 +++++++++++++++++++++++++++++++++ parrot_zik/resource_manager.py | 176 ++++++++++++ parrot_zik/status_app_mac.py | 25 ++ 8 files changed, 1286 insertions(+) create mode 100644 parrot_zik/__init__.py create mode 100644 parrot_zik/bluetooth_paired_devices.py create mode 100644 parrot_zik/indicator.py create mode 100644 parrot_zik/message.py create mode 100644 parrot_zik/parrot_zik_model.py create mode 100755 parrot_zik/parrot_zik_tray create mode 100644 parrot_zik/resource_manager.py create mode 100644 parrot_zik/status_app_mac.py (limited to 'parrot_zik') diff --git a/parrot_zik/__init__.py b/parrot_zik/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py new file mode 100644 index 0000000..eb1ec09 --- /dev/null +++ b/parrot_zik/bluetooth_paired_devices.py @@ -0,0 +1,107 @@ +import sys +import re +import os + +from parrot_zik.resource_manager import GenericResourceManager + +if sys.platform == "darwin": + from binplist import binplist + import lightblue +else: + import bluetooth + if sys.platform == "win32": + import _winreg + + +def get_parrot_zik_mac(): + p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}|' + 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') + if sys.platform == "linux2": + bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) + if bluetooth_on == 1: + out = os.popen("bluez-test-device list").read() + res = p.findall(out) + if len(res) > 0: + return res[0] + else: + raise DeviceNotConnected + else: + raise BluetoothIsNotOn + elif sys.platform == "darwin": + fd = open("/Library/Preferences/com.apple.Bluetooth.plist", "rb") + plist = binplist.BinaryPlist(file_obj=fd) + parsed_plist = plist.Parse() + try: + for mac in parsed_plist['PairedDevices']: + if p.match(mac.replace("-", ":")): + return mac.replace("-", ":") + else: + raise DeviceNotConnected + except Exception: + pass + + elif sys.platform == "win32": + aReg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + aKey = _winreg.OpenKey( + aReg, 'SYSTEM\CurrentControlSet\Services\ + BTHPORT\Parameters\Devices') + for i in range(10): + try: + asubkey_name = _winreg.EnumKey(aKey, i) + mac = ':'.join(asubkey_name[i:i+2] for i in range(0, 12, 2)) + res = p.findall(mac) + if len(res) > 0: + return res[0] + else: + raise DeviceNotConnected + except EnvironmentError: + pass + + +def connect(): + mac = get_parrot_zik_mac() + if sys.platform == "darwin": + service_matches = lightblue.findservices( + name="Parrot RFcomm service", addr=mac) + else: + uuids = ["0ef0f502-f0ee-46c9-986c-54ed027807fb", + "8B6814D3-6CE7-4498-9700-9312C1711F63"] + service_matches = [] + for uuid in uuids: + try: + service_matches = bluetooth.find_service(uuid=uuid, address=mac) + except bluetooth.btcommon.BluetoothError: + pass + if service_matches: + break + + if len(service_matches) == 0: + raise ConnectionFailure + first_match = service_matches[0] + + if sys.platform == "darwin": + host = first_match[0] + port = first_match[1] + sock = lightblue.socket() + else: + port = first_match["port"] + host = first_match["host"] + sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) + + sock.connect((host, port)) + + sock.send('\x00\x03\x00') + sock.recv(1024) + return GenericResourceManager(sock) + + +class DeviceNotConnected(Exception): + pass + + +class ConnectionFailure(Exception): + pass + + +class BluetoothIsNotOn(Exception): + pass diff --git a/parrot_zik/indicator.py b/parrot_zik/indicator.py new file mode 100644 index 0000000..2691113 --- /dev/null +++ b/parrot_zik/indicator.py @@ -0,0 +1,254 @@ +#!/usr/bin/env python + +import sys +import os +import tempfile + +if sys.platform == "linux2" or sys.platform == "win32": + import gtk +elif sys.platform == "darwin": + from Foundation import * + from AppKit import * + from PyObjCTools import AppHelper + from status_app_mac import StatusApp + + +class BaseIndicator(object): + def __init__(self, icon, menu, statusicon): + self.menu = menu + self.statusicon = statusicon + self.setIcon(icon) + + def gtk_right_click_event(self, icon, button, time): + if not self.menu_shown: + self.menu_shown = True + self.menu.popup(None, None, gtk.status_icon_position_menu, + button, time, self.statusicon) + else: + self.menu_shown = False + self.menu.popdown() + + def setIcon(self, name): + raise NotImplementedError + + def main(self): + raise NotImplementedError + + def show_about_dialog(self, widget): + raise NotImplementedError + + +class WindowsIndicator(BaseIndicator): + def __init__(self, icon, menu): + self.icon_directory = ( + os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep + '..' + + os.path.sep + 'share' + os.path.sep + 'icons' + + os.path.sep +'zik' + os.path.sep) + self.menu_shown = False + sys.stdout = open(tempfile.gettempdir() + + os.path.sep + "zik_tray_stdout.log", "w") + sys.stderr = open(tempfile.gettempdir() + + os.path.sep + "zik_tray_stderr.log", "w") + statusicon = gtk.StatusIcon() + statusicon.connect("popup-menu", self.gtk_right_click_event) + statusicon.set_tooltip("Parrot Zik") + super(WindowsIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.set_from_file(self.icon_directory + name + '.png') + + def main(self): + gtk.main() + + def show_about_dialog(self, widget): + about_dialog = gtk.AboutDialog() + about_dialog.set_destroy_with_parent(True) + about_dialog.set_name("Parrot Zik Tray") + about_dialog.set_version("0.3") + about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) + about_dialog.run() + about_dialog.destroy() + + +class LinuxIndicator(BaseIndicator): + def __init__(self, icon, menu): + import appindicator + self.icon_directory = (os.path.sep + 'usr' + os.path.sep + 'share' + + os.path.sep + 'icons' + os.path.sep+'zik' + + os.path.sep) + if not os.path.isdir(self.icon_directory): + self.icon_directory = (os.path.dirname(sys.argv[0]) + os.path.sep + '..' + + os.path.sep + 'share' + os.path.sep + + 'icons' + os.path.sep+'zik' + + os.path.sep) + statusicon = appindicator.Indicator( + "new-parrotzik-indicator", "indicator-messages", + appindicator.CATEGORY_APPLICATION_STATUS) + statusicon.set_status(appindicator.STATUS_ACTIVE) + statusicon.set_icon_theme_path(self.icon_directory) + statusicon.set_menu(menu.gtk_menu) + super(LinuxIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.set_icon(name) + + def main(self): + gtk.main() + + def show_about_dialog(self, widget): + about_dialog = gtk.AboutDialog() + about_dialog.set_destroy_with_parent(True) + about_dialog.set_name("Parrot Zik Tray") + about_dialog.set_version("0.3") + about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) + about_dialog.run() + about_dialog.destroy() + + +class DarwinIndicator(BaseIndicator): + def __init__(self, icon, menu): + self.icon_directory = ( + os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep + '..' + os.path.sep + + 'share' + os.path.sep + 'icons' + os.path.sep + 'zik' + + os.path.sep) + statusicon = StatusApp.sharedApplication() + statusicon.initMenu(menu) + super(DarwinIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.setIcon(name, self.icon_directory) + + def main(self): + AppHelper.runEventLoop() + + def show_about_dialog(self, widget): + pass + + +class NSMenu(object): + def __init__(self): + self.actions = {} + self.menubarMenu = NSMenu.alloc().init() + self.menubarMenu.setAutoenablesItems_(False) + + def append(self, menu_item): + self.actions[menu_item.title] = menu_item.action + self.menubarMenu.addItem_(menu_item.nsmenu_item) + + def reposition(self): + # TODO + pass + +class GTKMenu(object): + def __init__(self): + self.gtk_menu = gtk.Menu() + + def append(self, menu_item): + self.gtk_menu.append(menu_item.base_item) + + def reposition(self): + self.gtk_menu.reposition() + + +class MenuItemBase(object): + def __init__(self, base_item, sensitive, visible): + self.base_item = base_item + self.set_sensitive(sensitive) + if visible: + self.show() + else: + self.hide() + + def set_sensitive(self, option): + raise NotImplementedError + + def set_active(self, option): + raise NotImplementedError + + def get_active(self): + raise NotImplementedError + + def set_label(self, option): + raise NotImplementedError + + def show(self): + self.base_item.show() + + def hide(self): + self.base_item.hide() + + def set_submenu(self, menu): + raise NotImplementedError + +class GTKMenuItem(MenuItemBase): + def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): + if checkitem: + gtk_item = gtk.CheckMenuItem(name) + else: + gtk_item = gtk.MenuItem(name) + if action: + gtk_item.connect("activate", action) + super(GTKMenuItem, self).__init__(gtk_item, sensitive, visible) + + def set_sensitive(self, option): + return self.base_item.set_sensitive(option) + + def set_active(self, option): + return self.base_item.set_active(option) + + def get_active(self): + return self.base_item.get_active() + + def set_label(self, option): + return self.base_item.set_label(option) + + def set_submenu(self, menu): + self.base_item.set_submenu(menu.gtk_menu) + + +class NSMenuItem(MenuItemBase): + def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): + self.title = name + self.action = action + nsmenu_item = ( + NSMenuItem.alloc().initWithTitle_action_keyEquivalent_( + name, 'clicked:', '')) + super(NSMenuItem, self).__init__(nsmenu_item, sensitive, visible) + + def set_sensitive(self, option): + self.base_item.setEnabled_(option) + + def set_active(self, option): + self.base_item.setState_(option) + + def get_active(self): + return self.base_item.state + + def set_label(self, option): + self.title = option + self.base_item.setTitle_(option) + +if sys.platform == 'linux2': + SysIndicator = LinuxIndicator + Menu = GTKMenu + MenuItem = GTKMenuItem +elif sys.platform == 'win32': + SysIndicator = WindowsIndicator + Menu = GTKMenu + MenuItem = GTKMenuItem +elif sys.platform == 'darwin': + SysIndicator = DarwinIndicator + Menu = NSMenu + MenuItem = NSMenuItem +else: + raise Exception('Platform not supported') + +if __name__ == "__main__": + + quit_item = MenuItem("Quit", sys.exit, True) + + menu = Menu() + menu.append(quit_item) + + indicator = SysIndicator(icon="zik-audio-headset", menu=menu) + indicator.main() diff --git a/parrot_zik/message.py b/parrot_zik/message.py new file mode 100644 index 0000000..214b6f9 --- /dev/null +++ b/parrot_zik/message.py @@ -0,0 +1,30 @@ +class Message: + def __init__(self, resource, method, arg=None): + self.method = method + self.resource = resource + self.arg = arg + + def __str__(self): + return str(self.request) + + @property + def request(self): + message = bytearray() + message.extend(self.header) + message.extend(bytearray(self.request_string)) + return message + + @property + def header(self): + header = bytearray([0]) + header.append(len(self.request_string) + 3) + header.append("\x80") + return header + + @property + def request_string(self): + if self.method == 'set': + return 'SET {}/{}?arg={}'.format(self.resource, self.method, + str(self.arg).lower()) + else: + return 'GET {}/{}'.format(self.resource, self.method) diff --git a/parrot_zik/parrot_zik_model.py b/parrot_zik/parrot_zik_model.py new file mode 100644 index 0000000..e15200f --- /dev/null +++ b/parrot_zik/parrot_zik_model.py @@ -0,0 +1,222 @@ +from parrot_zik.resource_manager import Version1ResourceManager +from parrot_zik.resource_manager import Version2ResourceManager + + +class BatteryStates: + CHARGED = 'charged' + IN_USE = 'in_use' + CHARGING = 'charging' + representation = { + CHARGED: 'Charged', + IN_USE: 'In Use', + CHARGING: 'Charging', + } + +class Rooms: + CONCERT_HALL = 'concert' + JAZZ_CLUB = 'jazz' + LIVING_ROOM = 'living' + SILENT_ROOM = 'silent' + representation = { + CONCERT_HALL: 'Concert Hall', + JAZZ_CLUB: 'Jazz Club', + LIVING_ROOM: 'Living Room', + SILENT_ROOM: 'Silent Room', + } + +class NoiseControl(object): + def __init__(self, type, value): + self.type = type + self.value = value + + @classmethod + def from_noise_control(cls, noise_control): + return cls(noise_control['type'], int(noise_control['value'])) + + def __eq__(self, other): + return self.type == other.type and self.value == other.value + + def __str__(self): + return '{}++{}'.format(self.type, self.value) + +class NoiseControlTypes: + NOISE_CONTROL_MAX = NoiseControl('anc', 2) + NOISE_CONTROL_ON = NoiseControl('anc', 1) + NOISE_CONTROL_OFF = NoiseControl('off', 1) + STREET_MODE = NoiseControl('aoc', 1) + STREET_MODE_MAX = NoiseControl('aoc', 2) + + +class ParrotZikBase(object): + def __init__(self, resource_manager): + self.resource_manager = resource_manager + + @property + def version(self): + return self.resource_manager.api_version + + def refresh_battery(self): + self.resource_manager.fetch('/api/system/battery') + + @property + def battery_state(self): + answer = self.resource_manager.get("/api/system/battery") + return answer.system.battery["state"] + + def get_battery_level(self, field_name): + answer = self.resource_manager.get("/api/system/battery") + return int(answer.system.battery[field_name]) + + @property + def friendly_name(self): + answer = self.resource_manager.get("/api/bluetooth/friendlyname") + return answer.bluetooth["friendlyname"] + + @property + def auto_connect(self): + answer = self.resource_manager.get("/api/system/auto_connection/enabled") + return self._result_to_bool( + answer.system.auto_connection["enabled"]) + + @auto_connect.setter + def auto_connect(self, arg): + self.resource_manager.set("/api/system/auto_connection/enabled", arg) + + @property + def anc_phone_mode(self): + answer = self.resource_manager.get("/api/system/anc_phone_mode/enabled") + return self._result_to_bool( + answer.system.anc_phone_mode["enabled"]) + + def _result_to_bool(self, result): + if result == "true": + return True + elif result == "false": + return False + else: + raise AssertionError(result) + + +class ParrotZikVersion1(ParrotZikBase): + def __init__(self, resource_manager): + super(ParrotZikVersion1, self).__init__( + resource_manager.get_resource_manager( + Version1ResourceManager)) + + @property + def version(self): + answer = self.resource_manager.get('/api/software/version') + return answer.software['version'] + + @property + def battery_level(self): + return int(self.get_battery_level('level')) + + @property + def lou_reed_mode(self): + answer = self.resource_manager.get("/api/audio/specific_mode/enabled") + return self._result_to_bool( + answer.audio.specific_mode["enabled"]) + + @lou_reed_mode.setter + def lou_reed_mode(self, arg): + self.resource_manager.get("/api/audio/specific_mode/enabled", arg) + + @property + def concert_hall(self): + answer = self.resource_manager.get("/api/audio/sound_effect/enabled") + return self._result_to_bool( + answer.audio.sound_effect["enabled"]) + + @concert_hall.setter + def concert_hall(self, arg): + self.resource_manager.get("/api/audio/sound_effect/enabled", arg) + + @property + def cancel_noise(self): + answer = self.resource_manager.get("/api/audio/noise_cancellation/enabled") + return self._result_to_bool( + answer.audio.noise_cancellation["enabled"]) + + @cancel_noise.setter + def cancel_noise(self, arg): + self.resource_manager.set("/api/audio/noise_cancellation/enabled", arg) + + +class ParrotZikVersion2(ParrotZikBase): + def __init__(self, resource_manager): + super(ParrotZikVersion2, self).__init__( + resource_manager.get_resource_manager( + Version2ResourceManager)) + + @property + def version(self): + answer = self.resource_manager.get('/api/software/version') + return answer.software['sip6'] + + @property + def battery_level(self): + return self.get_battery_level('percent') + + @property + def flight_mode(self): + answer = self.resource_manager.get('/api/flight_mode') + return self._result_to_bool(answer.flight_mode['enabled']) + + @flight_mode.setter + def flight_mode(self, arg): + if arg: + self.resource_manager.toggle_on('/api/flight_mode') + else: + self.resource_manager.toggle_off('/api/flight_mode') + + @property + def sound_effect(self): + answer = self.resource_manager.get('/api/audio/sound_effect/enabled') + return self._result_to_bool(answer.audio.sound_effect['enabled']) + + @sound_effect.setter + def sound_effect(self, arg): + self.resource_manager.set('/api/audio/sound_effect/enabled', arg) + + @property + def room(self): + answer = self.resource_manager.get('/api/audio/sound_effect/room_size') + return answer.audio.sound_effect['room_size'] + + @room.setter + def room(self, arg): + self.resource_manager.set('/api/audio/sound_effect/room_size', arg) + + @property + def external_noise(self): + answer = self.resource_manager.get('/api/audio/noise') + return int(answer.audio.noise['external']) + + @property + def internal_noise(self): + answer = self.resource_manager.get('/api/audio/noise') + return int(answer.audio.noise['internal']) + + @property + def angle(self): + answer = self.resource_manager.get('/api/audio/sound_effect/angle') + return int(answer.audio.sound_effect['angle']) + + @angle.setter + def angle(self, arg): + self.resource_manager.set('/api/audio/sound_effect/angle', arg) + + @property + def noise_control(self): + answer = self.resource_manager.get('/api/audio/noise_control') + return NoiseControl.from_noise_control(answer.audio.noise_control) + + @noise_control.setter + def noise_control(self, arg): + pass + + @property + def noise_control_enabled(self): + answer = self.resource_manager.get('/api/audio/noise_control/enabled') + return self._result_to_bool(answer.audio.noise_control['enabled']) diff --git a/parrot_zik/parrot_zik_tray b/parrot_zik/parrot_zik_tray new file mode 100755 index 0000000..dcdacd0 --- /dev/null +++ b/parrot_zik/parrot_zik_tray @@ -0,0 +1,472 @@ +#!/usr/bin/env python +import functools +from threading import Lock +import gtk + +from parrot_zik import resource_manager +from parrot_zik import bluetooth_paired_devices +from parrot_zik.parrot_zik_model import BatteryStates +from parrot_zik.parrot_zik_model import ParrotZikVersion1 +from parrot_zik.parrot_zik_model import ParrotZikVersion2 +from parrot_zik.parrot_zik_model import NoiseControlTypes +from parrot_zik.parrot_zik_model import Rooms +from parrot_zik.indicator import MenuItem +from parrot_zik.indicator import Menu +from parrot_zik.indicator import SysIndicator + +REFRESH_FREQUENCY = 30000 +RECONNECT_FREQUENCY = 5000 + + +class repeat(object): + def __init__(self, f): + self.f = f + self.id = None + self.lock = Lock() + + def __call__(self, cls): + self.f(cls) + + def start(self, cls, frequency): + self.lock.acquire() + if not self.id: + def run(): + self.f(cls) + return True + + self.id = gtk.timeout_add(frequency, run) + self.lock.release() + + def stop(self): + self.lock.acquire() + if self.id: + gtk.timeout_remove(self.id) + self.id = None + self.lock.release() + + +class ParrotZikIndicator(SysIndicator): + def __init__(self): + + self.menu = Menu() + + self.info_item = MenuItem("Parrot Zik Not connected", + None, sensitive=False) + self.menu.append(self.info_item) + + self.version_1_interface = ParrotZikVersion1Interface(self) + self.version_2_interface = ParrotZikVersion2Interface(self) + self.quit = MenuItem("Quit", gtk.main_quit, checkitem=True) + self.menu.append(self.quit) + + SysIndicator.__init__(self, icon="zik-audio-headset", menu=self.menu) + + self.active_interface = None + + @repeat + def reconnect(self): + if self.active_interface: + self.reconnect.stop() + else: + self.info("Trying to connect") + try: + manager = bluetooth_paired_devices.connect() + except bluetooth_paired_devices.BluetoothIsNotOn: + self.info("Bluetooth is turned off") + except bluetooth_paired_devices.DeviceNotConnected: + self.info("Parrot Zik Not connected") + except bluetooth_paired_devices.ConnectionFailure: + self.info("Failed to connect") + else: + if manager.api_version.startswith('1'): + interface = self.version_1_interface + else: + interface = self.version_2_interface + try: + interface.activate(manager) + except resource_manager.DeviceDisconnected: + interface.deactivate() + else: + self.autorefresh(self) + self.autorefresh.start(self, REFRESH_FREQUENCY) + self.reconnect.stop() + + def info(self, message): + self.info_item.set_label(message) + print(message) + + @repeat + def autorefresh(self): + if self.active_interface: + self.active_interface.refresh() + else: + self.reconnect.start(self, RECONNECT_FREQUENCY) + self.autorefresh.stop() + + def main(self): + self.reconnect.start(self, RECONNECT_FREQUENCY) + SysIndicator.main(self) + +class ParrotZikBaseInterface(object): + def __init__(self, indicator): + self.indicator = indicator + self.parrot = None + self.battery_level = MenuItem("Battery Level:", None, sensitive=False, + visible=False) + self.battery_state = MenuItem("Battery State:", None, sensitive=False, + visible=False) + self.firmware_version = MenuItem("Firmware Version:", None, + sensitive=False, visible=False) + self.auto_connection = MenuItem("Auto Connection", self.toggle_auto_connection, + checkitem=True, visible=False) + self.indicator.menu.append(self.battery_level) + self.indicator.menu.append(self.battery_state) + self.indicator.menu.append(self.firmware_version) + self.indicator.menu.append(self.auto_connection) + + def activate(self, manager): + self.parrot = self.parrot_class(manager) + self.read_battery() + self.indicator.info("Connected to: " + self.parrot.friendly_name) + self.firmware_version.set_label( + "Firmware version: " + self.parrot.version) + self.auto_connection.set_active(self.parrot.auto_connect) + self.battery_level.show() + self.battery_state.show() + self.firmware_version.show() + self.auto_connection.show() + self.indicator.active_interface = self + self.indicator.menu.reposition() + + @property + def parrot_class(self): + raise NotImplementedError + + def deactivate(self): + self.parrot = None + self.battery_level.hide() + self.battery_state.hide() + self.firmware_version.hide() + self.auto_connection.hide() + self.indicator.menu.reposition() + self.indicator.active_interface = None + self.indicator.setIcon("zik-audio-headset") + self.indicator.info('Lost Connection') + self.indicator.reconnect.start(self.indicator, RECONNECT_FREQUENCY) + + def toggle_auto_connection(self, widget): + try: + self.parrot.auto_connect = self.auto_connection.get_active() + self.auto_connection.set_active(self.parrot.auto_connect) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def refresh(self): + self.read_battery() + + def read_battery(self): + try: + self.parrot.refresh_battery() + battery_level = self.parrot.battery_level + battery_state = self.parrot.battery_state + except resource_manager.DeviceDisconnected: + self.deactivate() + else: + if battery_state == BatteryStates.CHARGING: + self.indicator.setIcon("zik-battery-charging") + elif battery_level > 80: + self.indicator.setIcon("zik-battery-100") + elif battery_level > 60: + self.indicator.setIcon("zik-battery-080") + elif battery_level > 40: + self.indicator.setIcon("zik-battery-060") + elif battery_level > 20: + self.indicator.setIcon("zik-battery-040") + else: + self.indicator.setIcon("zik-battery-low") + + self.battery_state.set_label( + "State: " + BatteryStates.representation[battery_state]) + self.battery_level.set_label( + "Battery Level: " + str(battery_level)) + + +class ParrotZikVersion1Interface(ParrotZikBaseInterface): + parrot_class = ParrotZikVersion1 + + def __init__(self, indicator): + super(ParrotZikVersion1Interface, self).__init__(indicator) + self.noise_cancelation = MenuItem( + "Noise Cancellation", self.toggle_noise_cancelation, + checkitem=True, visible=False) + self.lou_reed_mode = MenuItem("Lou Reed Mode", self.toggle_lou_reed_mode, + checkitem=True, visible=False) + self.concert_hall_mode = MenuItem( + "Concert Hall Mode", self.toggle_parrot_concert_hall, + checkitem=True, visible=False) + self.indicator.menu.append(self.noise_cancelation) + self.indicator.menu.append(self.lou_reed_mode) + self.indicator.menu.append(self.concert_hall_mode) + + def activate(self, manager): + self.noise_cancelation.show() + self.lou_reed_mode.show() + self.concert_hall_mode.show() + super(ParrotZikVersion1Interface, self).activate(manager) + self.noise_cancelation.set_active(self.parrot.cancel_noise) + self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) + self.concert_hall_mode.set_active(self.parrot.concert_hall) + + def deactivate(self): + self.noise_cancelation.hide() + self.lou_reed_mode.hide() + self.concert_hall_mode.hide() + super(ParrotZikVersion1Interface, self).deactivate() + + def toggle_noise_cancelation(self, widget): + try: + self.parrot.cancel_noise = self.noise_cancelation.get_active() + self.noise_cancelation.set_active(self.parrot.cancel_noise) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_lou_reed_mode(self, widget): + try: + self.parrot.lou_reed_mode = self.lou_reed_mode.get_active() + self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) + self.concert_hall_mode.set_active(self.parrot.concert_hall) + self.concert_hall_mode.set_sensitive( + not self.lou_reed_mode.get_active()) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_parrot_concert_hall(self, widget): + try: + self.parrot.concert_hall = self.concert_hall_mode.get_active() + self.concert_hall_mode.set_active(self.parrot.concert_hall) + except resource_manager.DeviceDisconnected: + self.deactivate() + + +class ParrotZikVersion2Interface(ParrotZikBaseInterface): + parrot_class = ParrotZikVersion2 + + def __init__(self, indicator): + self.room_dirty = False + self.angle_dirty = False + self.noise_cancelation_dirty = False + super(ParrotZikVersion2Interface, self).__init__(indicator) + self.noise_cancelation = MenuItem("Noise Control", None, visible=False) + self.noise_cancelation_submenu = Menu() + self.noise_cancelation.set_submenu(self.noise_cancelation_submenu) + + self.noise_control_cancelation_max = MenuItem( + "Max Calcelation", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_MAX), checkitem=True, sensitive=False) + self.noise_control_cancelation_on = MenuItem( + "Normal Cancelation", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_ON), checkitem=True, sensitive=False) + self.noise_control_off = MenuItem( + "Off", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_OFF), checkitem=True, sensitive=False) + self.noise_control_street_mode = MenuItem( + "Street Mode", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.STREET_MODE), checkitem=True, sensitive=False) + self.noise_control_street_mode_max = MenuItem( + "Street Mode Max", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.STREET_MODE_MAX), checkitem=True, sensitive=False) + self.noise_cancelation_submenu.append(self.noise_control_cancelation_max) + self.noise_cancelation_submenu.append(self.noise_control_cancelation_on) + self.noise_cancelation_submenu.append(self.noise_control_off) + self.noise_cancelation_submenu.append(self.noise_control_street_mode) + self.noise_cancelation_submenu.append(self.noise_control_street_mode_max) + + self.room_sound_effect = MenuItem( + "Room Sound Effect", None, visible=False) + self.room_sound_effect_submenu = Menu() + self.room_sound_effect.set_submenu(self.room_sound_effect_submenu) + + self.room_sound_effect_enabled = MenuItem( + "Enabled", self.toggle_room_sound_effect, checkitem=True) + self.rooms = MenuItem("Rooms", None, checkitem=False) + self.angle = MenuItem("Angle", None, checkitem=False) + self.room_sound_effect_submenu.append(self.room_sound_effect_enabled) + self.room_sound_effect_submenu.append(self.rooms) + self.room_sound_effect_submenu.append(self.angle) + + self.rooms_submenu = Menu() + self.rooms.set_submenu(self.rooms_submenu) + + self.concert_hall_mode = MenuItem( + "Concert Hall", functools.partial(self.toggle_room, Rooms.CONCERT_HALL), checkitem=True) + self.jazz_mode = MenuItem( + "Jazz Club", functools.partial(self.toggle_room, Rooms.JAZZ_CLUB), checkitem=True) + self.living_mode = MenuItem( + "Living Room", functools.partial(self.toggle_room, Rooms.LIVING_ROOM), checkitem=True) + self.silent_mode = MenuItem( + "Silent Room", functools.partial(self.toggle_room, Rooms.SILENT_ROOM), checkitem=True) + self.rooms_submenu.append(self.concert_hall_mode) + self.rooms_submenu.append(self.jazz_mode) + self.rooms_submenu.append(self.living_mode) + self.rooms_submenu.append(self.silent_mode) + + self.angle_submenu = Menu() + self.angle.set_submenu(self.angle_submenu) + self.angle_30 = MenuItem( + "30", functools.partial(self.toggle_angle, 30), checkitem=True) + self.angle_60 = MenuItem( + "60", functools.partial(self.toggle_angle, 60), checkitem=True) + self.angle_90 = MenuItem( + "90", functools.partial(self.toggle_angle, 90), checkitem=True) + self.angle_120 = MenuItem( + "120", functools.partial(self.toggle_angle, 120), checkitem=True) + self.angle_150 = MenuItem( + "150", functools.partial(self.toggle_angle, 150), checkitem=True) + self.angle_180 = MenuItem( + "180", functools.partial(self.toggle_angle, 180), checkitem=True) + self.angle_submenu.append(self.angle_30) + self.angle_submenu.append(self.angle_60) + self.angle_submenu.append(self.angle_90) + self.angle_submenu.append(self.angle_120) + self.angle_submenu.append(self.angle_150) + self.angle_submenu.append(self.angle_180) + + self.flight_mode = MenuItem("Flight Mode", self.toggle_flight_mode, + checkitem=True, visible=False) + self.indicator.menu.append(self.room_sound_effect) + self.indicator.menu.append(self.noise_cancelation) + self.indicator.menu.append(self.flight_mode) + + def activate(self, manager): + self.noise_cancelation.show() + self.flight_mode.show() + self.room_sound_effect.show() + super(ParrotZikVersion2Interface, self).activate(manager) + self._read_noise_cancelation() + self.flight_mode.set_active(self.parrot.flight_mode) + self._read_sound_effect_room() + self._read_sound_effect_angle() + sound_effect = self.parrot.sound_effect + + self.room_sound_effect_enabled.set_active(sound_effect) + self.concert_hall_mode.set_sensitive(sound_effect) + self.jazz_mode.set_sensitive(sound_effect) + self.living_mode.set_sensitive(sound_effect) + self.silent_mode.set_sensitive(sound_effect) + + self.angle_30.set_sensitive(sound_effect) + self.angle_60.set_sensitive(sound_effect) + self.angle_90.set_sensitive(sound_effect) + self.angle_120.set_sensitive(sound_effect) + self.angle_150.set_sensitive(sound_effect) + self.angle_180.set_sensitive(sound_effect) + + def deactivate(self): + self.noise_cancelation.hide() + self.flight_mode.hide() + self.room_sound_effect.hide() + super(ParrotZikVersion2Interface, self).deactivate() + + def toggle_flight_mode(self, widget): + try: + self.parrot.flight_mode = self.flight_mode.get_active() + self.flight_mode.set_active(self.parrot.flight_mode) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_room(self, room, widget): + try: + if not self.room_dirty: + self.parrot.room = room + self.room_dirty = True + self._read_sound_effect_room() + self.room_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_sound_effect_room(self): + active_room = self.parrot.room + room_to_menuitem_map = ( + (Rooms.CONCERT_HALL, self.concert_hall_mode), + (Rooms.JAZZ_CLUB, self.jazz_mode), + (Rooms.LIVING_ROOM, self.living_mode), + (Rooms.SILENT_ROOM, self.silent_mode), + ) + for room, menu_item in room_to_menuitem_map: + menu_item.set_active(room == active_room) + + def toggle_room_sound_effect(self, widget): + try: + self.parrot.sound_effect = self.room_sound_effect_enabled.get_active() + sound_effect = self.parrot.sound_effect + self.room_sound_effect_enabled.set_active(sound_effect) + self.concert_hall_mode.set_sensitive(sound_effect) + self.jazz_mode.set_sensitive(sound_effect) + self.living_mode.set_sensitive(sound_effect) + self.silent_mode.set_sensitive(sound_effect) + self.angle_30.set_sensitive(sound_effect) + self.angle_60.set_sensitive(sound_effect) + self.angle_90.set_sensitive(sound_effect) + self.angle_120.set_sensitive(sound_effect) + self.angle_150.set_sensitive(sound_effect) + self.angle_180.set_sensitive(sound_effect) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_angle(self, angle, widget): + try: + if not self.angle_dirty: + self.parrot.angle = angle + self.angle_dirty = True + self._read_sound_effect_angle() + self.angle_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_sound_effect_angle(self): + active_angle = self.parrot.angle + angle_to_menuitem_map = ( + (30, self.angle_30), + (60, self.angle_60), + (90, self.angle_90), + (120, self.angle_120), + (150, self.angle_150), + (180, self.angle_180), + ) + for angle, menu_item in angle_to_menuitem_map: + menu_item.set_active(angle == active_angle) + + def toggle_noise_cancelation(self, noise_calcelation, widget): + try: + if not self.noise_cancelation_dirty: + self.parrot.noise_control = noise_calcelation + self.noise_cancelation_dirty = True + self._read_noise_cancelation() + self.noise_cancelation_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_noise_cancelation(self): + active_noise_control = self.parrot.noise_control + noise_control_to_menuitem_map = ( + (NoiseControlTypes.NOISE_CONTROL_MAX, self.noise_control_cancelation_max), + (NoiseControlTypes.NOISE_CONTROL_ON, self.noise_control_cancelation_on), + (NoiseControlTypes.NOISE_CONTROL_OFF, self.noise_control_off), + (NoiseControlTypes.STREET_MODE, self.noise_control_street_mode), + (NoiseControlTypes.STREET_MODE_MAX, self.noise_control_street_mode_max), + ) + for noise_control, menu_item in noise_control_to_menuitem_map: + menu_item.set_active(active_noise_control == noise_control) + + +if __name__ == "__main__": + try: + indicator = ParrotZikIndicator() + indicator.main() + except KeyboardInterrupt: + pass diff --git a/parrot_zik/resource_manager.py b/parrot_zik/resource_manager.py new file mode 100644 index 0000000..8b63e8c --- /dev/null +++ b/parrot_zik/resource_manager.py @@ -0,0 +1,176 @@ +import bluetooth +from operator import itemgetter +import sys + +from BeautifulSoup import BeautifulSoup + +from parrot_zik.message import Message + + +class ResourceManagerBase(object): + resources = [ + ] + + def __init__(self, socket, resource_values=None): + self.sock = socket + self.resource_values = resource_values or {} + + def get(self, resource): + try: + return self.resource_values[resource] + except KeyError: + return self.fetch(resource) + + def fetch(self, resource): + result = self.send_message(self._create_message(resource, 'get')) + self.resource_values[resource] = result + return result + + def toggle_on(self, resource): + self.send_message(self._create_message(resource, 'enable')) + self.fetch(resource) + + def toggle_off(self, resource): + self.send_message(self._create_message(resource, 'disable')) + self.fetch(resource) + + def set(self, resource, arg): + self.send_message(self._create_message(resource, 'set', arg)) + self.fetch(resource) + + def _create_message(self, resource, method, arg=None): + assert resource in self.resources, 'Unknown resource {}'.format(resource) + assert method in self.resources[resource], 'Unhandled method {} for {}'.format(method, resource) + return Message(resource, method, arg) + + def send_message(self, message): + try: + self.sock.send(str(message)) + return self.get_answer(message) + except bluetooth.btcommon.BluetoothError: + raise DeviceDisconnected + + def get_answer(self, message): + data = self.receive_message() + notifications = [] + while not data.answer: + if data.notify: + notifications.append(data.notify) + else: + raise AssertionError('Unknown response') + data = self.receive_message() + self.handle_notifications(notifications, message.resource) + return data.answer + + def handle_notifications(self, notifications, resource): + paths = map(itemgetter('path'), notifications) + clean_paths = set(map(self._clean_path, paths)) + for path in clean_paths: + if resource != path: + self.fetch(path) + + def _clean_path(self, path): + return path.rsplit('/', 1)[0].encode('utf-8') + + def receive_message(self): + if sys.platform == "darwin": + self.sock.recv(30) + else: + self.sock.recv(7) + return BeautifulSoup(self.sock.recv(1024)) + + def close(self): + self.sock.close() + + +class GenericResourceManager(ResourceManagerBase): + resources = { + '/api/software/version': ['get'], + } + + def __init__(self, sock): + super(GenericResourceManager, self).__init__(sock) + self.notifications = [] + + def handle_notification(self, notification): + self.notifications.append(notification) + + def get_resource_manager(self, resource_manager_class): + resource_manager = resource_manager_class(self.sock, self.resource_values) + resource_manager.handle_notifications(self.notifications, '/api/software/version') + return resource_manager + + @property + def api_version(self): + answer = self.get("/api/software/version") + try: + return answer.software["version"] + except KeyError: + return answer.software['sip6'] + + +class Version1ResourceManager(ResourceManagerBase): + resources = { + '/api/software/version': ['get'], + '/api/system/battery': ['get'], + '/api/bluetooth/friendlyname': ['get'], + '/api/system/auto_connection/enabled': ['get', 'set'], + '/api/system/anc_phone_mode/enabled': ['get', 'set'], + '/api/audio/specific_mode/enabled': ['get', 'set'], + '/api/audio/sound_effect/enabled': ['get', 'set'], + '/api/audio/noise_cancellation/enabled': ['get', 'set'], + } + +class Version2ResourceManager(ResourceManagerBase): + resources = { + '/api/account/username': ['get', 'set'], + '/api/appli_version': ['set'], + '/api/audio/counter': ['get'], + '/api/audio/equalizer/enabled': ['get', 'set'], + '/api/audio/equalizer/preset_id': ['set'], + '/api/audio/equalizer/preset_value': ['set'], + '/api/audio/noise_cancellation/enabled': ['get', 'set'], + '/api/audio/noise_control/enabled': ['get', 'set'], + '/api/audio/noise_control': ['get'], + '/api/audio/noise_control/phone_mode': ['get', 'set'], + '/api/audio/noise': ['get'], + '/api/audio/param_equalizer/value': ['set'], + '/api/audio/preset/bypass': ['get', 'set'], + '/api/audio/preset/': ['clear_all'], + '/api/audio/preset/counter': ['get'], + '/api/audio/preset/current': ['get'], + '/api/audio/preset': ['download', 'activate', 'save', 'remove', 'cancel_producer'], + '/api/audio/preset/synchro': ['start', 'stop'], + '/api/audio/smart_audio_tune': ['get', 'set'], + '/api/audio/sound_effect/angle': ['get', 'set'], + '/api/audio/sound_effect/enabled': ['get', 'set'], + '/api/audio/sound_effect': ['get'], + '/api/audio/sound_effect/room_size': ['get', 'set'], + '/api/audio/source': ['get'], + '/api/audio/specific_mode/enabled': ['get', 'set'], + '/api/audio/thumb_equalizer/value': ['get', 'set'], + '/api/audio/track/metadata': ['get', 'force'], + '/api/bluetooth/friendlyname': ['get', 'set'], + '/api/flight_mode': ['get', 'enable', 'disable'], + '/api/software/download_check_state': ['get'], + '/api/software/download_size': ['set'], + '/api/software/tts': ['get', 'enable', 'disable'], + '/api/software/version_checking': ['get'], + '/api/software/version': ['get'], + '/api/system/anc_phone_mode/enabled': ['get', 'set'], + '/api/system/auto_connection/enabled': ['get', 'set'], + '/api/system/auto_power_off': ['get', 'set'], + '/api/system/auto_power_off/presets_list': ['get'], + '/api/system/battery/forecast': ['get'], + '/api/system/battery': ['get'], + '/api/system/bt_address': ['get'], + '/api/system': ['calibrate'], + '/api/system/color': ['get'], + '/api/system/device_type': ['get'], + '/api/system/': ['factory_reset'], + '/api/system/head_detection/enabled': ['get', 'set'], + '/api/system/pi': ['get'], + } + +class DeviceDisconnected(Exception): + pass diff --git a/parrot_zik/status_app_mac.py b/parrot_zik/status_app_mac.py new file mode 100644 index 0000000..dccffe4 --- /dev/null +++ b/parrot_zik/status_app_mac.py @@ -0,0 +1,25 @@ +from Foundation import * +from AppKit import * + +class StatusApp(NSApplication): + + def initMenu(self, menu): + statusbar = NSStatusBar.systemStatusBar() + self.statusitem = statusbar.statusItemWithLength_( + NSVariableStatusItemLength) + + self.mymenu = menu + #add menu to statusitem + self.statusitem.setMenu_(menu.menubarMenu) + self.statusitem.setToolTip_('Parrot Zik Indicator') + + def setIcon(self,icon,icon_directory): + self.icon = NSImage.alloc().initByReferencingFile_( + icon_directory + icon + '.png') + self.icon.setScalesWhenResized_(True) + self.icon.setSize_((20, 20)) + self.statusitem.setImage_(self.icon) + + def clicked_(self, notification): + self.mymenu.actions[notification._.title]() + NSLog('clicked!') -- cgit v1.2.1 From 793b4d11fe6e7a188d5594cad5f7861225e0dd58 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 11:42:11 +0200 Subject: Refactor. --- parrot_zik/indicator.py | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/indicator.py b/parrot_zik/indicator.py index 2691113..e121e92 100644 --- a/parrot_zik/indicator.py +++ b/parrot_zik/indicator.py @@ -40,15 +40,11 @@ class BaseIndicator(object): class WindowsIndicator(BaseIndicator): def __init__(self, icon, menu): - self.icon_directory = ( - os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep + '..' - + os.path.sep + 'share' + os.path.sep + 'icons' - + os.path.sep +'zik' + os.path.sep) + self.icon_directory = os.path.join( + os.path.dirname(os.path.realpath(sys.argv[0])), '..', 'share', 'icons', 'zik') self.menu_shown = False - sys.stdout = open(tempfile.gettempdir() - + os.path.sep + "zik_tray_stdout.log", "w") - sys.stderr = open(tempfile.gettempdir() - + os.path.sep + "zik_tray_stderr.log", "w") + sys.stdout = open(os.path.join(tempfile.gettempdir(), "zik_tray_stdout.log", "w")) + sys.stderr = open(os.path.join(tempfile.gettempdir(), "zik_tray_stderr.log", "w")) statusicon = gtk.StatusIcon() statusicon.connect("popup-menu", self.gtk_right_click_event) statusicon.set_tooltip("Parrot Zik") @@ -73,14 +69,9 @@ class WindowsIndicator(BaseIndicator): class LinuxIndicator(BaseIndicator): def __init__(self, icon, menu): import appindicator - self.icon_directory = (os.path.sep + 'usr' + os.path.sep + 'share' - + os.path.sep + 'icons' + os.path.sep+'zik' - + os.path.sep) + self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') if not os.path.isdir(self.icon_directory): - self.icon_directory = (os.path.dirname(sys.argv[0]) + os.path.sep + '..' - + os.path.sep + 'share' + os.path.sep - + 'icons' + os.path.sep+'zik' - + os.path.sep) + self.icon_directory = os.path.join(os.path.dirname(sys.argv[0]), '..', 'share', 'icons', 'zik') statusicon = appindicator.Indicator( "new-parrotzik-indicator", "indicator-messages", appindicator.CATEGORY_APPLICATION_STATUS) @@ -107,10 +98,8 @@ class LinuxIndicator(BaseIndicator): class DarwinIndicator(BaseIndicator): def __init__(self, icon, menu): - self.icon_directory = ( - os.path.dirname(os.path.realpath(sys.argv[0])) + os.path.sep + '..' + os.path.sep - + 'share' + os.path.sep + 'icons' + os.path.sep + 'zik' - + os.path.sep) + self.icon_directory = os.path.join( + os.path.dirname(os.path.realpath(sys.argv[0])), '..', 'share', 'icons', 'zik') statusicon = StatusApp.sharedApplication() statusicon.initMenu(menu) super(DarwinIndicator, self).__init__(icon, menu, statusicon) -- cgit v1.2.1 From b4ff541fd77d4076051e57b748fc5817e0cc1e25 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 12:41:30 +0200 Subject: Make into proper package. --- parrot_zik/bluetooth_paired_devices.py | 2 +- parrot_zik/indicator.py | 6 +++--- parrot_zik/parrot_zik_model.py | 4 ++-- parrot_zik/resource_manager.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index eb1ec09..726731c 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -2,7 +2,7 @@ import sys import re import os -from parrot_zik.resource_manager import GenericResourceManager +from .resource_manager import GenericResourceManager if sys.platform == "darwin": from binplist import binplist diff --git a/parrot_zik/indicator.py b/parrot_zik/indicator.py index e121e92..b6b6bea 100644 --- a/parrot_zik/indicator.py +++ b/parrot_zik/indicator.py @@ -41,7 +41,7 @@ class BaseIndicator(object): class WindowsIndicator(BaseIndicator): def __init__(self, icon, menu): self.icon_directory = os.path.join( - os.path.dirname(os.path.realpath(sys.argv[0])), '..', 'share', 'icons', 'zik') + os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') self.menu_shown = False sys.stdout = open(os.path.join(tempfile.gettempdir(), "zik_tray_stdout.log", "w")) sys.stderr = open(os.path.join(tempfile.gettempdir(), "zik_tray_stderr.log", "w")) @@ -71,7 +71,7 @@ class LinuxIndicator(BaseIndicator): import appindicator self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') if not os.path.isdir(self.icon_directory): - self.icon_directory = os.path.join(os.path.dirname(sys.argv[0]), '..', 'share', 'icons', 'zik') + self.icon_directory = os.path.join('share', 'icons', 'zik') statusicon = appindicator.Indicator( "new-parrotzik-indicator", "indicator-messages", appindicator.CATEGORY_APPLICATION_STATUS) @@ -99,7 +99,7 @@ class LinuxIndicator(BaseIndicator): class DarwinIndicator(BaseIndicator): def __init__(self, icon, menu): self.icon_directory = os.path.join( - os.path.dirname(os.path.realpath(sys.argv[0])), '..', 'share', 'icons', 'zik') + os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') statusicon = StatusApp.sharedApplication() statusicon.initMenu(menu) super(DarwinIndicator, self).__init__(icon, menu, statusicon) diff --git a/parrot_zik/parrot_zik_model.py b/parrot_zik/parrot_zik_model.py index e15200f..e6a8bc7 100644 --- a/parrot_zik/parrot_zik_model.py +++ b/parrot_zik/parrot_zik_model.py @@ -1,5 +1,5 @@ -from parrot_zik.resource_manager import Version1ResourceManager -from parrot_zik.resource_manager import Version2ResourceManager +from .resource_manager import Version1ResourceManager +from .resource_manager import Version2ResourceManager class BatteryStates: diff --git a/parrot_zik/resource_manager.py b/parrot_zik/resource_manager.py index 8b63e8c..8a9cd46 100644 --- a/parrot_zik/resource_manager.py +++ b/parrot_zik/resource_manager.py @@ -4,7 +4,7 @@ import sys from BeautifulSoup import BeautifulSoup -from parrot_zik.message import Message +from .message import Message class ResourceManagerBase(object): -- cgit v1.2.1 From 8c724233f95dec5a871bb1eb39da621902d3fcd1 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 12:53:26 +0200 Subject: Refactor. Move. --- parrot_zik/interface/__init__.py | 0 parrot_zik/interface/base.py | 89 ++++++++++ parrot_zik/interface/version1.py | 61 +++++++ parrot_zik/interface/version2.py | 224 ++++++++++++++++++++++++ parrot_zik/parrot_zik_tray | 364 +-------------------------------------- 5 files changed, 376 insertions(+), 362 deletions(-) create mode 100644 parrot_zik/interface/__init__.py create mode 100644 parrot_zik/interface/base.py create mode 100644 parrot_zik/interface/version1.py create mode 100644 parrot_zik/interface/version2.py (limited to 'parrot_zik') diff --git a/parrot_zik/interface/__init__.py b/parrot_zik/interface/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py new file mode 100644 index 0000000..9ddf47a --- /dev/null +++ b/parrot_zik/interface/base.py @@ -0,0 +1,89 @@ +from .. import resource_manager +from ..indicator import MenuItem +from ..parrot_zik_model import BatteryStates + +RECONNECT_FREQUENCY = 5000 + + +class ParrotZikBaseInterface(object): + def __init__(self, indicator): + self.indicator = indicator + self.parrot = None + self.battery_level = MenuItem("Battery Level:", None, sensitive=False, + visible=False) + self.battery_state = MenuItem("Battery State:", None, sensitive=False, + visible=False) + self.firmware_version = MenuItem("Firmware Version:", None, + sensitive=False, visible=False) + self.auto_connection = MenuItem("Auto Connection", self.toggle_auto_connection, + checkitem=True, visible=False) + self.indicator.menu.append(self.battery_level) + self.indicator.menu.append(self.battery_state) + self.indicator.menu.append(self.firmware_version) + self.indicator.menu.append(self.auto_connection) + + def activate(self, manager): + self.parrot = self.parrot_class(manager) + self.read_battery() + self.indicator.info("Connected to: " + self.parrot.friendly_name) + self.firmware_version.set_label( + "Firmware version: " + self.parrot.version) + self.auto_connection.set_active(self.parrot.auto_connect) + self.battery_level.show() + self.battery_state.show() + self.firmware_version.show() + self.auto_connection.show() + self.indicator.active_interface = self + self.indicator.menu.reposition() + + @property + def parrot_class(self): + raise NotImplementedError + + def deactivate(self): + self.parrot = None + self.battery_level.hide() + self.battery_state.hide() + self.firmware_version.hide() + self.auto_connection.hide() + self.indicator.menu.reposition() + self.indicator.active_interface = None + self.indicator.setIcon("zik-audio-headset") + self.indicator.info('Lost Connection') + self.indicator.reconnect.start(self.indicator, RECONNECT_FREQUENCY) + + def toggle_auto_connection(self, widget): + try: + self.parrot.auto_connect = self.auto_connection.get_active() + self.auto_connection.set_active(self.parrot.auto_connect) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def refresh(self): + self.read_battery() + + def read_battery(self): + try: + self.parrot.refresh_battery() + battery_level = self.parrot.battery_level + battery_state = self.parrot.battery_state + except resource_manager.DeviceDisconnected: + self.deactivate() + else: + if battery_state == BatteryStates.CHARGING: + self.indicator.setIcon("zik-battery-charging") + elif battery_level > 80: + self.indicator.setIcon("zik-battery-100") + elif battery_level > 60: + self.indicator.setIcon("zik-battery-080") + elif battery_level > 40: + self.indicator.setIcon("zik-battery-060") + elif battery_level > 20: + self.indicator.setIcon("zik-battery-040") + else: + self.indicator.setIcon("zik-battery-low") + + self.battery_state.set_label( + "State: " + BatteryStates.representation[battery_state]) + self.battery_level.set_label( + "Battery Level: " + str(battery_level)) diff --git a/parrot_zik/interface/version1.py b/parrot_zik/interface/version1.py new file mode 100644 index 0000000..5a00441 --- /dev/null +++ b/parrot_zik/interface/version1.py @@ -0,0 +1,61 @@ +from .. import resource_manager +from ..indicator import MenuItem +from ..interface.base import ParrotZikBaseInterface +from ..parrot_zik_model import ParrotZikVersion1 + + +class ParrotZikVersion1Interface(ParrotZikBaseInterface): + parrot_class = ParrotZikVersion1 + + def __init__(self, indicator): + super(ParrotZikVersion1Interface, self).__init__(indicator) + self.noise_cancelation = MenuItem( + "Noise Cancellation", self.toggle_noise_cancelation, + checkitem=True, visible=False) + self.lou_reed_mode = MenuItem("Lou Reed Mode", self.toggle_lou_reed_mode, + checkitem=True, visible=False) + self.concert_hall_mode = MenuItem( + "Concert Hall Mode", self.toggle_parrot_concert_hall, + checkitem=True, visible=False) + self.indicator.menu.append(self.noise_cancelation) + self.indicator.menu.append(self.lou_reed_mode) + self.indicator.menu.append(self.concert_hall_mode) + + def activate(self, manager): + self.noise_cancelation.show() + self.lou_reed_mode.show() + self.concert_hall_mode.show() + super(ParrotZikVersion1Interface, self).activate(manager) + self.noise_cancelation.set_active(self.parrot.cancel_noise) + self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) + self.concert_hall_mode.set_active(self.parrot.concert_hall) + + def deactivate(self): + self.noise_cancelation.hide() + self.lou_reed_mode.hide() + self.concert_hall_mode.hide() + super(ParrotZikVersion1Interface, self).deactivate() + + def toggle_noise_cancelation(self, widget): + try: + self.parrot.cancel_noise = self.noise_cancelation.get_active() + self.noise_cancelation.set_active(self.parrot.cancel_noise) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_lou_reed_mode(self, widget): + try: + self.parrot.lou_reed_mode = self.lou_reed_mode.get_active() + self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) + self.concert_hall_mode.set_active(self.parrot.concert_hall) + self.concert_hall_mode.set_sensitive( + not self.lou_reed_mode.get_active()) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_parrot_concert_hall(self, widget): + try: + self.parrot.concert_hall = self.concert_hall_mode.get_active() + self.concert_hall_mode.set_active(self.parrot.concert_hall) + except resource_manager.DeviceDisconnected: + self.deactivate() diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py new file mode 100644 index 0000000..fc4af21 --- /dev/null +++ b/parrot_zik/interface/version2.py @@ -0,0 +1,224 @@ +import functools + +from .. import resource_manager +from ..indicator import MenuItem, Menu +from .base import ParrotZikBaseInterface +from ..parrot_zik_model import ParrotZikVersion2 +from ..parrot_zik_model import NoiseControlTypes +from ..parrot_zik_model import Rooms + + +class ParrotZikVersion2Interface(ParrotZikBaseInterface): + parrot_class = ParrotZikVersion2 + + def __init__(self, indicator): + self.room_dirty = False + self.angle_dirty = False + self.noise_cancelation_dirty = False + super(ParrotZikVersion2Interface, self).__init__(indicator) + self.noise_cancelation = MenuItem("Noise Control", None, visible=False) + self.noise_cancelation_submenu = Menu() + self.noise_cancelation.set_submenu(self.noise_cancelation_submenu) + + self.noise_control_cancelation_max = MenuItem( + "Max Calcelation", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_MAX), checkitem=True, sensitive=False) + self.noise_control_cancelation_on = MenuItem( + "Normal Cancelation", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_ON), checkitem=True, sensitive=False) + self.noise_control_off = MenuItem( + "Off", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.NOISE_CONTROL_OFF), checkitem=True, sensitive=False) + self.noise_control_street_mode = MenuItem( + "Street Mode", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.STREET_MODE), checkitem=True, sensitive=False) + self.noise_control_street_mode_max = MenuItem( + "Street Mode Max", functools.partial( + self.toggle_noise_cancelation, + NoiseControlTypes.STREET_MODE_MAX), checkitem=True, sensitive=False) + self.noise_cancelation_submenu.append(self.noise_control_cancelation_max) + self.noise_cancelation_submenu.append(self.noise_control_cancelation_on) + self.noise_cancelation_submenu.append(self.noise_control_off) + self.noise_cancelation_submenu.append(self.noise_control_street_mode) + self.noise_cancelation_submenu.append(self.noise_control_street_mode_max) + + self.room_sound_effect = MenuItem( + "Room Sound Effect", None, visible=False) + self.room_sound_effect_submenu = Menu() + self.room_sound_effect.set_submenu(self.room_sound_effect_submenu) + + self.room_sound_effect_enabled = MenuItem( + "Enabled", self.toggle_room_sound_effect, checkitem=True) + self.rooms = MenuItem("Rooms", None, checkitem=False) + self.angle = MenuItem("Angle", None, checkitem=False) + self.room_sound_effect_submenu.append(self.room_sound_effect_enabled) + self.room_sound_effect_submenu.append(self.rooms) + self.room_sound_effect_submenu.append(self.angle) + + self.rooms_submenu = Menu() + self.rooms.set_submenu(self.rooms_submenu) + + self.concert_hall_mode = MenuItem( + "Concert Hall", functools.partial(self.toggle_room, Rooms.CONCERT_HALL), checkitem=True) + self.jazz_mode = MenuItem( + "Jazz Club", functools.partial(self.toggle_room, Rooms.JAZZ_CLUB), checkitem=True) + self.living_mode = MenuItem( + "Living Room", functools.partial(self.toggle_room, Rooms.LIVING_ROOM), checkitem=True) + self.silent_mode = MenuItem( + "Silent Room", functools.partial(self.toggle_room, Rooms.SILENT_ROOM), checkitem=True) + self.rooms_submenu.append(self.concert_hall_mode) + self.rooms_submenu.append(self.jazz_mode) + self.rooms_submenu.append(self.living_mode) + self.rooms_submenu.append(self.silent_mode) + + self.angle_submenu = Menu() + self.angle.set_submenu(self.angle_submenu) + self.angle_30 = MenuItem( + "30", functools.partial(self.toggle_angle, 30), checkitem=True) + self.angle_60 = MenuItem( + "60", functools.partial(self.toggle_angle, 60), checkitem=True) + self.angle_90 = MenuItem( + "90", functools.partial(self.toggle_angle, 90), checkitem=True) + self.angle_120 = MenuItem( + "120", functools.partial(self.toggle_angle, 120), checkitem=True) + self.angle_150 = MenuItem( + "150", functools.partial(self.toggle_angle, 150), checkitem=True) + self.angle_180 = MenuItem( + "180", functools.partial(self.toggle_angle, 180), checkitem=True) + self.angle_submenu.append(self.angle_30) + self.angle_submenu.append(self.angle_60) + self.angle_submenu.append(self.angle_90) + self.angle_submenu.append(self.angle_120) + self.angle_submenu.append(self.angle_150) + self.angle_submenu.append(self.angle_180) + + self.flight_mode = MenuItem("Flight Mode", self.toggle_flight_mode, + checkitem=True, visible=False) + self.indicator.menu.append(self.room_sound_effect) + self.indicator.menu.append(self.noise_cancelation) + self.indicator.menu.append(self.flight_mode) + + def activate(self, manager): + self.noise_cancelation.show() + self.flight_mode.show() + self.room_sound_effect.show() + super(ParrotZikVersion2Interface, self).activate(manager) + self._read_noise_cancelation() + self.flight_mode.set_active(self.parrot.flight_mode) + self._read_sound_effect_room() + self._read_sound_effect_angle() + sound_effect = self.parrot.sound_effect + + self.room_sound_effect_enabled.set_active(sound_effect) + self.concert_hall_mode.set_sensitive(sound_effect) + self.jazz_mode.set_sensitive(sound_effect) + self.living_mode.set_sensitive(sound_effect) + self.silent_mode.set_sensitive(sound_effect) + + self.angle_30.set_sensitive(sound_effect) + self.angle_60.set_sensitive(sound_effect) + self.angle_90.set_sensitive(sound_effect) + self.angle_120.set_sensitive(sound_effect) + self.angle_150.set_sensitive(sound_effect) + self.angle_180.set_sensitive(sound_effect) + + def deactivate(self): + self.noise_cancelation.hide() + self.flight_mode.hide() + self.room_sound_effect.hide() + super(ParrotZikVersion2Interface, self).deactivate() + + def toggle_flight_mode(self, widget): + try: + self.parrot.flight_mode = self.flight_mode.get_active() + self.flight_mode.set_active(self.parrot.flight_mode) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_room(self, room, widget): + try: + if not self.room_dirty: + self.parrot.room = room + self.room_dirty = True + self._read_sound_effect_room() + self.room_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_sound_effect_room(self): + active_room = self.parrot.room + room_to_menuitem_map = ( + (Rooms.CONCERT_HALL, self.concert_hall_mode), + (Rooms.JAZZ_CLUB, self.jazz_mode), + (Rooms.LIVING_ROOM, self.living_mode), + (Rooms.SILENT_ROOM, self.silent_mode), + ) + for room, menu_item in room_to_menuitem_map: + menu_item.set_active(room == active_room) + + def toggle_room_sound_effect(self, widget): + try: + self.parrot.sound_effect = self.room_sound_effect_enabled.get_active() + sound_effect = self.parrot.sound_effect + self.room_sound_effect_enabled.set_active(sound_effect) + self.concert_hall_mode.set_sensitive(sound_effect) + self.jazz_mode.set_sensitive(sound_effect) + self.living_mode.set_sensitive(sound_effect) + self.silent_mode.set_sensitive(sound_effect) + self.angle_30.set_sensitive(sound_effect) + self.angle_60.set_sensitive(sound_effect) + self.angle_90.set_sensitive(sound_effect) + self.angle_120.set_sensitive(sound_effect) + self.angle_150.set_sensitive(sound_effect) + self.angle_180.set_sensitive(sound_effect) + except resource_manager.DeviceDisconnected: + self.deactivate() + + def toggle_angle(self, angle, widget): + try: + if not self.angle_dirty: + self.parrot.angle = angle + self.angle_dirty = True + self._read_sound_effect_angle() + self.angle_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_sound_effect_angle(self): + active_angle = self.parrot.angle + angle_to_menuitem_map = ( + (30, self.angle_30), + (60, self.angle_60), + (90, self.angle_90), + (120, self.angle_120), + (150, self.angle_150), + (180, self.angle_180), + ) + for angle, menu_item in angle_to_menuitem_map: + menu_item.set_active(angle == active_angle) + + def toggle_noise_cancelation(self, noise_calcelation, widget): + try: + if not self.noise_cancelation_dirty: + self.parrot.noise_control = noise_calcelation + self.noise_cancelation_dirty = True + self._read_noise_cancelation() + self.noise_cancelation_dirty = False + except resource_manager.DeviceDisconnected: + self.deactivate() + + def _read_noise_cancelation(self): + active_noise_control = self.parrot.noise_control + noise_control_to_menuitem_map = ( + (NoiseControlTypes.NOISE_CONTROL_MAX, self.noise_control_cancelation_max), + (NoiseControlTypes.NOISE_CONTROL_ON, self.noise_control_cancelation_on), + (NoiseControlTypes.NOISE_CONTROL_OFF, self.noise_control_off), + (NoiseControlTypes.STREET_MODE, self.noise_control_street_mode), + (NoiseControlTypes.STREET_MODE_MAX, self.noise_control_street_mode_max), + ) + for noise_control, menu_item in noise_control_to_menuitem_map: + menu_item.set_active(active_noise_control == noise_control) diff --git a/parrot_zik/parrot_zik_tray b/parrot_zik/parrot_zik_tray index dcdacd0..ae57e4d 100755 --- a/parrot_zik/parrot_zik_tray +++ b/parrot_zik/parrot_zik_tray @@ -1,15 +1,11 @@ #!/usr/bin/env python -import functools from threading import Lock import gtk +from parrot_zik.interface.version1 import ParrotZikVersion1Interface +from parrot_zik.interface.version2 import ParrotZikVersion2Interface from parrot_zik import resource_manager from parrot_zik import bluetooth_paired_devices -from parrot_zik.parrot_zik_model import BatteryStates -from parrot_zik.parrot_zik_model import ParrotZikVersion1 -from parrot_zik.parrot_zik_model import ParrotZikVersion2 -from parrot_zik.parrot_zik_model import NoiseControlTypes -from parrot_zik.parrot_zik_model import Rooms from parrot_zik.indicator import MenuItem from parrot_zik.indicator import Menu from parrot_zik.indicator import SysIndicator @@ -107,362 +103,6 @@ class ParrotZikIndicator(SysIndicator): self.reconnect.start(self, RECONNECT_FREQUENCY) SysIndicator.main(self) -class ParrotZikBaseInterface(object): - def __init__(self, indicator): - self.indicator = indicator - self.parrot = None - self.battery_level = MenuItem("Battery Level:", None, sensitive=False, - visible=False) - self.battery_state = MenuItem("Battery State:", None, sensitive=False, - visible=False) - self.firmware_version = MenuItem("Firmware Version:", None, - sensitive=False, visible=False) - self.auto_connection = MenuItem("Auto Connection", self.toggle_auto_connection, - checkitem=True, visible=False) - self.indicator.menu.append(self.battery_level) - self.indicator.menu.append(self.battery_state) - self.indicator.menu.append(self.firmware_version) - self.indicator.menu.append(self.auto_connection) - - def activate(self, manager): - self.parrot = self.parrot_class(manager) - self.read_battery() - self.indicator.info("Connected to: " + self.parrot.friendly_name) - self.firmware_version.set_label( - "Firmware version: " + self.parrot.version) - self.auto_connection.set_active(self.parrot.auto_connect) - self.battery_level.show() - self.battery_state.show() - self.firmware_version.show() - self.auto_connection.show() - self.indicator.active_interface = self - self.indicator.menu.reposition() - - @property - def parrot_class(self): - raise NotImplementedError - - def deactivate(self): - self.parrot = None - self.battery_level.hide() - self.battery_state.hide() - self.firmware_version.hide() - self.auto_connection.hide() - self.indicator.menu.reposition() - self.indicator.active_interface = None - self.indicator.setIcon("zik-audio-headset") - self.indicator.info('Lost Connection') - self.indicator.reconnect.start(self.indicator, RECONNECT_FREQUENCY) - - def toggle_auto_connection(self, widget): - try: - self.parrot.auto_connect = self.auto_connection.get_active() - self.auto_connection.set_active(self.parrot.auto_connect) - except resource_manager.DeviceDisconnected: - self.deactivate() - - def refresh(self): - self.read_battery() - - def read_battery(self): - try: - self.parrot.refresh_battery() - battery_level = self.parrot.battery_level - battery_state = self.parrot.battery_state - except resource_manager.DeviceDisconnected: - self.deactivate() - else: - if battery_state == BatteryStates.CHARGING: - self.indicator.setIcon("zik-battery-charging") - elif battery_level > 80: - self.indicator.setIcon("zik-battery-100") - elif battery_level > 60: - self.indicator.setIcon("zik-battery-080") - elif battery_level > 40: - self.indicator.setIcon("zik-battery-060") - elif battery_level > 20: - self.indicator.setIcon("zik-battery-040") - else: - self.indicator.setIcon("zik-battery-low") - - self.battery_state.set_label( - "State: " + BatteryStates.representation[battery_state]) - self.battery_level.set_label( - "Battery Level: " + str(battery_level)) - - -class ParrotZikVersion1Interface(ParrotZikBaseInterface): - parrot_class = ParrotZikVersion1 - - def __init__(self, indicator): - super(ParrotZikVersion1Interface, self).__init__(indicator) - self.noise_cancelation = MenuItem( - "Noise Cancellation", self.toggle_noise_cancelation, - checkitem=True, visible=False) - self.lou_reed_mode = MenuItem("Lou Reed Mode", self.toggle_lou_reed_mode, - checkitem=True, visible=False) - self.concert_hall_mode = MenuItem( - "Concert Hall Mode", self.toggle_parrot_concert_hall, - checkitem=True, visible=False) - self.indicator.menu.append(self.noise_cancelation) - self.indicator.menu.append(self.lou_reed_mode) - self.indicator.menu.append(self.concert_hall_mode) - - def activate(self, manager): - self.noise_cancelation.show() - self.lou_reed_mode.show() - self.concert_hall_mode.show() - super(ParrotZikVersion1Interface, self).activate(manager) - self.noise_cancelation.set_active(self.parrot.cancel_noise) - self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) - self.concert_hall_mode.set_active(self.parrot.concert_hall) - - def deactivate(self): - self.noise_cancelation.hide() - self.lou_reed_mode.hide() - self.concert_hall_mode.hide() - super(ParrotZikVersion1Interface, self).deactivate() - - def toggle_noise_cancelation(self, widget): - try: - self.parrot.cancel_noise = self.noise_cancelation.get_active() - self.noise_cancelation.set_active(self.parrot.cancel_noise) - except resource_manager.DeviceDisconnected: - self.deactivate() - - def toggle_lou_reed_mode(self, widget): - try: - self.parrot.lou_reed_mode = self.lou_reed_mode.get_active() - self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) - self.concert_hall_mode.set_active(self.parrot.concert_hall) - self.concert_hall_mode.set_sensitive( - not self.lou_reed_mode.get_active()) - except resource_manager.DeviceDisconnected: - self.deactivate() - - def toggle_parrot_concert_hall(self, widget): - try: - self.parrot.concert_hall = self.concert_hall_mode.get_active() - self.concert_hall_mode.set_active(self.parrot.concert_hall) - except resource_manager.DeviceDisconnected: - self.deactivate() - - -class ParrotZikVersion2Interface(ParrotZikBaseInterface): - parrot_class = ParrotZikVersion2 - - def __init__(self, indicator): - self.room_dirty = False - self.angle_dirty = False - self.noise_cancelation_dirty = False - super(ParrotZikVersion2Interface, self).__init__(indicator) - self.noise_cancelation = MenuItem("Noise Control", None, visible=False) - self.noise_cancelation_submenu = Menu() - self.noise_cancelation.set_submenu(self.noise_cancelation_submenu) - - self.noise_control_cancelation_max = MenuItem( - "Max Calcelation", functools.partial( - self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_MAX), checkitem=True, sensitive=False) - self.noise_control_cancelation_on = MenuItem( - "Normal Cancelation", functools.partial( - self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_ON), checkitem=True, sensitive=False) - self.noise_control_off = MenuItem( - "Off", functools.partial( - self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_OFF), checkitem=True, sensitive=False) - self.noise_control_street_mode = MenuItem( - "Street Mode", functools.partial( - self.toggle_noise_cancelation, - NoiseControlTypes.STREET_MODE), checkitem=True, sensitive=False) - self.noise_control_street_mode_max = MenuItem( - "Street Mode Max", functools.partial( - self.toggle_noise_cancelation, - NoiseControlTypes.STREET_MODE_MAX), checkitem=True, sensitive=False) - self.noise_cancelation_submenu.append(self.noise_control_cancelation_max) - self.noise_cancelation_submenu.append(self.noise_control_cancelation_on) - self.noise_cancelation_submenu.append(self.noise_control_off) - self.noise_cancelation_submenu.append(self.noise_control_street_mode) - self.noise_cancelation_submenu.append(self.noise_control_street_mode_max) - - self.room_sound_effect = MenuItem( - "Room Sound Effect", None, visible=False) - self.room_sound_effect_submenu = Menu() - self.room_sound_effect.set_submenu(self.room_sound_effect_submenu) - - self.room_sound_effect_enabled = MenuItem( - "Enabled", self.toggle_room_sound_effect, checkitem=True) - self.rooms = MenuItem("Rooms", None, checkitem=False) - self.angle = MenuItem("Angle", None, checkitem=False) - self.room_sound_effect_submenu.append(self.room_sound_effect_enabled) - self.room_sound_effect_submenu.append(self.rooms) - self.room_sound_effect_submenu.append(self.angle) - - self.rooms_submenu = Menu() - self.rooms.set_submenu(self.rooms_submenu) - - self.concert_hall_mode = MenuItem( - "Concert Hall", functools.partial(self.toggle_room, Rooms.CONCERT_HALL), checkitem=True) - self.jazz_mode = MenuItem( - "Jazz Club", functools.partial(self.toggle_room, Rooms.JAZZ_CLUB), checkitem=True) - self.living_mode = MenuItem( - "Living Room", functools.partial(self.toggle_room, Rooms.LIVING_ROOM), checkitem=True) - self.silent_mode = MenuItem( - "Silent Room", functools.partial(self.toggle_room, Rooms.SILENT_ROOM), checkitem=True) - self.rooms_submenu.append(self.concert_hall_mode) - self.rooms_submenu.append(self.jazz_mode) - self.rooms_submenu.append(self.living_mode) - self.rooms_submenu.append(self.silent_mode) - - self.angle_submenu = Menu() - self.angle.set_submenu(self.angle_submenu) - self.angle_30 = MenuItem( - "30", functools.partial(self.toggle_angle, 30), checkitem=True) - self.angle_60 = MenuItem( - "60", functools.partial(self.toggle_angle, 60), checkitem=True) - self.angle_90 = MenuItem( - "90", functools.partial(self.toggle_angle, 90), checkitem=True) - self.angle_120 = MenuItem( - "120", functools.partial(self.toggle_angle, 120), checkitem=True) - self.angle_150 = MenuItem( - "150", functools.partial(self.toggle_angle, 150), checkitem=True) - self.angle_180 = MenuItem( - "180", functools.partial(self.toggle_angle, 180), checkitem=True) - self.angle_submenu.append(self.angle_30) - self.angle_submenu.append(self.angle_60) - self.angle_submenu.append(self.angle_90) - self.angle_submenu.append(self.angle_120) - self.angle_submenu.append(self.angle_150) - self.angle_submenu.append(self.angle_180) - - self.flight_mode = MenuItem("Flight Mode", self.toggle_flight_mode, - checkitem=True, visible=False) - self.indicator.menu.append(self.room_sound_effect) - self.indicator.menu.append(self.noise_cancelation) - self.indicator.menu.append(self.flight_mode) - - def activate(self, manager): - self.noise_cancelation.show() - self.flight_mode.show() - self.room_sound_effect.show() - super(ParrotZikVersion2Interface, self).activate(manager) - self._read_noise_cancelation() - self.flight_mode.set_active(self.parrot.flight_mode) - self._read_sound_effect_room() - self._read_sound_effect_angle() - sound_effect = self.parrot.sound_effect - - self.room_sound_effect_enabled.set_active(sound_effect) - self.concert_hall_mode.set_sensitive(sound_effect) - self.jazz_mode.set_sensitive(sound_effect) - self.living_mode.set_sensitive(sound_effect) - self.silent_mode.set_sensitive(sound_effect) - - self.angle_30.set_sensitive(sound_effect) - self.angle_60.set_sensitive(sound_effect) - self.angle_90.set_sensitive(sound_effect) - self.angle_120.set_sensitive(sound_effect) - self.angle_150.set_sensitive(sound_effect) - self.angle_180.set_sensitive(sound_effect) - - def deactivate(self): - self.noise_cancelation.hide() - self.flight_mode.hide() - self.room_sound_effect.hide() - super(ParrotZikVersion2Interface, self).deactivate() - - def toggle_flight_mode(self, widget): - try: - self.parrot.flight_mode = self.flight_mode.get_active() - self.flight_mode.set_active(self.parrot.flight_mode) - except resource_manager.DeviceDisconnected: - self.deactivate() - - def toggle_room(self, room, widget): - try: - if not self.room_dirty: - self.parrot.room = room - self.room_dirty = True - self._read_sound_effect_room() - self.room_dirty = False - except resource_manager.DeviceDisconnected: - self.deactivate() - - def _read_sound_effect_room(self): - active_room = self.parrot.room - room_to_menuitem_map = ( - (Rooms.CONCERT_HALL, self.concert_hall_mode), - (Rooms.JAZZ_CLUB, self.jazz_mode), - (Rooms.LIVING_ROOM, self.living_mode), - (Rooms.SILENT_ROOM, self.silent_mode), - ) - for room, menu_item in room_to_menuitem_map: - menu_item.set_active(room == active_room) - - def toggle_room_sound_effect(self, widget): - try: - self.parrot.sound_effect = self.room_sound_effect_enabled.get_active() - sound_effect = self.parrot.sound_effect - self.room_sound_effect_enabled.set_active(sound_effect) - self.concert_hall_mode.set_sensitive(sound_effect) - self.jazz_mode.set_sensitive(sound_effect) - self.living_mode.set_sensitive(sound_effect) - self.silent_mode.set_sensitive(sound_effect) - self.angle_30.set_sensitive(sound_effect) - self.angle_60.set_sensitive(sound_effect) - self.angle_90.set_sensitive(sound_effect) - self.angle_120.set_sensitive(sound_effect) - self.angle_150.set_sensitive(sound_effect) - self.angle_180.set_sensitive(sound_effect) - except resource_manager.DeviceDisconnected: - self.deactivate() - - def toggle_angle(self, angle, widget): - try: - if not self.angle_dirty: - self.parrot.angle = angle - self.angle_dirty = True - self._read_sound_effect_angle() - self.angle_dirty = False - except resource_manager.DeviceDisconnected: - self.deactivate() - - def _read_sound_effect_angle(self): - active_angle = self.parrot.angle - angle_to_menuitem_map = ( - (30, self.angle_30), - (60, self.angle_60), - (90, self.angle_90), - (120, self.angle_120), - (150, self.angle_150), - (180, self.angle_180), - ) - for angle, menu_item in angle_to_menuitem_map: - menu_item.set_active(angle == active_angle) - - def toggle_noise_cancelation(self, noise_calcelation, widget): - try: - if not self.noise_cancelation_dirty: - self.parrot.noise_control = noise_calcelation - self.noise_cancelation_dirty = True - self._read_noise_cancelation() - self.noise_cancelation_dirty = False - except resource_manager.DeviceDisconnected: - self.deactivate() - - def _read_noise_cancelation(self): - active_noise_control = self.parrot.noise_control - noise_control_to_menuitem_map = ( - (NoiseControlTypes.NOISE_CONTROL_MAX, self.noise_control_cancelation_max), - (NoiseControlTypes.NOISE_CONTROL_ON, self.noise_control_cancelation_on), - (NoiseControlTypes.NOISE_CONTROL_OFF, self.noise_control_off), - (NoiseControlTypes.STREET_MODE, self.noise_control_street_mode), - (NoiseControlTypes.STREET_MODE_MAX, self.noise_control_street_mode_max), - ) - for noise_control, menu_item in noise_control_to_menuitem_map: - menu_item.set_active(active_noise_control == noise_control) - if __name__ == "__main__": try: -- cgit v1.2.1 From 65f9c06e00c78c382451458ea1d8a9dad1016fb0 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 12:55:18 +0200 Subject: Refactor. Move --- parrot_zik/parrot_zik_tray | 28 +--------------------------- parrot_zik/utils.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 parrot_zik/utils.py (limited to 'parrot_zik') diff --git a/parrot_zik/parrot_zik_tray b/parrot_zik/parrot_zik_tray index ae57e4d..914a37e 100755 --- a/parrot_zik/parrot_zik_tray +++ b/parrot_zik/parrot_zik_tray @@ -1,5 +1,4 @@ #!/usr/bin/env python -from threading import Lock import gtk from parrot_zik.interface.version1 import ParrotZikVersion1Interface @@ -9,37 +8,12 @@ from parrot_zik import bluetooth_paired_devices from parrot_zik.indicator import MenuItem from parrot_zik.indicator import Menu from parrot_zik.indicator import SysIndicator +from parrot_zik.utils import repeat REFRESH_FREQUENCY = 30000 RECONNECT_FREQUENCY = 5000 -class repeat(object): - def __init__(self, f): - self.f = f - self.id = None - self.lock = Lock() - - def __call__(self, cls): - self.f(cls) - - def start(self, cls, frequency): - self.lock.acquire() - if not self.id: - def run(): - self.f(cls) - return True - - self.id = gtk.timeout_add(frequency, run) - self.lock.release() - - def stop(self): - self.lock.acquire() - if self.id: - gtk.timeout_remove(self.id) - self.id = None - self.lock.release() - class ParrotZikIndicator(SysIndicator): def __init__(self): diff --git a/parrot_zik/utils.py b/parrot_zik/utils.py new file mode 100644 index 0000000..18b878d --- /dev/null +++ b/parrot_zik/utils.py @@ -0,0 +1,31 @@ +from threading import Lock + +import gtk + + +class repeat(object): + def __init__(self, f): + self.f = f + self.id = None + self.lock = Lock() + + def __call__(self, cls): + self.f(cls) + + def start(self, cls, frequency): + self.lock.acquire() + if not self.id: + def run(): + self.f(cls) + return True + + self.id = gtk.timeout_add(frequency, run) + self.lock.release() + + def stop(self): + self.lock.acquire() + if self.id: + gtk.timeout_remove(self.id) + self.id = None + self.lock.release() + -- cgit v1.2.1 From df5aa3102f9d0257224ee9423afdfd42f00592ac Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 13:20:28 +0200 Subject: Refactor. Move. --- parrot_zik/indicator.py | 243 ----------------------------------- parrot_zik/indicator/__init__.py | 23 ++++ parrot_zik/indicator/base.py | 44 +++++++ parrot_zik/indicator/gtk_wrapping.py | 40 ++++++ parrot_zik/indicator/linux.py | 44 +++++++ parrot_zik/indicator/mac.py | 66 ++++++++++ parrot_zik/indicator/windows.py | 43 +++++++ 7 files changed, 260 insertions(+), 243 deletions(-) delete mode 100644 parrot_zik/indicator.py create mode 100644 parrot_zik/indicator/__init__.py create mode 100644 parrot_zik/indicator/base.py create mode 100644 parrot_zik/indicator/gtk_wrapping.py create mode 100644 parrot_zik/indicator/linux.py create mode 100644 parrot_zik/indicator/mac.py create mode 100644 parrot_zik/indicator/windows.py (limited to 'parrot_zik') diff --git a/parrot_zik/indicator.py b/parrot_zik/indicator.py deleted file mode 100644 index b6b6bea..0000000 --- a/parrot_zik/indicator.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python - -import sys -import os -import tempfile - -if sys.platform == "linux2" or sys.platform == "win32": - import gtk -elif sys.platform == "darwin": - from Foundation import * - from AppKit import * - from PyObjCTools import AppHelper - from status_app_mac import StatusApp - - -class BaseIndicator(object): - def __init__(self, icon, menu, statusicon): - self.menu = menu - self.statusicon = statusicon - self.setIcon(icon) - - def gtk_right_click_event(self, icon, button, time): - if not self.menu_shown: - self.menu_shown = True - self.menu.popup(None, None, gtk.status_icon_position_menu, - button, time, self.statusicon) - else: - self.menu_shown = False - self.menu.popdown() - - def setIcon(self, name): - raise NotImplementedError - - def main(self): - raise NotImplementedError - - def show_about_dialog(self, widget): - raise NotImplementedError - - -class WindowsIndicator(BaseIndicator): - def __init__(self, icon, menu): - self.icon_directory = os.path.join( - os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') - self.menu_shown = False - sys.stdout = open(os.path.join(tempfile.gettempdir(), "zik_tray_stdout.log", "w")) - sys.stderr = open(os.path.join(tempfile.gettempdir(), "zik_tray_stderr.log", "w")) - statusicon = gtk.StatusIcon() - statusicon.connect("popup-menu", self.gtk_right_click_event) - statusicon.set_tooltip("Parrot Zik") - super(WindowsIndicator, self).__init__(icon, menu, statusicon) - - def setIcon(self, name): - self.statusicon.set_from_file(self.icon_directory + name + '.png') - - def main(self): - gtk.main() - - def show_about_dialog(self, widget): - about_dialog = gtk.AboutDialog() - about_dialog.set_destroy_with_parent(True) - about_dialog.set_name("Parrot Zik Tray") - about_dialog.set_version("0.3") - about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) - about_dialog.run() - about_dialog.destroy() - - -class LinuxIndicator(BaseIndicator): - def __init__(self, icon, menu): - import appindicator - self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') - if not os.path.isdir(self.icon_directory): - self.icon_directory = os.path.join('share', 'icons', 'zik') - statusicon = appindicator.Indicator( - "new-parrotzik-indicator", "indicator-messages", - appindicator.CATEGORY_APPLICATION_STATUS) - statusicon.set_status(appindicator.STATUS_ACTIVE) - statusicon.set_icon_theme_path(self.icon_directory) - statusicon.set_menu(menu.gtk_menu) - super(LinuxIndicator, self).__init__(icon, menu, statusicon) - - def setIcon(self, name): - self.statusicon.set_icon(name) - - def main(self): - gtk.main() - - def show_about_dialog(self, widget): - about_dialog = gtk.AboutDialog() - about_dialog.set_destroy_with_parent(True) - about_dialog.set_name("Parrot Zik Tray") - about_dialog.set_version("0.3") - about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) - about_dialog.run() - about_dialog.destroy() - - -class DarwinIndicator(BaseIndicator): - def __init__(self, icon, menu): - self.icon_directory = os.path.join( - os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') - statusicon = StatusApp.sharedApplication() - statusicon.initMenu(menu) - super(DarwinIndicator, self).__init__(icon, menu, statusicon) - - def setIcon(self, name): - self.statusicon.setIcon(name, self.icon_directory) - - def main(self): - AppHelper.runEventLoop() - - def show_about_dialog(self, widget): - pass - - -class NSMenu(object): - def __init__(self): - self.actions = {} - self.menubarMenu = NSMenu.alloc().init() - self.menubarMenu.setAutoenablesItems_(False) - - def append(self, menu_item): - self.actions[menu_item.title] = menu_item.action - self.menubarMenu.addItem_(menu_item.nsmenu_item) - - def reposition(self): - # TODO - pass - -class GTKMenu(object): - def __init__(self): - self.gtk_menu = gtk.Menu() - - def append(self, menu_item): - self.gtk_menu.append(menu_item.base_item) - - def reposition(self): - self.gtk_menu.reposition() - - -class MenuItemBase(object): - def __init__(self, base_item, sensitive, visible): - self.base_item = base_item - self.set_sensitive(sensitive) - if visible: - self.show() - else: - self.hide() - - def set_sensitive(self, option): - raise NotImplementedError - - def set_active(self, option): - raise NotImplementedError - - def get_active(self): - raise NotImplementedError - - def set_label(self, option): - raise NotImplementedError - - def show(self): - self.base_item.show() - - def hide(self): - self.base_item.hide() - - def set_submenu(self, menu): - raise NotImplementedError - -class GTKMenuItem(MenuItemBase): - def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): - if checkitem: - gtk_item = gtk.CheckMenuItem(name) - else: - gtk_item = gtk.MenuItem(name) - if action: - gtk_item.connect("activate", action) - super(GTKMenuItem, self).__init__(gtk_item, sensitive, visible) - - def set_sensitive(self, option): - return self.base_item.set_sensitive(option) - - def set_active(self, option): - return self.base_item.set_active(option) - - def get_active(self): - return self.base_item.get_active() - - def set_label(self, option): - return self.base_item.set_label(option) - - def set_submenu(self, menu): - self.base_item.set_submenu(menu.gtk_menu) - - -class NSMenuItem(MenuItemBase): - def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): - self.title = name - self.action = action - nsmenu_item = ( - NSMenuItem.alloc().initWithTitle_action_keyEquivalent_( - name, 'clicked:', '')) - super(NSMenuItem, self).__init__(nsmenu_item, sensitive, visible) - - def set_sensitive(self, option): - self.base_item.setEnabled_(option) - - def set_active(self, option): - self.base_item.setState_(option) - - def get_active(self): - return self.base_item.state - - def set_label(self, option): - self.title = option - self.base_item.setTitle_(option) - -if sys.platform == 'linux2': - SysIndicator = LinuxIndicator - Menu = GTKMenu - MenuItem = GTKMenuItem -elif sys.platform == 'win32': - SysIndicator = WindowsIndicator - Menu = GTKMenu - MenuItem = GTKMenuItem -elif sys.platform == 'darwin': - SysIndicator = DarwinIndicator - Menu = NSMenu - MenuItem = NSMenuItem -else: - raise Exception('Platform not supported') - -if __name__ == "__main__": - - quit_item = MenuItem("Quit", sys.exit, True) - - menu = Menu() - menu.append(quit_item) - - indicator = SysIndicator(icon="zik-audio-headset", menu=menu) - indicator.main() diff --git a/parrot_zik/indicator/__init__.py b/parrot_zik/indicator/__init__.py new file mode 100644 index 0000000..aeda305 --- /dev/null +++ b/parrot_zik/indicator/__init__.py @@ -0,0 +1,23 @@ +__all__ = ('SysIndicator', 'Menu', 'MenuItem') + +import sys + +if sys.platform == 'linux2': + import linux + import gtk_wrapping + SysIndicator = linux.LinuxIndicator + Menu = gtk_wrapping.GTKMenu + MenuItem = gtk_wrapping.GTKMenuItem +elif sys.platform == 'win32': + import gtk_wrapping + import windows + SysIndicator = windows.WindowsIndicator + Menu = gtk_wrapping.GTKMenu + MenuItem = gtk_wrapping.GTKMenuItem +elif sys.platform == 'darwin': + import mac + SysIndicator = mac.DarwinIndicator + Menu = mac.NSMenu + MenuItem = mac.NSMenuItem +else: + raise Exception('Platform not supported') diff --git a/parrot_zik/indicator/base.py b/parrot_zik/indicator/base.py new file mode 100644 index 0000000..7101790 --- /dev/null +++ b/parrot_zik/indicator/base.py @@ -0,0 +1,44 @@ +class BaseIndicator(object): + def __init__(self, icon, menu, statusicon): + self.menu = menu + self.statusicon = statusicon + self.setIcon(icon) + + def setIcon(self, name): + raise NotImplementedError + + def main(self): + raise NotImplementedError + + def show_about_dialog(self, widget): + raise NotImplementedError + +class MenuItemBase(object): + def __init__(self, base_item, sensitive, visible): + self.base_item = base_item + self.set_sensitive(sensitive) + if visible: + self.show() + else: + self.hide() + + def set_sensitive(self, option): + raise NotImplementedError + + def set_active(self, option): + raise NotImplementedError + + def get_active(self): + raise NotImplementedError + + def set_label(self, option): + raise NotImplementedError + + def show(self): + self.base_item.show() + + def hide(self): + self.base_item.hide() + + def set_submenu(self, menu): + raise NotImplementedError diff --git a/parrot_zik/indicator/gtk_wrapping.py b/parrot_zik/indicator/gtk_wrapping.py new file mode 100644 index 0000000..9494adc --- /dev/null +++ b/parrot_zik/indicator/gtk_wrapping.py @@ -0,0 +1,40 @@ +import gtk + +from .base import MenuItemBase + + +class GTKMenu(object): + def __init__(self): + self.gtk_menu = gtk.Menu() + + def append(self, menu_item): + self.gtk_menu.append(menu_item.base_item) + + def reposition(self): + self.gtk_menu.reposition() + + +class GTKMenuItem(MenuItemBase): + def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): + if checkitem: + gtk_item = gtk.CheckMenuItem(name) + else: + gtk_item = gtk.MenuItem(name) + if action: + gtk_item.connect("activate", action) + super(GTKMenuItem, self).__init__(gtk_item, sensitive, visible) + + def set_sensitive(self, option): + return self.base_item.set_sensitive(option) + + def set_active(self, option): + return self.base_item.set_active(option) + + def get_active(self): + return self.base_item.get_active() + + def set_label(self, option): + return self.base_item.set_label(option) + + def set_submenu(self, menu): + self.base_item.set_submenu(menu.gtk_menu) diff --git a/parrot_zik/indicator/linux.py b/parrot_zik/indicator/linux.py new file mode 100644 index 0000000..cbec1dd --- /dev/null +++ b/parrot_zik/indicator/linux.py @@ -0,0 +1,44 @@ +import os + +import gtk + +from .base import BaseIndicator + + +class LinuxIndicator(BaseIndicator): + def __init__(self, icon, menu): + import appindicator + self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') + if not os.path.isdir(self.icon_directory): + self.icon_directory = os.path.join('share', 'icons', 'zik') + statusicon = appindicator.Indicator( + "new-parrotzik-indicator", "indicator-messages", + appindicator.CATEGORY_APPLICATION_STATUS) + statusicon.set_status(appindicator.STATUS_ACTIVE) + statusicon.set_icon_theme_path(self.icon_directory) + statusicon.set_menu(menu.gtk_menu) + super(LinuxIndicator, self).__init__(icon, menu, statusicon) + + def gtk_right_click_event(self, icon, button, time): + if not self.menu_shown: + self.menu_shown = True + self.menu.popup(None, None, gtk.status_icon_position_menu, + button, time, self.statusicon) + else: + self.menu_shown = False + self.menu.poVpdown() + + def setIcon(self, name): + self.statusicon.set_icon(name) + + def main(self): + gtk.main() + + def show_about_dialog(self, widget): + about_dialog = gtk.AboutDialog() + about_dialog.set_destroy_with_parent(True) + about_dialog.set_name("Parrot Zik Tray") + about_dialog.set_version("0.3") + about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) + about_dialog.run() + about_dialog.destroy() diff --git a/parrot_zik/indicator/mac.py b/parrot_zik/indicator/mac.py new file mode 100644 index 0000000..8fdd1e6 --- /dev/null +++ b/parrot_zik/indicator/mac.py @@ -0,0 +1,66 @@ +import os +import sys + +from Foundation import * +from AppKit import * +from PyObjCTools import AppHelper + +from .base import BaseIndicator +from .base import MenuItemBase +from ..status_app_mac import StatusApp + + +class DarwinIndicator(BaseIndicator): + def __init__(self, icon, menu): + self.icon_directory = os.path.join( + os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') + statusicon = StatusApp.sharedApplication() + statusicon.initMenu(menu) + super(DarwinIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.setIcon(name, self.icon_directory) + + def main(self): + AppHelper.runEventLoop() + + def show_about_dialog(self, widget): + pass + + +class NSMenu(object): + def __init__(self): + self.actions = {} + self.menubarMenu = NSMenu.alloc().init() + self.menubarMenu.setAutoenablesItems_(False) + + def append(self, menu_item): + self.actions[menu_item.title] = menu_item.action + self.menubarMenu.addItem_(menu_item.nsmenu_item) + + def reposition(self): + # TODO + pass + + +class NSMenuItem(MenuItemBase): + def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): + self.title = name + self.action = action + nsmenu_item = ( + NSMenuItem.alloc().initWithTitle_action_keyEquivalent_( + name, 'clicked:', '')) + super(NSMenuItem, self).__init__(nsmenu_item, sensitive, visible) + + def set_sensitive(self, option): + self.base_item.setEnabled_(option) + + def set_active(self, option): + self.base_item.setState_(option) + + def get_active(self): + return self.base_item.state + + def set_label(self, option): + self.title = option + self.base_item.setTitle_(option) diff --git a/parrot_zik/indicator/windows.py b/parrot_zik/indicator/windows.py new file mode 100644 index 0000000..0f81e55 --- /dev/null +++ b/parrot_zik/indicator/windows.py @@ -0,0 +1,43 @@ +import sys +import tempfile +import gtk +import os + +from .base import BaseIndicator + + +class WindowsIndicator(BaseIndicator): + def __init__(self, icon, menu): + self.icon_directory = os.path.join( + os.path.dirname(os.path.realpath(sys.argv[0])), 'share', 'icons', 'zik') + self.menu_shown = False + sys.stdout = open(os.path.join(tempfile.gettempdir(), "zik_tray_stdout.log", "w")) + sys.stderr = open(os.path.join(tempfile.gettempdir(), "zik_tray_stderr.log", "w")) + statusicon = gtk.StatusIcon() + statusicon.connect("popup-menu", self.gtk_right_click_event) + statusicon.set_tooltip("Parrot Zik") + super(WindowsIndicator, self).__init__(icon, menu, statusicon) + + def gtk_right_click_event(self, icon, button, time): + if not self.menu_shown: + self.menu_shown = True + self.menu.popup(None, None, gtk.status_icon_position_menu, + button, time, self.statusicon) + else: + self.menu_shown = False + self.menu.poVpdown() + + def setIcon(self, name): + self.statusicon.set_from_file(self.icon_directory + name + '.png') + + def main(self): + gtk.main() + + def show_about_dialog(self, widget): + about_dialog = gtk.AboutDialog() + about_dialog.set_destroy_with_parent(True) + about_dialog.set_name("Parrot Zik Tray") + about_dialog.set_version("0.3") + about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) + about_dialog.run() + about_dialog.destroy() -- cgit v1.2.1 From 3b4f022722e43d5821f4d2276018242c88cb1ed3 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 13:30:06 +0200 Subject: Fix quit wrapping. --- parrot_zik/indicator/base.py | 3 +++ parrot_zik/indicator/linux.py | 3 +++ parrot_zik/indicator/mac.py | 3 +++ parrot_zik/indicator/windows.py | 3 +++ parrot_zik/parrot_zik_tray | 5 ++--- 5 files changed, 14 insertions(+), 3 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/indicator/base.py b/parrot_zik/indicator/base.py index 7101790..8204fa9 100644 --- a/parrot_zik/indicator/base.py +++ b/parrot_zik/indicator/base.py @@ -13,6 +13,9 @@ class BaseIndicator(object): def show_about_dialog(self, widget): raise NotImplementedError + def quit(self, _): + raise NotImplementedError + class MenuItemBase(object): def __init__(self, base_item, sensitive, visible): self.base_item = base_item diff --git a/parrot_zik/indicator/linux.py b/parrot_zik/indicator/linux.py index cbec1dd..ff06587 100644 --- a/parrot_zik/indicator/linux.py +++ b/parrot_zik/indicator/linux.py @@ -34,6 +34,9 @@ class LinuxIndicator(BaseIndicator): def main(self): gtk.main() + def quit(self, _): + gtk.main_quit() + def show_about_dialog(self, widget): about_dialog = gtk.AboutDialog() about_dialog.set_destroy_with_parent(True) diff --git a/parrot_zik/indicator/mac.py b/parrot_zik/indicator/mac.py index 8fdd1e6..d28ee26 100644 --- a/parrot_zik/indicator/mac.py +++ b/parrot_zik/indicator/mac.py @@ -27,6 +27,9 @@ class DarwinIndicator(BaseIndicator): def show_about_dialog(self, widget): pass + def quit(self, _): + pass + class NSMenu(object): def __init__(self): diff --git a/parrot_zik/indicator/windows.py b/parrot_zik/indicator/windows.py index 0f81e55..118f620 100644 --- a/parrot_zik/indicator/windows.py +++ b/parrot_zik/indicator/windows.py @@ -33,6 +33,9 @@ class WindowsIndicator(BaseIndicator): def main(self): gtk.main() + def quit(self, _): + gtk.main_quit() + def show_about_dialog(self, widget): about_dialog = gtk.AboutDialog() about_dialog.set_destroy_with_parent(True) diff --git a/parrot_zik/parrot_zik_tray b/parrot_zik/parrot_zik_tray index 914a37e..0e5b951 100755 --- a/parrot_zik/parrot_zik_tray +++ b/parrot_zik/parrot_zik_tray @@ -1,5 +1,4 @@ #!/usr/bin/env python -import gtk from parrot_zik.interface.version1 import ParrotZikVersion1Interface from parrot_zik.interface.version2 import ParrotZikVersion2Interface @@ -26,8 +25,8 @@ class ParrotZikIndicator(SysIndicator): self.version_1_interface = ParrotZikVersion1Interface(self) self.version_2_interface = ParrotZikVersion2Interface(self) - self.quit = MenuItem("Quit", gtk.main_quit, checkitem=True) - self.menu.append(self.quit) + self.quit_item = MenuItem("Quit", self.quit, checkitem=True) + self.menu.append(self.quit_item) SysIndicator.__init__(self, icon="zik-audio-headset", menu=self.menu) -- cgit v1.2.1 From f291feaa8a33645850818f811ba8d7f9eb9d4c31 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 13:41:06 +0200 Subject: Refactor. --- parrot_zik/indicator/base.py | 3 +- parrot_zik/indicator/linux.py | 3 +- parrot_zik/indicator/mac.py | 3 +- parrot_zik/indicator/windows.py | 3 +- parrot_zik/parrot_zik_tray | 85 ----------------------------------------- parrot_zik/parrot_zik_tray.py | 80 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 88 insertions(+), 89 deletions(-) delete mode 100755 parrot_zik/parrot_zik_tray create mode 100755 parrot_zik/parrot_zik_tray.py (limited to 'parrot_zik') diff --git a/parrot_zik/indicator/base.py b/parrot_zik/indicator/base.py index 8204fa9..b29368e 100644 --- a/parrot_zik/indicator/base.py +++ b/parrot_zik/indicator/base.py @@ -7,7 +7,8 @@ class BaseIndicator(object): def setIcon(self, name): raise NotImplementedError - def main(self): + @classmethod + def main(cls): raise NotImplementedError def show_about_dialog(self, widget): diff --git a/parrot_zik/indicator/linux.py b/parrot_zik/indicator/linux.py index ff06587..fc0f425 100644 --- a/parrot_zik/indicator/linux.py +++ b/parrot_zik/indicator/linux.py @@ -31,7 +31,8 @@ class LinuxIndicator(BaseIndicator): def setIcon(self, name): self.statusicon.set_icon(name) - def main(self): + @classmethod + def main(cls): gtk.main() def quit(self, _): diff --git a/parrot_zik/indicator/mac.py b/parrot_zik/indicator/mac.py index d28ee26..232e010 100644 --- a/parrot_zik/indicator/mac.py +++ b/parrot_zik/indicator/mac.py @@ -21,7 +21,8 @@ class DarwinIndicator(BaseIndicator): def setIcon(self, name): self.statusicon.setIcon(name, self.icon_directory) - def main(self): + @classmethod + def main(cls): AppHelper.runEventLoop() def show_about_dialog(self, widget): diff --git a/parrot_zik/indicator/windows.py b/parrot_zik/indicator/windows.py index 118f620..79a4ef3 100644 --- a/parrot_zik/indicator/windows.py +++ b/parrot_zik/indicator/windows.py @@ -30,7 +30,8 @@ class WindowsIndicator(BaseIndicator): def setIcon(self, name): self.statusicon.set_from_file(self.icon_directory + name + '.png') - def main(self): + @classmethod + def main(cls): gtk.main() def quit(self, _): diff --git a/parrot_zik/parrot_zik_tray b/parrot_zik/parrot_zik_tray deleted file mode 100755 index 0e5b951..0000000 --- a/parrot_zik/parrot_zik_tray +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python - -from parrot_zik.interface.version1 import ParrotZikVersion1Interface -from parrot_zik.interface.version2 import ParrotZikVersion2Interface -from parrot_zik import resource_manager -from parrot_zik import bluetooth_paired_devices -from parrot_zik.indicator import MenuItem -from parrot_zik.indicator import Menu -from parrot_zik.indicator import SysIndicator -from parrot_zik.utils import repeat - -REFRESH_FREQUENCY = 30000 -RECONNECT_FREQUENCY = 5000 - - - -class ParrotZikIndicator(SysIndicator): - def __init__(self): - - self.menu = Menu() - - self.info_item = MenuItem("Parrot Zik Not connected", - None, sensitive=False) - self.menu.append(self.info_item) - - self.version_1_interface = ParrotZikVersion1Interface(self) - self.version_2_interface = ParrotZikVersion2Interface(self) - self.quit_item = MenuItem("Quit", self.quit, checkitem=True) - self.menu.append(self.quit_item) - - SysIndicator.__init__(self, icon="zik-audio-headset", menu=self.menu) - - self.active_interface = None - - @repeat - def reconnect(self): - if self.active_interface: - self.reconnect.stop() - else: - self.info("Trying to connect") - try: - manager = bluetooth_paired_devices.connect() - except bluetooth_paired_devices.BluetoothIsNotOn: - self.info("Bluetooth is turned off") - except bluetooth_paired_devices.DeviceNotConnected: - self.info("Parrot Zik Not connected") - except bluetooth_paired_devices.ConnectionFailure: - self.info("Failed to connect") - else: - if manager.api_version.startswith('1'): - interface = self.version_1_interface - else: - interface = self.version_2_interface - try: - interface.activate(manager) - except resource_manager.DeviceDisconnected: - interface.deactivate() - else: - self.autorefresh(self) - self.autorefresh.start(self, REFRESH_FREQUENCY) - self.reconnect.stop() - - def info(self, message): - self.info_item.set_label(message) - print(message) - - @repeat - def autorefresh(self): - if self.active_interface: - self.active_interface.refresh() - else: - self.reconnect.start(self, RECONNECT_FREQUENCY) - self.autorefresh.stop() - - def main(self): - self.reconnect.start(self, RECONNECT_FREQUENCY) - SysIndicator.main(self) - - -if __name__ == "__main__": - try: - indicator = ParrotZikIndicator() - indicator.main() - except KeyboardInterrupt: - pass diff --git a/parrot_zik/parrot_zik_tray.py b/parrot_zik/parrot_zik_tray.py new file mode 100755 index 0000000..35931d7 --- /dev/null +++ b/parrot_zik/parrot_zik_tray.py @@ -0,0 +1,80 @@ +from parrot_zik.interface.version1 import ParrotZikVersion1Interface +from parrot_zik.interface.version2 import ParrotZikVersion2Interface +from parrot_zik import resource_manager +from parrot_zik import bluetooth_paired_devices +from parrot_zik.indicator import MenuItem +from parrot_zik.indicator import Menu +from parrot_zik.indicator import SysIndicator +from parrot_zik.utils import repeat + +REFRESH_FREQUENCY = 30000 +RECONNECT_FREQUENCY = 5000 + + + +class ParrotZikIndicator(SysIndicator): + def __init__(self): + + self.menu = Menu() + + self.info_item = MenuItem("Parrot Zik Not connected", + None, sensitive=False) + self.menu.append(self.info_item) + + self.version_1_interface = ParrotZikVersion1Interface(self) + self.version_2_interface = ParrotZikVersion2Interface(self) + self.quit_item = MenuItem("Quit", self.quit, checkitem=True) + self.menu.append(self.quit_item) + + SysIndicator.__init__(self, icon="zik-audio-headset", menu=self.menu) + + self.active_interface = None + + @repeat + def reconnect(self): + if self.active_interface: + self.reconnect.stop() + else: + self.info("Trying to connect") + try: + manager = bluetooth_paired_devices.connect() + except bluetooth_paired_devices.BluetoothIsNotOn: + self.info("Bluetooth is turned off") + except bluetooth_paired_devices.DeviceNotConnected: + self.info("Parrot Zik Not connected") + except bluetooth_paired_devices.ConnectionFailure: + self.info("Failed to connect") + else: + if manager.api_version.startswith('1'): + interface = self.version_1_interface + else: + interface = self.version_2_interface + try: + interface.activate(manager) + except resource_manager.DeviceDisconnected: + interface.deactivate() + else: + self.autorefresh(self) + self.autorefresh.start(self, REFRESH_FREQUENCY) + self.reconnect.stop() + + def info(self, message): + self.info_item.set_label(message) + print(message) + + @repeat + def autorefresh(self): + if self.active_interface: + self.active_interface.refresh() + else: + self.reconnect.start(self, RECONNECT_FREQUENCY) + self.autorefresh.stop() + + @classmethod + def main(cls): + try: + indicator = cls() + cls.reconnect.start(indicator, RECONNECT_FREQUENCY) + super(ParrotZikIndicator, cls).main() + except KeyboardInterrupt: + pass -- cgit v1.2.1 From afa654af0a2d2e6b34b47af52ed214977b7a3e12 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 13:56:44 +0200 Subject: Refactor. Move. --- parrot_zik/interface/base.py | 2 +- parrot_zik/interface/version1.py | 2 +- parrot_zik/interface/version2.py | 6 +- parrot_zik/model/__init__.py | 0 parrot_zik/model/base.py | 58 ++++++++++ parrot_zik/model/version1.py | 48 +++++++++ parrot_zik/model/version2.py | 118 +++++++++++++++++++++ parrot_zik/parrot_zik_model.py | 222 --------------------------------------- 8 files changed, 229 insertions(+), 227 deletions(-) create mode 100644 parrot_zik/model/__init__.py create mode 100644 parrot_zik/model/base.py create mode 100644 parrot_zik/model/version1.py create mode 100644 parrot_zik/model/version2.py delete mode 100644 parrot_zik/parrot_zik_model.py (limited to 'parrot_zik') diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py index 9ddf47a..1611874 100644 --- a/parrot_zik/interface/base.py +++ b/parrot_zik/interface/base.py @@ -1,6 +1,6 @@ from .. import resource_manager from ..indicator import MenuItem -from ..parrot_zik_model import BatteryStates +from ..model.base import BatteryStates RECONNECT_FREQUENCY = 5000 diff --git a/parrot_zik/interface/version1.py b/parrot_zik/interface/version1.py index 5a00441..1af71ec 100644 --- a/parrot_zik/interface/version1.py +++ b/parrot_zik/interface/version1.py @@ -1,7 +1,7 @@ from .. import resource_manager from ..indicator import MenuItem from ..interface.base import ParrotZikBaseInterface -from ..parrot_zik_model import ParrotZikVersion1 +from ..model.version1 import ParrotZikVersion1 class ParrotZikVersion1Interface(ParrotZikBaseInterface): diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index fc4af21..ff21004 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -3,9 +3,9 @@ import functools from .. import resource_manager from ..indicator import MenuItem, Menu from .base import ParrotZikBaseInterface -from ..parrot_zik_model import ParrotZikVersion2 -from ..parrot_zik_model import NoiseControlTypes -from ..parrot_zik_model import Rooms +from ..model.version2 import ParrotZikVersion2 +from ..model.version2 import NoiseControlTypes +from ..model.version2 import Rooms class ParrotZikVersion2Interface(ParrotZikBaseInterface): diff --git a/parrot_zik/model/__init__.py b/parrot_zik/model/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/parrot_zik/model/base.py b/parrot_zik/model/base.py new file mode 100644 index 0000000..0cd4652 --- /dev/null +++ b/parrot_zik/model/base.py @@ -0,0 +1,58 @@ +class ParrotZikBase(object): + def __init__(self, resource_manager): + self.resource_manager = resource_manager + + @property + def version(self): + return self.resource_manager.api_version + + def refresh_battery(self): + self.resource_manager.fetch('/api/system/battery') + + @property + def battery_state(self): + answer = self.resource_manager.get("/api/system/battery") + return answer.system.battery["state"] + + def get_battery_level(self, field_name): + answer = self.resource_manager.get("/api/system/battery") + return int(answer.system.battery[field_name]) + + @property + def friendly_name(self): + answer = self.resource_manager.get("/api/bluetooth/friendlyname") + return answer.bluetooth["friendlyname"] + + @property + def auto_connect(self): + answer = self.resource_manager.get("/api/system/auto_connection/enabled") + return self._result_to_bool( + answer.system.auto_connection["enabled"]) + + @auto_connect.setter + def auto_connect(self, arg): + self.resource_manager.set("/api/system/auto_connection/enabled", arg) + + @property + def anc_phone_mode(self): + answer = self.resource_manager.get("/api/system/anc_phone_mode/enabled") + return self._result_to_bool( + answer.system.anc_phone_mode["enabled"]) + + def _result_to_bool(self, result): + if result == "true": + return True + elif result == "false": + return False + else: + raise AssertionError(result) + +class BatteryStates: + CHARGED = 'charged' + IN_USE = 'in_use' + CHARGING = 'charging' + representation = { + CHARGED: 'Charged', + IN_USE: 'In Use', + CHARGING: 'Charging', + } diff --git a/parrot_zik/model/version1.py b/parrot_zik/model/version1.py new file mode 100644 index 0000000..b39684f --- /dev/null +++ b/parrot_zik/model/version1.py @@ -0,0 +1,48 @@ +from .base import ParrotZikBase +from ..resource_manager import Version1ResourceManager + + +class ParrotZikVersion1(ParrotZikBase): + def __init__(self, resource_manager): + super(ParrotZikVersion1, self).__init__( + resource_manager.get_resource_manager( + Version1ResourceManager)) + + @property + def version(self): + answer = self.resource_manager.get('/api/software/version') + return answer.software['version'] + + @property + def battery_level(self): + return int(self.get_battery_level('level')) + + @property + def lou_reed_mode(self): + answer = self.resource_manager.get("/api/audio/specific_mode/enabled") + return self._result_to_bool( + answer.audio.specific_mode["enabled"]) + + @lou_reed_mode.setter + def lou_reed_mode(self, arg): + self.resource_manager.get("/api/audio/specific_mode/enabled", arg) + + @property + def concert_hall(self): + answer = self.resource_manager.get("/api/audio/sound_effect/enabled") + return self._result_to_bool( + answer.audio.sound_effect["enabled"]) + + @concert_hall.setter + def concert_hall(self, arg): + self.resource_manager.get("/api/audio/sound_effect/enabled", arg) + + @property + def cancel_noise(self): + answer = self.resource_manager.get("/api/audio/noise_cancellation/enabled") + return self._result_to_bool( + answer.audio.noise_cancellation["enabled"]) + + @cancel_noise.setter + def cancel_noise(self, arg): + self.resource_manager.set("/api/audio/noise_cancellation/enabled", arg) \ No newline at end of file diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py new file mode 100644 index 0000000..9ef6267 --- /dev/null +++ b/parrot_zik/model/version2.py @@ -0,0 +1,118 @@ +from .base import ParrotZikBase +from ..resource_manager import Version2ResourceManager + + +class ParrotZikVersion2(ParrotZikBase): + def __init__(self, resource_manager): + super(ParrotZikVersion2, self).__init__( + resource_manager.get_resource_manager( + Version2ResourceManager)) + + @property + def version(self): + answer = self.resource_manager.get('/api/software/version') + return answer.software['sip6'] + + @property + def battery_level(self): + return self.get_battery_level('percent') + + @property + def flight_mode(self): + answer = self.resource_manager.get('/api/flight_mode') + return self._result_to_bool(answer.flight_mode['enabled']) + + @flight_mode.setter + def flight_mode(self, arg): + if arg: + self.resource_manager.toggle_on('/api/flight_mode') + else: + self.resource_manager.toggle_off('/api/flight_mode') + + @property + def sound_effect(self): + answer = self.resource_manager.get('/api/audio/sound_effect/enabled') + return self._result_to_bool(answer.audio.sound_effect['enabled']) + + @sound_effect.setter + def sound_effect(self, arg): + self.resource_manager.set('/api/audio/sound_effect/enabled', arg) + + @property + def room(self): + answer = self.resource_manager.get('/api/audio/sound_effect/room_size') + return answer.audio.sound_effect['room_size'] + + @room.setter + def room(self, arg): + self.resource_manager.set('/api/audio/sound_effect/room_size', arg) + + @property + def external_noise(self): + answer = self.resource_manager.get('/api/audio/noise') + return int(answer.audio.noise['external']) + + @property + def internal_noise(self): + answer = self.resource_manager.get('/api/audio/noise') + return int(answer.audio.noise['internal']) + + @property + def angle(self): + answer = self.resource_manager.get('/api/audio/sound_effect/angle') + return int(answer.audio.sound_effect['angle']) + + @angle.setter + def angle(self, arg): + self.resource_manager.set('/api/audio/sound_effect/angle', arg) + + @property + def noise_control(self): + answer = self.resource_manager.get('/api/audio/noise_control') + return NoiseControl.from_noise_control(answer.audio.noise_control) + + @noise_control.setter + def noise_control(self, arg): + pass + + @property + def noise_control_enabled(self): + answer = self.resource_manager.get('/api/audio/noise_control/enabled') + return self._result_to_bool(answer.audio.noise_control['enabled']) + + +class NoiseControl(object): + def __init__(self, type, value): + self.type = type + self.value = value + + @classmethod + def from_noise_control(cls, noise_control): + return cls(noise_control['type'], int(noise_control['value'])) + + def __eq__(self, other): + return self.type == other.type and self.value == other.value + + def __str__(self): + return '{}++{}'.format(self.type, self.value) + + +class NoiseControlTypes: + NOISE_CONTROL_MAX = NoiseControl('anc', 2) + NOISE_CONTROL_ON = NoiseControl('anc', 1) + NOISE_CONTROL_OFF = NoiseControl('off', 1) + STREET_MODE = NoiseControl('aoc', 1) + STREET_MODE_MAX = NoiseControl('aoc', 2) + + +class Rooms: + CONCERT_HALL = 'concert' + JAZZ_CLUB = 'jazz' + LIVING_ROOM = 'living' + SILENT_ROOM = 'silent' + representation = { + CONCERT_HALL: 'Concert Hall', + JAZZ_CLUB: 'Jazz Club', + LIVING_ROOM: 'Living Room', + SILENT_ROOM: 'Silent Room', + } \ No newline at end of file diff --git a/parrot_zik/parrot_zik_model.py b/parrot_zik/parrot_zik_model.py deleted file mode 100644 index e6a8bc7..0000000 --- a/parrot_zik/parrot_zik_model.py +++ /dev/null @@ -1,222 +0,0 @@ -from .resource_manager import Version1ResourceManager -from .resource_manager import Version2ResourceManager - - -class BatteryStates: - CHARGED = 'charged' - IN_USE = 'in_use' - CHARGING = 'charging' - representation = { - CHARGED: 'Charged', - IN_USE: 'In Use', - CHARGING: 'Charging', - } - -class Rooms: - CONCERT_HALL = 'concert' - JAZZ_CLUB = 'jazz' - LIVING_ROOM = 'living' - SILENT_ROOM = 'silent' - representation = { - CONCERT_HALL: 'Concert Hall', - JAZZ_CLUB: 'Jazz Club', - LIVING_ROOM: 'Living Room', - SILENT_ROOM: 'Silent Room', - } - -class NoiseControl(object): - def __init__(self, type, value): - self.type = type - self.value = value - - @classmethod - def from_noise_control(cls, noise_control): - return cls(noise_control['type'], int(noise_control['value'])) - - def __eq__(self, other): - return self.type == other.type and self.value == other.value - - def __str__(self): - return '{}++{}'.format(self.type, self.value) - -class NoiseControlTypes: - NOISE_CONTROL_MAX = NoiseControl('anc', 2) - NOISE_CONTROL_ON = NoiseControl('anc', 1) - NOISE_CONTROL_OFF = NoiseControl('off', 1) - STREET_MODE = NoiseControl('aoc', 1) - STREET_MODE_MAX = NoiseControl('aoc', 2) - - -class ParrotZikBase(object): - def __init__(self, resource_manager): - self.resource_manager = resource_manager - - @property - def version(self): - return self.resource_manager.api_version - - def refresh_battery(self): - self.resource_manager.fetch('/api/system/battery') - - @property - def battery_state(self): - answer = self.resource_manager.get("/api/system/battery") - return answer.system.battery["state"] - - def get_battery_level(self, field_name): - answer = self.resource_manager.get("/api/system/battery") - return int(answer.system.battery[field_name]) - - @property - def friendly_name(self): - answer = self.resource_manager.get("/api/bluetooth/friendlyname") - return answer.bluetooth["friendlyname"] - - @property - def auto_connect(self): - answer = self.resource_manager.get("/api/system/auto_connection/enabled") - return self._result_to_bool( - answer.system.auto_connection["enabled"]) - - @auto_connect.setter - def auto_connect(self, arg): - self.resource_manager.set("/api/system/auto_connection/enabled", arg) - - @property - def anc_phone_mode(self): - answer = self.resource_manager.get("/api/system/anc_phone_mode/enabled") - return self._result_to_bool( - answer.system.anc_phone_mode["enabled"]) - - def _result_to_bool(self, result): - if result == "true": - return True - elif result == "false": - return False - else: - raise AssertionError(result) - - -class ParrotZikVersion1(ParrotZikBase): - def __init__(self, resource_manager): - super(ParrotZikVersion1, self).__init__( - resource_manager.get_resource_manager( - Version1ResourceManager)) - - @property - def version(self): - answer = self.resource_manager.get('/api/software/version') - return answer.software['version'] - - @property - def battery_level(self): - return int(self.get_battery_level('level')) - - @property - def lou_reed_mode(self): - answer = self.resource_manager.get("/api/audio/specific_mode/enabled") - return self._result_to_bool( - answer.audio.specific_mode["enabled"]) - - @lou_reed_mode.setter - def lou_reed_mode(self, arg): - self.resource_manager.get("/api/audio/specific_mode/enabled", arg) - - @property - def concert_hall(self): - answer = self.resource_manager.get("/api/audio/sound_effect/enabled") - return self._result_to_bool( - answer.audio.sound_effect["enabled"]) - - @concert_hall.setter - def concert_hall(self, arg): - self.resource_manager.get("/api/audio/sound_effect/enabled", arg) - - @property - def cancel_noise(self): - answer = self.resource_manager.get("/api/audio/noise_cancellation/enabled") - return self._result_to_bool( - answer.audio.noise_cancellation["enabled"]) - - @cancel_noise.setter - def cancel_noise(self, arg): - self.resource_manager.set("/api/audio/noise_cancellation/enabled", arg) - - -class ParrotZikVersion2(ParrotZikBase): - def __init__(self, resource_manager): - super(ParrotZikVersion2, self).__init__( - resource_manager.get_resource_manager( - Version2ResourceManager)) - - @property - def version(self): - answer = self.resource_manager.get('/api/software/version') - return answer.software['sip6'] - - @property - def battery_level(self): - return self.get_battery_level('percent') - - @property - def flight_mode(self): - answer = self.resource_manager.get('/api/flight_mode') - return self._result_to_bool(answer.flight_mode['enabled']) - - @flight_mode.setter - def flight_mode(self, arg): - if arg: - self.resource_manager.toggle_on('/api/flight_mode') - else: - self.resource_manager.toggle_off('/api/flight_mode') - - @property - def sound_effect(self): - answer = self.resource_manager.get('/api/audio/sound_effect/enabled') - return self._result_to_bool(answer.audio.sound_effect['enabled']) - - @sound_effect.setter - def sound_effect(self, arg): - self.resource_manager.set('/api/audio/sound_effect/enabled', arg) - - @property - def room(self): - answer = self.resource_manager.get('/api/audio/sound_effect/room_size') - return answer.audio.sound_effect['room_size'] - - @room.setter - def room(self, arg): - self.resource_manager.set('/api/audio/sound_effect/room_size', arg) - - @property - def external_noise(self): - answer = self.resource_manager.get('/api/audio/noise') - return int(answer.audio.noise['external']) - - @property - def internal_noise(self): - answer = self.resource_manager.get('/api/audio/noise') - return int(answer.audio.noise['internal']) - - @property - def angle(self): - answer = self.resource_manager.get('/api/audio/sound_effect/angle') - return int(answer.audio.sound_effect['angle']) - - @angle.setter - def angle(self, arg): - self.resource_manager.set('/api/audio/sound_effect/angle', arg) - - @property - def noise_control(self): - answer = self.resource_manager.get('/api/audio/noise_control') - return NoiseControl.from_noise_control(answer.audio.noise_control) - - @noise_control.setter - def noise_control(self, arg): - pass - - @property - def noise_control_enabled(self): - answer = self.resource_manager.get('/api/audio/noise_control/enabled') - return self._result_to_bool(answer.audio.noise_control['enabled']) -- cgit v1.2.1 From 3d06315f862150a978ba3c8a7a5a3b1672b6e89d Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 14:06:02 +0200 Subject: Proper wrap. --- parrot_zik/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/utils.py b/parrot_zik/utils.py index 18b878d..86f52cd 100644 --- a/parrot_zik/utils.py +++ b/parrot_zik/utils.py @@ -1,3 +1,4 @@ +import functools from threading import Lock import gtk @@ -15,10 +16,10 @@ class repeat(object): def start(self, cls, frequency): self.lock.acquire() if not self.id: + @functools.wraps(self.f) def run(): self.f(cls) return True - self.id = gtk.timeout_add(frequency, run) self.lock.release() -- cgit v1.2.1 From 4573f9f3e95a0d79c576e3fe0f34023bbf6f0898 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 14:56:52 +0200 Subject: Implement head detection setting. --- parrot_zik/interface/version2.py | 17 +++++++++++++++++ parrot_zik/model/version2.py | 9 +++++++++ 2 files changed, 26 insertions(+) (limited to 'parrot_zik') diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index ff21004..c348bb4 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -98,14 +98,23 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.flight_mode = MenuItem("Flight Mode", self.toggle_flight_mode, checkitem=True, visible=False) + self.settings = MenuItem("Settings", None, visible=False) + self.settings_submenu = Menu() + self.settings.set_submenu(self.settings_submenu) + + self.head_detection = MenuItem("Head Detection", self.toggle_head_detection, checkitem=True) + self.settings_submenu.append(self.head_detection) + self.indicator.menu.append(self.room_sound_effect) self.indicator.menu.append(self.noise_cancelation) self.indicator.menu.append(self.flight_mode) + self.indicator.menu.append(self.settings) def activate(self, manager): self.noise_cancelation.show() self.flight_mode.show() self.room_sound_effect.show() + self.settings.show() super(ParrotZikVersion2Interface, self).activate(manager) self._read_noise_cancelation() self.flight_mode.set_active(self.parrot.flight_mode) @@ -130,6 +139,7 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.noise_cancelation.hide() self.flight_mode.hide() self.room_sound_effect.hide() + self.settings.hide() super(ParrotZikVersion2Interface, self).deactivate() def toggle_flight_mode(self, widget): @@ -222,3 +232,10 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): ) for noise_control, menu_item in noise_control_to_menuitem_map: menu_item.set_active(active_noise_control == noise_control) + + def toggle_head_detection(self, widget): + try: + self.parrot.head_detection = self.head_detection.get_active() + self.head_detection.set_active(self.parrot.head_detection) + except resource_manager.DeviceDisconnected: + self.deactivate() \ No newline at end of file diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py index 9ef6267..e0bce44 100644 --- a/parrot_zik/model/version2.py +++ b/parrot_zik/model/version2.py @@ -80,6 +80,15 @@ class ParrotZikVersion2(ParrotZikBase): answer = self.resource_manager.get('/api/audio/noise_control/enabled') return self._result_to_bool(answer.audio.noise_control['enabled']) + @property + def head_detection(self): + answer = self.resource_manager.get('/api/system/head_detection/enabled') + return self._result_to_bool(answer.system.head_detection['enabled']) + + @head_detection.setter + def head_detection(self, arg): + self.resource_manager.set('/api/system/head_detection/enabled', arg) + class NoiseControl(object): def __init__(self, type, value): -- cgit v1.2.1 From 814921eabbfb0cdc41baeb62e4b25da10c9e0212 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 15:11:43 +0200 Subject: Fix connection refused error. --- parrot_zik/bluetooth_paired_devices.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index 726731c..f06286a 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -88,7 +88,10 @@ def connect(): host = first_match["host"] sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) - sock.connect((host, port)) + try: + sock.connect((host, port)) + except bluetooth.btcommon.BluetoothError: + raise ConnectionFailure sock.send('\x00\x03\x00') sock.recv(1024) -- cgit v1.2.1 From 2340cbd0291f6f0f64615a3ed0cb5cfc062ec4f5 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 15:32:31 +0200 Subject: Add more information to unknown response. --- parrot_zik/resource_manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/resource_manager.py b/parrot_zik/resource_manager.py index 8a9cd46..4f90fb6 100644 --- a/parrot_zik/resource_manager.py +++ b/parrot_zik/resource_manager.py @@ -57,7 +57,8 @@ class ResourceManagerBase(object): if data.notify: notifications.append(data.notify) else: - raise AssertionError('Unknown response') + raise AssertionError('Unknown response "{}" for {}'.format( + data, message.request_string)) data = self.receive_message() self.handle_notifications(notifications, message.resource) return data.answer -- cgit v1.2.1 From 1e6c7b96695cb69de8655cbe20e8ddb5baa77a32 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 15:33:35 +0200 Subject: Add sound source model. --- parrot_zik/model/version2.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py index e0bce44..d90d79d 100644 --- a/parrot_zik/model/version2.py +++ b/parrot_zik/model/version2.py @@ -124,4 +124,8 @@ class Rooms: JAZZ_CLUB: 'Jazz Club', LIVING_ROOM: 'Living Room', SILENT_ROOM: 'Silent Room', - } \ No newline at end of file + } + +class SoundSource: + LINE_IN = 'line-in' + A2DP = 'a2dp' -- cgit v1.2.1 From 494e542c8eca97cb01f6e4495588a08136f482a0 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 17:37:54 +0200 Subject: Migrate to newer wersion of beatifulsop. --- parrot_zik/resource_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/resource_manager.py b/parrot_zik/resource_manager.py index 4f90fb6..c2dae2f 100644 --- a/parrot_zik/resource_manager.py +++ b/parrot_zik/resource_manager.py @@ -2,7 +2,7 @@ import bluetooth from operator import itemgetter import sys -from BeautifulSoup import BeautifulSoup +from bs4 import BeautifulSoup from .message import Message -- cgit v1.2.1 From e7089b04e59ae1cf7a24649ec2ef64af56eb7dce Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 17:46:22 +0200 Subject: Use absolute package imports. --- parrot_zik/indicator/__init__.py | 25 ++++++++++--------------- parrot_zik/indicator/gtk_wrapping.py | 2 +- parrot_zik/indicator/linux.py | 2 +- parrot_zik/indicator/mac.py | 6 +++--- parrot_zik/indicator/windows.py | 2 +- parrot_zik/interface/base.py | 6 +++--- parrot_zik/interface/version1.py | 8 ++++---- parrot_zik/interface/version2.py | 12 ++++++------ parrot_zik/model/version1.py | 4 ++-- parrot_zik/model/version2.py | 4 ++-- 10 files changed, 33 insertions(+), 38 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/indicator/__init__.py b/parrot_zik/indicator/__init__.py index aeda305..4194dde 100644 --- a/parrot_zik/indicator/__init__.py +++ b/parrot_zik/indicator/__init__.py @@ -2,22 +2,17 @@ __all__ = ('SysIndicator', 'Menu', 'MenuItem') import sys -if sys.platform == 'linux2': - import linux - import gtk_wrapping - SysIndicator = linux.LinuxIndicator - Menu = gtk_wrapping.GTKMenu - MenuItem = gtk_wrapping.GTKMenuItem +if sys.platform in ['linux', 'linux2']: + from parrot_zik.indicator.linux import LinuxIndicator as SysIndicator + from parrot_zik.indicator.gtk_wrapping import GTKMenuItem as MenuItem + from parrot_zik.indicator.gtk_wrapping import GTKMenu as Menu elif sys.platform == 'win32': - import gtk_wrapping - import windows - SysIndicator = windows.WindowsIndicator - Menu = gtk_wrapping.GTKMenu - MenuItem = gtk_wrapping.GTKMenuItem + from parrot_zik.indicator.windows import WindowsIndicator as SysIndicator + from parrot_zik.indicator.gtk_wrapping import GTKMenuItem as MenuItem + from parrot_zik.indicator.gtk_wrapping import GTKMenu as Menu elif sys.platform == 'darwin': - import mac - SysIndicator = mac.DarwinIndicator - Menu = mac.NSMenu - MenuItem = mac.NSMenuItem + from parrot_zik.indicator.mac import DarwinIndicator as SysIndicator + from parrot_zik.indicator.mac import NSMenuItem as MenuItem + from parrot_zik.indicator.mac import NSMenu as Menu else: raise Exception('Platform not supported') diff --git a/parrot_zik/indicator/gtk_wrapping.py b/parrot_zik/indicator/gtk_wrapping.py index 9494adc..ce78c1d 100644 --- a/parrot_zik/indicator/gtk_wrapping.py +++ b/parrot_zik/indicator/gtk_wrapping.py @@ -1,6 +1,6 @@ import gtk -from .base import MenuItemBase +from parrot_zik.indicator.base import MenuItemBase class GTKMenu(object): diff --git a/parrot_zik/indicator/linux.py b/parrot_zik/indicator/linux.py index fc0f425..278f781 100644 --- a/parrot_zik/indicator/linux.py +++ b/parrot_zik/indicator/linux.py @@ -2,7 +2,7 @@ import os import gtk -from .base import BaseIndicator +from parrot_zik.indicator.base import BaseIndicator class LinuxIndicator(BaseIndicator): diff --git a/parrot_zik/indicator/mac.py b/parrot_zik/indicator/mac.py index 232e010..ceeacb0 100644 --- a/parrot_zik/indicator/mac.py +++ b/parrot_zik/indicator/mac.py @@ -5,9 +5,9 @@ from Foundation import * from AppKit import * from PyObjCTools import AppHelper -from .base import BaseIndicator -from .base import MenuItemBase -from ..status_app_mac import StatusApp +from parrot_zik.indicator.base import BaseIndicator +from parrot_zik.indicator.base import MenuItemBase +from parrot_zik.status_app_mac import StatusApp class DarwinIndicator(BaseIndicator): diff --git a/parrot_zik/indicator/windows.py b/parrot_zik/indicator/windows.py index 79a4ef3..f10c91a 100644 --- a/parrot_zik/indicator/windows.py +++ b/parrot_zik/indicator/windows.py @@ -3,7 +3,7 @@ import tempfile import gtk import os -from .base import BaseIndicator +from parrot_zik.indicator.base import BaseIndicator class WindowsIndicator(BaseIndicator): diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py index 1611874..225e53f 100644 --- a/parrot_zik/interface/base.py +++ b/parrot_zik/interface/base.py @@ -1,6 +1,6 @@ -from .. import resource_manager -from ..indicator import MenuItem -from ..model.base import BatteryStates +from parrot_zik import resource_manager +from parrot_zik.indicator import MenuItem +from parrot_zik.model.base import BatteryStates RECONNECT_FREQUENCY = 5000 diff --git a/parrot_zik/interface/version1.py b/parrot_zik/interface/version1.py index 1af71ec..6ddd1b5 100644 --- a/parrot_zik/interface/version1.py +++ b/parrot_zik/interface/version1.py @@ -1,7 +1,7 @@ -from .. import resource_manager -from ..indicator import MenuItem -from ..interface.base import ParrotZikBaseInterface -from ..model.version1 import ParrotZikVersion1 +from parrot_zik import resource_manager +from parrot_zik.indicator import MenuItem +from parrot_zik.interface.base import ParrotZikBaseInterface +from parrot_zik.model.version1 import ParrotZikVersion1 class ParrotZikVersion1Interface(ParrotZikBaseInterface): diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index c348bb4..74fdcc9 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -1,11 +1,11 @@ import functools -from .. import resource_manager -from ..indicator import MenuItem, Menu -from .base import ParrotZikBaseInterface -from ..model.version2 import ParrotZikVersion2 -from ..model.version2 import NoiseControlTypes -from ..model.version2 import Rooms +from parrot_zik import resource_manager +from parrot_zik.indicator import MenuItem, Menu +from parrot_zik.interface.base import ParrotZikBaseInterface +from parrot_zik.model.version2 import ParrotZikVersion2 +from parrot_zik.model.version2 import NoiseControlTypes +from parrot_zik.model.version2 import Rooms class ParrotZikVersion2Interface(ParrotZikBaseInterface): diff --git a/parrot_zik/model/version1.py b/parrot_zik/model/version1.py index b39684f..f0197e9 100644 --- a/parrot_zik/model/version1.py +++ b/parrot_zik/model/version1.py @@ -1,5 +1,5 @@ -from .base import ParrotZikBase -from ..resource_manager import Version1ResourceManager +from parrot_zik.model.base import ParrotZikBase +from parrot_zik.resource_manager import Version1ResourceManager class ParrotZikVersion1(ParrotZikBase): diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py index d90d79d..11b4d51 100644 --- a/parrot_zik/model/version2.py +++ b/parrot_zik/model/version2.py @@ -1,5 +1,5 @@ -from .base import ParrotZikBase -from ..resource_manager import Version2ResourceManager +from parrot_zik.model.base import ParrotZikBase +from parrot_zik.resource_manager import Version2ResourceManager class ParrotZikVersion2(ParrotZikBase): -- cgit v1.2.1 From 6049e5e3a9f77f4b784eeaf90ace6905feb1afd7 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 18:55:12 +0200 Subject: Move auto connection to setttings. --- parrot_zik/interface/base.py | 15 +++++++++++---- parrot_zik/interface/version2.py | 6 ------ 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py index 225e53f..b93c6c0 100644 --- a/parrot_zik/interface/base.py +++ b/parrot_zik/interface/base.py @@ -1,4 +1,5 @@ from parrot_zik import resource_manager +from parrot_zik.indicator import Menu from parrot_zik.indicator import MenuItem from parrot_zik.model.base import BatteryStates @@ -15,12 +16,18 @@ class ParrotZikBaseInterface(object): visible=False) self.firmware_version = MenuItem("Firmware Version:", None, sensitive=False, visible=False) + self.settings = MenuItem("Settings", None, visible=False) + self.settings_submenu = Menu() + self.settings.set_submenu(self.settings_submenu) + self.auto_connection = MenuItem("Auto Connection", self.toggle_auto_connection, - checkitem=True, visible=False) + checkitem=True) + self.settings_submenu.append(self.auto_connection) + self.indicator.menu.append(self.battery_level) self.indicator.menu.append(self.battery_state) self.indicator.menu.append(self.firmware_version) - self.indicator.menu.append(self.auto_connection) + self.indicator.menu.append(self.settings) def activate(self, manager): self.parrot = self.parrot_class(manager) @@ -32,7 +39,7 @@ class ParrotZikBaseInterface(object): self.battery_level.show() self.battery_state.show() self.firmware_version.show() - self.auto_connection.show() + self.settings.show() self.indicator.active_interface = self self.indicator.menu.reposition() @@ -45,7 +52,7 @@ class ParrotZikBaseInterface(object): self.battery_level.hide() self.battery_state.hide() self.firmware_version.hide() - self.auto_connection.hide() + self.settings.hide() self.indicator.menu.reposition() self.indicator.active_interface = None self.indicator.setIcon("zik-audio-headset") diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index 74fdcc9..08af737 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -98,9 +98,6 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.flight_mode = MenuItem("Flight Mode", self.toggle_flight_mode, checkitem=True, visible=False) - self.settings = MenuItem("Settings", None, visible=False) - self.settings_submenu = Menu() - self.settings.set_submenu(self.settings_submenu) self.head_detection = MenuItem("Head Detection", self.toggle_head_detection, checkitem=True) self.settings_submenu.append(self.head_detection) @@ -108,13 +105,11 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.indicator.menu.append(self.room_sound_effect) self.indicator.menu.append(self.noise_cancelation) self.indicator.menu.append(self.flight_mode) - self.indicator.menu.append(self.settings) def activate(self, manager): self.noise_cancelation.show() self.flight_mode.show() self.room_sound_effect.show() - self.settings.show() super(ParrotZikVersion2Interface, self).activate(manager) self._read_noise_cancelation() self.flight_mode.set_active(self.parrot.flight_mode) @@ -139,7 +134,6 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.noise_cancelation.hide() self.flight_mode.hide() self.room_sound_effect.hide() - self.settings.hide() super(ParrotZikVersion2Interface, self).deactivate() def toggle_flight_mode(self, widget): -- cgit v1.2.1 From 48a0498d56e54e01b9eed06af00b5ba127fe9134 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 18:58:56 +0200 Subject: First get data from api then show. --- parrot_zik/interface/base.py | 1 - parrot_zik/interface/version1.py | 8 +++++--- parrot_zik/interface/version2.py | 8 +++++--- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py index b93c6c0..90caa02 100644 --- a/parrot_zik/interface/base.py +++ b/parrot_zik/interface/base.py @@ -41,7 +41,6 @@ class ParrotZikBaseInterface(object): self.firmware_version.show() self.settings.show() self.indicator.active_interface = self - self.indicator.menu.reposition() @property def parrot_class(self): diff --git a/parrot_zik/interface/version1.py b/parrot_zik/interface/version1.py index 6ddd1b5..d0a1b2b 100644 --- a/parrot_zik/interface/version1.py +++ b/parrot_zik/interface/version1.py @@ -22,14 +22,16 @@ class ParrotZikVersion1Interface(ParrotZikBaseInterface): self.indicator.menu.append(self.concert_hall_mode) def activate(self, manager): - self.noise_cancelation.show() - self.lou_reed_mode.show() - self.concert_hall_mode.show() super(ParrotZikVersion1Interface, self).activate(manager) self.noise_cancelation.set_active(self.parrot.cancel_noise) self.lou_reed_mode.set_active(self.parrot.lou_reed_mode) self.concert_hall_mode.set_active(self.parrot.concert_hall) + self.noise_cancelation.show() + self.lou_reed_mode.show() + self.concert_hall_mode.show() + self.indicator.menu.reposition() + def deactivate(self): self.noise_cancelation.hide() self.lou_reed_mode.hide() diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index 08af737..b378a88 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -107,9 +107,6 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.indicator.menu.append(self.flight_mode) def activate(self, manager): - self.noise_cancelation.show() - self.flight_mode.show() - self.room_sound_effect.show() super(ParrotZikVersion2Interface, self).activate(manager) self._read_noise_cancelation() self.flight_mode.set_active(self.parrot.flight_mode) @@ -130,6 +127,11 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.angle_150.set_sensitive(sound_effect) self.angle_180.set_sensitive(sound_effect) + self.noise_cancelation.show() + self.flight_mode.show() + self.room_sound_effect.show() + self.indicator.menu.reposition() + def deactivate(self): self.noise_cancelation.hide() self.flight_mode.hide() -- cgit v1.2.1 From feac48c21e390cbf4e2ecf3b3c7a12d89c1e3436 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 20:39:17 +0200 Subject: Ignore dbus exception. --- parrot_zik/bluetooth_paired_devices.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index f06286a..cec6d8e 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -1,3 +1,4 @@ +import dbus import sys import re import os @@ -17,16 +18,24 @@ def get_parrot_zik_mac(): p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}|' 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') if sys.platform == "linux2": - bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) - if bluetooth_on == 1: - out = os.popen("bluez-test-device list").read() - res = p.findall(out) - if len(res) > 0: - return res[0] - else: - raise DeviceNotConnected + try: + bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) + except dbus.exceptions.DBusException: + pass else: - raise BluetoothIsNotOn + if bluetooth_on == 1: + try: + out = os.popen("bluez-test-device list").read() + except dbus.exceptions.DBusException: + pass + else: + res = p.findall(out) + if len(res) > 0: + return res[0] + else: + raise DeviceNotConnected + else: + raise BluetoothIsNotOn elif sys.platform == "darwin": fd = open("/Library/Preferences/com.apple.Bluetooth.plist", "rb") plist = binplist.BinaryPlist(file_obj=fd) -- cgit v1.2.1 From deedbdca9564168460b24ee9549d084e2749fa1d Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Mon, 15 Jun 2015 20:49:11 +0200 Subject: Refactor. --- parrot_zik/bluetooth_paired_devices.py | 101 +++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 44 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index cec6d8e..e518161 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -14,57 +14,70 @@ else: import _winreg -def get_parrot_zik_mac(): - p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}|' - 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') - if sys.platform == "linux2": +p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}|' + 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') + +def get_parrot_zik_mac_linux(): + try: + bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) + except dbus.exceptions.DBusException: + pass + else: + if bluetooth_on == 1: try: - bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) + out = os.popen("bluez-test-device list").read() except dbus.exceptions.DBusException: pass else: - if bluetooth_on == 1: - try: - out = os.popen("bluez-test-device list").read() - except dbus.exceptions.DBusException: - pass - else: - res = p.findall(out) - if len(res) > 0: - return res[0] - else: - raise DeviceNotConnected - else: - raise BluetoothIsNotOn - elif sys.platform == "darwin": - fd = open("/Library/Preferences/com.apple.Bluetooth.plist", "rb") - plist = binplist.BinaryPlist(file_obj=fd) - parsed_plist = plist.Parse() - try: - for mac in parsed_plist['PairedDevices']: - if p.match(mac.replace("-", ":")): - return mac.replace("-", ":") + res = p.findall(out) + if len(res) > 0: + return res[0] else: raise DeviceNotConnected - except Exception: - pass + else: + raise BluetoothIsNotOn - elif sys.platform == "win32": - aReg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) - aKey = _winreg.OpenKey( - aReg, 'SYSTEM\CurrentControlSet\Services\ - BTHPORT\Parameters\Devices') - for i in range(10): - try: - asubkey_name = _winreg.EnumKey(aKey, i) - mac = ':'.join(asubkey_name[i:i+2] for i in range(0, 12, 2)) - res = p.findall(mac) - if len(res) > 0: - return res[0] - else: - raise DeviceNotConnected - except EnvironmentError: - pass + +def get_parrot_zik_mac_darwin(): + fd = open("/Library/Preferences/com.apple.Bluetooth.plist", "rb") + plist = binplist.BinaryPlist(file_obj=fd) + parsed_plist = plist.Parse() + try: + for mac in parsed_plist['PairedDevices']: + if p.match(mac.replace("-", ":")): + return mac.replace("-", ":") + else: + raise DeviceNotConnected + except Exception: + pass + + +def get_parrot_zik_mac_windows(): + aReg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) + aKey = _winreg.OpenKey( + aReg, 'SYSTEM\CurrentControlSet\Services\ + BTHPORT\Parameters\Devices') + for i in range(10): + try: + asubkey_name = _winreg.EnumKey(aKey, i) + mac = ':'.join(asubkey_name[i:i+2] for i in range(0, 12, 2)) + res = p.findall(mac) + if len(res) > 0: + return res[0] + else: + raise DeviceNotConnected + except EnvironmentError: + pass + + +if sys.platform in ['linux', 'linux2']: + get_parrot_zik_mac = get_parrot_zik_mac_linux +elif sys.platform == 'darwin': + get_parrot_zik_mac = get_parrot_zik_mac_darwin +elif sys.platform == 'win32': + get_parrot_zik_mac = get_parrot_zik_mac_windows +else: + raise AssertionError('Platform not supported') def connect(): -- cgit v1.2.1 From 8236f6229e420406cfc64a55c8b358f7cb0357a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20S=C3=A1nchez?= Date: Fri, 3 Jul 2015 12:02:51 +0200 Subject: Fixed setter properties in version1 model --- parrot_zik/model/version1.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/model/version1.py b/parrot_zik/model/version1.py index f0197e9..324cc9f 100644 --- a/parrot_zik/model/version1.py +++ b/parrot_zik/model/version1.py @@ -25,7 +25,7 @@ class ParrotZikVersion1(ParrotZikBase): @lou_reed_mode.setter def lou_reed_mode(self, arg): - self.resource_manager.get("/api/audio/specific_mode/enabled", arg) + self.resource_manager.set("/api/audio/specific_mode/enabled", arg) @property def concert_hall(self): @@ -35,7 +35,7 @@ class ParrotZikVersion1(ParrotZikBase): @concert_hall.setter def concert_hall(self, arg): - self.resource_manager.get("/api/audio/sound_effect/enabled", arg) + self.resource_manager.set("/api/audio/sound_effect/enabled", arg) @property def cancel_noise(self): @@ -45,4 +45,4 @@ class ParrotZikVersion1(ParrotZikBase): @cancel_noise.setter def cancel_noise(self, arg): - self.resource_manager.set("/api/audio/noise_cancellation/enabled", arg) \ No newline at end of file + self.resource_manager.set("/api/audio/noise_cancellation/enabled", arg) -- cgit v1.2.1 From 0973bb1a2f8e46d7dffe67063f0d1415b3397619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20S=C3=A1nchez?= Date: Fri, 3 Jul 2015 12:07:31 +0200 Subject: Use other method to get bluetooth devices list in linux --- parrot_zik/bluetooth_paired_devices.py | 42 ++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index e518161..8eba2ce 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -1,7 +1,7 @@ import dbus import sys import re -import os +from subprocess import Popen, PIPE, STDOUT from .resource_manager import GenericResourceManager @@ -17,15 +17,28 @@ else: p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}|' 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') -def get_parrot_zik_mac_linux(): + +def get_parrot_zik_mac_linux_using_bluez_test(): try: - bluetooth_on = int(os.popen('bluez-test-adapter powered').read()) + pipe = Popen( + ['bluez-test-adapter', 'powered'], + stdout=PIPE, + stdin=PIPE, + stderr=STDOUT + ) + bluetooth_on = int(pipe.communicate()) except dbus.exceptions.DBusException: pass else: if bluetooth_on == 1: try: - out = os.popen("bluez-test-device list").read() + pipe = Popen( + ['bluez-test-device', 'list'], + stdout=PIPE, + stdin=PIPE, + stderr=STDOUT + ) + out = pipe.communicate() except dbus.exceptions.DBusException: pass else: @@ -38,6 +51,27 @@ def get_parrot_zik_mac_linux(): raise BluetoothIsNotOn +def get_parrot_zik_mac_linux_using_bluetoothcmd(): + pipe = Popen(['bluetoothctl'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) + res = pipe.communicate("exit") + if len(res) > 0 and res[0]: + match = p.search(res[0]) + if match: + return match.group(0) + + raise DeviceNotConnected + + +def get_parrot_zik_mac_linux(): + try: + get_parrot_zik_mac_linux_using_bluez_test() + except OSError as e: + if e.errno == 2: + # File not found, probably it means that bluez utils are not + # installed + return get_parrot_zik_mac_linux_using_bluetoothcmd() + + def get_parrot_zik_mac_darwin(): fd = open("/Library/Preferences/com.apple.Bluetooth.plist", "rb") plist = binplist.BinaryPlist(file_obj=fd) -- cgit v1.2.1 From 6eba736eb54ebecef14c4bd2b03df29b82f16f4b Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 3 Jul 2015 13:20:40 +0200 Subject: Fix mistakes and refactor. --- parrot_zik/bluetooth_paired_devices.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index 8eba2ce..0a40481 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -18,31 +18,24 @@ p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') -def get_parrot_zik_mac_linux_using_bluez_test(): +def get_parrot_zik_mac_bluez(): + pipe = Popen(['bluez-test-adapter', 'powered'], stdout=PIPE, stdin=PIPE, + stderr=STDOUT) try: - pipe = Popen( - ['bluez-test-adapter', 'powered'], - stdout=PIPE, - stdin=PIPE, - stderr=STDOUT - ) - bluetooth_on = int(pipe.communicate()) + stdout, stderr = pipe.communicate() except dbus.exceptions.DBusException: pass else: + bluetooth_on = int(stdout) if bluetooth_on == 1: + pipe = Popen(['bluez-test-device', 'list'], stdout=PIPE, stdin=PIPE, + stderr=STDOUT) try: - pipe = Popen( - ['bluez-test-device', 'list'], - stdout=PIPE, - stdin=PIPE, - stderr=STDOUT - ) - out = pipe.communicate() + stdout, stderr = pipe.communicate() except dbus.exceptions.DBusException: pass else: - res = p.findall(out) + res = p.findall(stdout) if len(res) > 0: return res[0] else: @@ -51,7 +44,7 @@ def get_parrot_zik_mac_linux_using_bluez_test(): raise BluetoothIsNotOn -def get_parrot_zik_mac_linux_using_bluetoothcmd(): +def get_parrot_zik_mac_bluetoothcmd(): pipe = Popen(['bluetoothctl'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) res = pipe.communicate("exit") if len(res) > 0 and res[0]: @@ -64,12 +57,10 @@ def get_parrot_zik_mac_linux_using_bluetoothcmd(): def get_parrot_zik_mac_linux(): try: - get_parrot_zik_mac_linux_using_bluez_test() + return get_parrot_zik_mac_bluez() except OSError as e: if e.errno == 2: - # File not found, probably it means that bluez utils are not - # installed - return get_parrot_zik_mac_linux_using_bluetoothcmd() + return get_parrot_zik_mac_bluetoothcmd() def get_parrot_zik_mac_darwin(): -- cgit v1.2.1 From 3d455057798db862b5e1fb510d2f4aceaf71515a Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Fri, 3 Jul 2015 13:40:07 +0200 Subject: Refactor. --- parrot_zik/bluetooth_paired_devices.py | 80 ++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 33 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/bluetooth_paired_devices.py b/parrot_zik/bluetooth_paired_devices.py index 0a40481..905819f 100644 --- a/parrot_zik/bluetooth_paired_devices.py +++ b/parrot_zik/bluetooth_paired_devices.py @@ -18,49 +18,63 @@ p = re.compile('90:03:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2 'A0:14:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}') -def get_parrot_zik_mac_bluez(): - pipe = Popen(['bluez-test-adapter', 'powered'], stdout=PIPE, stdin=PIPE, - stderr=STDOUT) - try: - stdout, stderr = pipe.communicate() - except dbus.exceptions.DBusException: - pass - else: - bluetooth_on = int(stdout) - if bluetooth_on == 1: - pipe = Popen(['bluez-test-device', 'list'], stdout=PIPE, stdin=PIPE, - stderr=STDOUT) - try: - stdout, stderr = pipe.communicate() - except dbus.exceptions.DBusException: - pass - else: - res = p.findall(stdout) - if len(res) > 0: - return res[0] - else: - raise DeviceNotConnected +class BluetoothDeviceManager(object): + def is_bluetooth_on(self): + raise NotImplementedError + + def get_mac(self): + raise NotImplementedError + + +class BluezBluetoothDeviceManager(BluetoothDeviceManager): + def is_bluetooth_on(self): + pipe = Popen(['bluez-test-adapter', 'powered'], stdout=PIPE, stdin=PIPE, + stderr=STDOUT) + try: + stdout, stderr = pipe.communicate() + except dbus.exceptions.DBusException: + pass + else: + return bool(stdout.strip()) + + def get_mac(self): + pipe = Popen(['bluez-test-device', 'list'], stdout=PIPE, stdin=PIPE, + stderr=STDOUT) + try: + stdout, stderr = pipe.communicate() + except dbus.exceptions.DBusException: + pass else: - raise BluetoothIsNotOn + res = p.findall(stdout) + if len(res) > 0: + return res[0] + else: + raise DeviceNotConnected -def get_parrot_zik_mac_bluetoothcmd(): - pipe = Popen(['bluetoothctl'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) - res = pipe.communicate("exit") - if len(res) > 0 and res[0]: - match = p.search(res[0]) - if match: - return match.group(0) +class BluetoothCmdDeviceManager(BluetoothDeviceManager): + def is_bluetooth_on(self): + return True - raise DeviceNotConnected + def get_mac(self): + pipe = Popen(['bluetoothctl'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) + res = pipe.communicate("exit") + if len(res) > 0 and res[0]: + match = p.search(res[0]) + if match: + return match.group(0) + raise DeviceNotConnected def get_parrot_zik_mac_linux(): + bluez_manager = BluezBluetoothDeviceManager() try: - return get_parrot_zik_mac_bluez() + bluez_manager.is_bluetooth_on() + return bluez_manager.get_mac() except OSError as e: if e.errno == 2: - return get_parrot_zik_mac_bluetoothcmd() + bluetoothcmd_manager = BluetoothCmdDeviceManager() + return bluetoothcmd_manager.get_mac() def get_parrot_zik_mac_darwin(): -- cgit v1.2.1 From 22e903f15887bff972ecd0f28c0ee485e918c3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20S=C3=A1nchez?= Date: Fri, 3 Jul 2015 13:33:26 +0200 Subject: Fixed cast when the value is an empty string --- parrot_zik/model/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'parrot_zik') diff --git a/parrot_zik/model/base.py b/parrot_zik/model/base.py index 0cd4652..d722788 100644 --- a/parrot_zik/model/base.py +++ b/parrot_zik/model/base.py @@ -16,7 +16,7 @@ class ParrotZikBase(object): def get_battery_level(self, field_name): answer = self.resource_manager.get("/api/system/battery") - return int(answer.system.battery[field_name]) + return int(answer.system.battery[field_name] or 0) @property def friendly_name(self): -- cgit v1.2.1 From 0200800656ff1add2df9c662ade6a52a2adb9f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20S=C3=A1nchez?= Date: Fri, 3 Jul 2015 13:22:02 +0200 Subject: Fixed _result_to_bool() assertion when a values has some strange status --- parrot_zik/model/base.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'parrot_zik') diff --git a/parrot_zik/model/base.py b/parrot_zik/model/base.py index d722788..fdacde0 100644 --- a/parrot_zik/model/base.py +++ b/parrot_zik/model/base.py @@ -44,6 +44,8 @@ class ParrotZikBase(object): return True elif result == "false": return False + elif result == "invalid_on": + return True else: raise AssertionError(result) -- cgit v1.2.1 From 4098b681ca9bc4b57e8283f6f21d139fc1c9940b Mon Sep 17 00:00:00 2001 From: Max Grishkin Date: Tue, 8 Dec 2015 23:44:28 +0300 Subject: Use gtk on linux --- parrot_zik/indicator/__init__.py | 11 ++++++-- parrot_zik/indicator/gtk_wrapping.py | 6 +++++ parrot_zik/indicator/linux.py | 49 +++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 16 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/indicator/__init__.py b/parrot_zik/indicator/__init__.py index 4194dde..156f7de 100644 --- a/parrot_zik/indicator/__init__.py +++ b/parrot_zik/indicator/__init__.py @@ -3,10 +3,17 @@ __all__ = ('SysIndicator', 'Menu', 'MenuItem') import sys if sys.platform in ['linux', 'linux2']: - from parrot_zik.indicator.linux import LinuxIndicator as SysIndicator + import argparse + parser = argparse.ArgumentParser() + parser.add_argument("--gtk", action="store_true") + args = parser.parse_args() + if args.gtk: + from parrot_zik.indicator.linux import LinuxGtkIndicator as SysIndicator + else: + from parrot_zik.indicator.linux import LinuxAppIndicator as SysIndicator from parrot_zik.indicator.gtk_wrapping import GTKMenuItem as MenuItem from parrot_zik.indicator.gtk_wrapping import GTKMenu as Menu -elif sys.platform == 'win32': +elif sys.platform in ['win32']: from parrot_zik.indicator.windows import WindowsIndicator as SysIndicator from parrot_zik.indicator.gtk_wrapping import GTKMenuItem as MenuItem from parrot_zik.indicator.gtk_wrapping import GTKMenu as Menu diff --git a/parrot_zik/indicator/gtk_wrapping.py b/parrot_zik/indicator/gtk_wrapping.py index ce78c1d..6d4a5a8 100644 --- a/parrot_zik/indicator/gtk_wrapping.py +++ b/parrot_zik/indicator/gtk_wrapping.py @@ -13,6 +13,12 @@ class GTKMenu(object): def reposition(self): self.gtk_menu.reposition() + def popup(self, *args, **kwargs): + self.gtk_menu.popup(*args, **kwargs) + + def poVpdown(self, *args, **kwargs): + pass + class GTKMenuItem(MenuItemBase): def __init__(self, name, action, sensitive=True, checkitem=False, visible=True): diff --git a/parrot_zik/indicator/linux.py b/parrot_zik/indicator/linux.py index 278f781..f6f9cfc 100644 --- a/parrot_zik/indicator/linux.py +++ b/parrot_zik/indicator/linux.py @@ -6,17 +6,7 @@ from parrot_zik.indicator.base import BaseIndicator class LinuxIndicator(BaseIndicator): - def __init__(self, icon, menu): - import appindicator - self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') - if not os.path.isdir(self.icon_directory): - self.icon_directory = os.path.join('share', 'icons', 'zik') - statusicon = appindicator.Indicator( - "new-parrotzik-indicator", "indicator-messages", - appindicator.CATEGORY_APPLICATION_STATUS) - statusicon.set_status(appindicator.STATUS_ACTIVE) - statusicon.set_icon_theme_path(self.icon_directory) - statusicon.set_menu(menu.gtk_menu) + def __init__(self, icon, menu, statusicon): super(LinuxIndicator, self).__init__(icon, menu, statusicon) def gtk_right_click_event(self, icon, button, time): @@ -28,9 +18,6 @@ class LinuxIndicator(BaseIndicator): self.menu_shown = False self.menu.poVpdown() - def setIcon(self, name): - self.statusicon.set_icon(name) - @classmethod def main(cls): gtk.main() @@ -46,3 +33,37 @@ class LinuxIndicator(BaseIndicator): about_dialog.set_authors(["Dmitry Moiseev m0sia@m0sia.ru"]) about_dialog.run() about_dialog.destroy() + + +class LinuxAppIndicator(LinuxIndicator): + def __init__(self, icon, menu): + import appindicator + self.icon_directory = os.path.join('/', 'usr', 'share', 'icons', 'zik') + if not os.path.isdir(self.icon_directory): + self.icon_directory = os.path.join('share', 'icons', 'zik') + statusicon = appindicator.Indicator( + "new-parrotzik-indicator", "indicator-messages", + appindicator.CATEGORY_APPLICATION_STATUS) + statusicon.set_status(appindicator.STATUS_ACTIVE) + statusicon.set_icon_theme_path(self.icon_directory) + statusicon.set_menu(menu.gtk_menu) + super(LinuxIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.set_icon(name) + + + +class LinuxGtkIndicator(LinuxIndicator): + def __init__(self, icon, menu): + self.icon_directory = os.path.join( + '/usr', 'share', 'icons/') + self.menu_shown = False + statusicon = gtk.StatusIcon() + statusicon.connect("popup-menu", self.gtk_right_click_event) + statusicon.set_tooltip("Parrot Zik") + super(LinuxIndicator, self).__init__(icon, menu, statusicon) + + def setIcon(self, name): + self.statusicon.set_from_file(self.icon_directory + name + '.png') + -- cgit v1.2.1 From d6e3eb4ffb88959503cf41870dab72446ace6b46 Mon Sep 17 00:00:00 2001 From: Pavel Salomatov Date: Fri, 5 Feb 2016 15:41:47 +0300 Subject: Added functionality to change noise cancellation mode "Head detection" now initializes on startup --- parrot_zik/interface/version2.py | 14 ++++++++------ parrot_zik/model/version2.py | 4 ++-- parrot_zik/resource_manager.py | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) (limited to 'parrot_zik') diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py index b378a88..e6076ed 100644 --- a/parrot_zik/interface/version2.py +++ b/parrot_zik/interface/version2.py @@ -23,23 +23,23 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.noise_control_cancelation_max = MenuItem( "Max Calcelation", functools.partial( self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_MAX), checkitem=True, sensitive=False) + NoiseControlTypes.NOISE_CONTROL_MAX), checkitem=True) self.noise_control_cancelation_on = MenuItem( "Normal Cancelation", functools.partial( self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_ON), checkitem=True, sensitive=False) + NoiseControlTypes.NOISE_CONTROL_ON), checkitem=True) self.noise_control_off = MenuItem( "Off", functools.partial( self.toggle_noise_cancelation, - NoiseControlTypes.NOISE_CONTROL_OFF), checkitem=True, sensitive=False) + NoiseControlTypes.NOISE_CONTROL_OFF), checkitem=True) self.noise_control_street_mode = MenuItem( "Street Mode", functools.partial( self.toggle_noise_cancelation, - NoiseControlTypes.STREET_MODE), checkitem=True, sensitive=False) + NoiseControlTypes.STREET_MODE), checkitem=True) self.noise_control_street_mode_max = MenuItem( "Street Mode Max", functools.partial( self.toggle_noise_cancelation, - NoiseControlTypes.STREET_MODE_MAX), checkitem=True, sensitive=False) + NoiseControlTypes.STREET_MODE_MAX), checkitem=True) self.noise_cancelation_submenu.append(self.noise_control_cancelation_max) self.noise_cancelation_submenu.append(self.noise_control_cancelation_on) self.noise_cancelation_submenu.append(self.noise_control_off) @@ -112,6 +112,8 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.flight_mode.set_active(self.parrot.flight_mode) self._read_sound_effect_room() self._read_sound_effect_angle() + self.head_detection.set_active(self.parrot.head_detection) + sound_effect = self.parrot.sound_effect self.room_sound_effect_enabled.set_active(sound_effect) @@ -234,4 +236,4 @@ class ParrotZikVersion2Interface(ParrotZikBaseInterface): self.parrot.head_detection = self.head_detection.get_active() self.head_detection.set_active(self.parrot.head_detection) except resource_manager.DeviceDisconnected: - self.deactivate() \ No newline at end of file + self.deactivate() diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py index 11b4d51..0cbdc1a 100644 --- a/parrot_zik/model/version2.py +++ b/parrot_zik/model/version2.py @@ -73,7 +73,7 @@ class ParrotZikVersion2(ParrotZikBase): @noise_control.setter def noise_control(self, arg): - pass + self.resource_manager.set('/api/audio/noise_control', arg) @property def noise_control_enabled(self): @@ -103,7 +103,7 @@ class NoiseControl(object): return self.type == other.type and self.value == other.value def __str__(self): - return '{}++{}'.format(self.type, self.value) + return '{}&value={}'.format(self.type, self.value) class NoiseControlTypes: diff --git a/parrot_zik/resource_manager.py b/parrot_zik/resource_manager.py index c2dae2f..aa141cb 100644 --- a/parrot_zik/resource_manager.py +++ b/parrot_zik/resource_manager.py @@ -132,7 +132,7 @@ class Version2ResourceManager(ResourceManagerBase): '/api/audio/equalizer/preset_value': ['set'], '/api/audio/noise_cancellation/enabled': ['get', 'set'], '/api/audio/noise_control/enabled': ['get', 'set'], - '/api/audio/noise_control': ['get'], + '/api/audio/noise_control': ['get', 'set'], '/api/audio/noise_control/phone_mode': ['get', 'set'], '/api/audio/noise': ['get'], '/api/audio/param_equalizer/value': ['set'], -- cgit v1.2.1