aboutsummaryrefslogtreecommitdiff
path: root/parrot_zik
diff options
context:
space:
mode:
Diffstat (limited to 'parrot_zik')
-rw-r--r--parrot_zik/interface/base.py93
-rw-r--r--parrot_zik/interface/version2.py317
-rw-r--r--parrot_zik/model/version2.py31
-rwxr-xr-xparrot_zik/parrot_zik_tray.py80
-rw-r--r--parrot_zik/utils.py32
5 files changed, 173 insertions, 380 deletions
diff --git a/parrot_zik/interface/base.py b/parrot_zik/interface/base.py
index 90caa02..75f368c 100644
--- a/parrot_zik/interface/base.py
+++ b/parrot_zik/interface/base.py
@@ -1,45 +1,21 @@
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
-RECONNECT_FREQUENCY = 5000
+RECONNECT_FREQUENCY = 5
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.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)
- 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.settings)
+ self.battery_level = ""
+ self.battery_state = ""
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.settings.show()
+ self.indicator.info({"info": "Connected to: " + self.parrot.friendly_name})
+ self.firmware_version = self.parrot.version
+ self.auto_connection = self.parrot.auto_connect
self.indicator.active_interface = self
@property
@@ -48,48 +24,45 @@ class ParrotZikBaseInterface(object):
def deactivate(self):
self.parrot = None
- self.battery_level.hide()
- self.battery_state.hide()
- self.firmware_version.hide()
- self.settings.hide()
- self.indicator.menu.reposition()
+ self.battery_level = ""
+ self.battery_mode = ""
+ self.firmware_version = ""
self.indicator.active_interface = None
- self.indicator.setIcon("zik-audio-headset")
- self.indicator.info('Lost Connection')
- self.indicator.reconnect.start(self.indicator, RECONNECT_FREQUENCY)
+ self.indicator.info({"error": "Lost Connection"})
+ self.indicator.reconnect(RECONNECT_FREQUENCY)
- def toggle_auto_connection(self, widget):
+ def read_auto_connection(self):
+ """
+ Return auto connection status.
+ """
try:
- self.parrot.auto_connect = self.auto_connection.get_active()
- self.auto_connection.set_active(self.parrot.auto_connect)
+ data = {"data": {"auto_connection": self.parrot.auto_connect}}
+ self.indicator.info(data)
+ return data
except resource_manager.DeviceDisconnected:
self.deactivate()
- def refresh(self):
- self.read_battery()
+ def toggle_auto_connection(self, auto_connection):
+ """
+ Set auto connection mode. Must be 'true' or 'false'.
+ """
+ try:
+ self.parrot.auto_connect = auto_connection
+ return self.read_auto_connection()
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
def read_battery(self):
+ """
+ Return battery level and battery state
+ """
try:
self.parrot.refresh_battery()
battery_level = self.parrot.battery_level
battery_state = self.parrot.battery_state
+ except AssertionError as e:
+ print(e)
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))
+ return {"data": {"state": BatteryStates.representation[battery_state], "level": battery_level}}
diff --git a/parrot_zik/interface/version2.py b/parrot_zik/interface/version2.py
index e3ad474..b00eb77 100644
--- a/parrot_zik/interface/version2.py
+++ b/parrot_zik/interface/version2.py
@@ -1,239 +1,170 @@
import functools
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
+from parrot_zik.model.version2 import Angles
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 Cancelation", functools.partial(
- self.toggle_noise_cancelation,
- 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)
- self.noise_control_off = MenuItem(
- "Off", functools.partial(
- self.toggle_noise_cancelation,
- 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)
- self.noise_control_street_mode_max = MenuItem(
- "Street Mode Max", functools.partial(
- self.toggle_noise_cancelation,
- 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)
- 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.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.noise_control_types = NoiseControlTypes.representation
+ self.rooms_types = Rooms.representation
+ self.angles = Angles.representation
def activate(self, manager):
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()
- self.head_detection.set_active(self.parrot.head_detection)
-
- 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)
-
- 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()
- self.room_sound_effect.hide()
super(ParrotZikVersion2Interface, self).deactivate()
- def toggle_flight_mode(self, widget):
+ def toggle_flight_mode(self, flight_mode):
try:
- self.parrot.flight_mode = self.flight_mode.get_active()
- self.flight_mode.set_active(self.parrot.flight_mode)
+ #self.parrot.flight_mode = flight_mode
+ warning = {'warning': 'Sorry for this moment this function is disable because you need to connect your system on headset with NFC to disable flight mode.'}
+ self.indicator.info(warning)
+ return warning
except resource_manager.DeviceDisconnected:
self.deactivate()
- def toggle_room(self, room, widget):
+ def read_flight_mode(self):
try:
- if not self.room_dirty:
+ data = {'data': {'flight_mode': self.parrot.flight_mode}}
+ self.indicator.info(data)
+ return data
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def toggle_sound_effect_room(self, room):
+ """
+ Define ambiance room. Muse be one of the following room:
+ 'concert', 'jazz', 'living', 'silent'.
+ """
+ try:
+ if room in self.rooms_types:
self.parrot.room = room
- self.room_dirty = True
- self._read_sound_effect_room()
- self.room_dirty = False
+ data = {'data': {'sound_effect_room': self.parrot.room}}
+ self.indicator.info(data)
+ return data
+ else:
+ data = {'error': "'" + room + "' is not a correct room name"}
+ self.indicator.info(data)
+ return data
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def read_sound_effect_room(self):
+ """
+ Return current ambiance room value.
+ """
+ try:
+ data = {'data': {'sound_effect_type': self.parrot.room}}
+ self.indicator.info(data)
+ return data
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def toggle_sound_effect_room_enabled(self, sound_effect):
+ """
+ Enable or disable the ambiance room. Must be 'true' or 'false'.
+ """
+ try:
+ self.parrot.sound_effect = sound_effect
+ return self.read_sound_effect_room_enabled()
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):
+ def read_sound_effect_room_enabled(self):
+ """
+ Return current ambiance room status.
+ """
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)
+ data = {'data': {'sound_effect_state': self.parrot.sound_effect}}
+ self.indicator.info(data)
+ return data
except resource_manager.DeviceDisconnected:
self.deactivate()
- def toggle_angle(self, angle, widget):
+ def toggle_sound_effect_angle(self, angle):
+ """
+ Define angle, must be one of the following interger:
+ 30, 60, 90, 120, 150, 180
+ """
try:
- if not self.angle_dirty:
+ if angle in self.angles:
self.parrot.angle = angle
- self.angle_dirty = True
- self._read_sound_effect_angle()
- self.angle_dirty = False
+ return self.read_sound_effect_angle()
+ else:
+ data = {'error': "'"+str(angle)+"' is not an accepted angle"}
+ self.indicator.info(data)
+ return data
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def read_sound_effect_angle(self):
+ """
+ Return current sound angle.
+ """
+ try:
+ data = {'data': {'sound_effec_angle': self.parrot.angle}}
+ self.indicator.info(data)
+ return data
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def toggle_noise_control(self, noise_control):
+ """
+ Define noise cancelation mode. Must be one of this value:
+ 'NOISE_CONTROL_MAX': Noise reduction maximum
+ 'NOISE_CONTROL_ON': Noise reduction enable
+ 'NOISE_CONTROL_OFF': Noise reduction disable
+ 'STREET_MODE': Street mode
+ 'STREET_MODE_MAX': Street mode maximum
+ """
+ try:
+ for noise_control_type, noise_control_value in self.noise_control_types.items():
+ if noise_control == noise_control_type:
+ self.parrot.noise_control = noise_control_value
+ return self.read_noise_control()
+ except resource_manager.DeviceDisconnected:
+ self.deactivate()
+
+ def read_noise_control(self):
+ """
+ Return current noise cancelation mode.
+ """
+ try:
+ active_noise_control = self.parrot.noise_control
+ for noise_control_type, noise_control in self.noise_control_types.items():
+ if active_noise_control == noise_control:
+ data = {'data': {'noise_control': noise_control_type}}
+ self.indicator.info(data)
+ return data
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_cancelation, widget):
+ def toggle_head_detection(self, head_detection):
+ """
+ Enable or disable head detection. Must be 'true' or 'false'.
+ """
try:
- if not self.noise_cancelation_dirty:
- self.parrot.noise_control = noise_cancelation
- self.noise_cancelation_dirty = True
- self._read_noise_cancelation()
- self.noise_cancelation_dirty = False
+ self.parrot.head_detection = head_detection
+ return self.read_head_detection()
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)
-
- def toggle_head_detection(self, widget):
+ def read_head_detection(self):
+ """
+ Return head detector status.
+ """
try:
- self.parrot.head_detection = self.head_detection.get_active()
- self.head_detection.set_active(self.parrot.head_detection)
+ data = {'data': {'head_detection': self.parrot.head_detection}}
+ self.indicator.info(data)
+ return data
except resource_manager.DeviceDisconnected:
self.deactivate()
diff --git a/parrot_zik/model/version2.py b/parrot_zik/model/version2.py
index 0cbdc1a..bbdec6a 100644
--- a/parrot_zik/model/version2.py
+++ b/parrot_zik/model/version2.py
@@ -107,24 +107,25 @@ class NoiseControl(object):
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)
+ representation = {
+ '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',
- }
+ representation = [
+ 'concert',
+ 'jazz',
+ 'living',
+ 'silent',
+ ]
+
+class Angles:
+ representation = [30, 60, 90, 120, 150, 180]
class SoundSource:
LINE_IN = 'line-in'
diff --git a/parrot_zik/parrot_zik_tray.py b/parrot_zik/parrot_zik_tray.py
deleted file mode 100755
index b5fab68..0000000
--- a/parrot_zik/parrot_zik_tray.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from interface.version1 import ParrotZikVersion1Interface
-from interface.version2 import ParrotZikVersion2Interface
-import resource_manager
-import bluetooth_paired_devices
-from indicator import MenuItem
-from indicator import Menu
-from indicator import SysIndicator
-from 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
diff --git a/parrot_zik/utils.py b/parrot_zik/utils.py
deleted file mode 100644
index 86f52cd..0000000
--- a/parrot_zik/utils.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import functools
-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:
- @functools.wraps(self.f)
- 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()
-