diff --git a/app/__init__.py b/app/__init__.py
index 093969d6..d9b677d9 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -29,15 +29,15 @@ def _status_updated(watcher, icon, window):
# pass
-def run():
+def run(config):
GObject.threads_init()
- ui.notify.start(APP_TITLE)
+ ui.notify.init(APP_TITLE, config.notifications)
watcher = WatcherThread(ui.notify.show)
watcher.start()
- window = ui.window.create(APP_TITLE, watcher.devices[0])
+ window = ui.window.create(APP_TITLE, watcher.devices[0], not config.start_hidden, config.close_to_tray)
menu_actions = [('Scan all devices', watcher.full_scan),
# ('Pair new device', _pair_new_device, watcher),
@@ -53,4 +53,4 @@ def run():
Gtk.main()
watcher.stop()
- ui.notify.stop()
+ ui.notify.set_active(False)
diff --git a/app/ui/notify.py b/app/ui/notify.py
index 8fa43fd2..46759394 100644
--- a/app/ui/notify.py
+++ b/app/ui/notify.py
@@ -2,35 +2,62 @@
# Optional desktop notifications.
#
+import logging
+
+
try:
import notify2 as _notify
-
- available = True
+ available = True # assumed to be working since the import succeeded
+ _active = False # not yet active
+ _app_title = None
_notifications = {}
- def start(app_title):
+ def init(app_title, active=True):
"""Init the notifications system."""
- _notify.init(app_title)
- return True
+ global _app_title, _active
+ _app_title = app_title
+ return set_active(active)
- def stop():
- """Stop the notifications system."""
- for n in list(_notifications.values()):
- try:
- n.close()
- except Exception:
- # DBUS
- pass
- _notifications.clear()
- _notify.uninit()
+ def set_active(active=True):
+ global available, _active
+ if available:
+ if active:
+ if not _active:
+ try:
+ _notify.init(_app_title)
+ _active = True
+ except:
+ logging.exception("initializing desktop notifications")
+ available = False
+ else:
+ if _active:
+ for n in list(_notifications.values()):
+ try:
+ n.close()
+ except Exception:
+ logging.exception("closing open notification %s", n)
+ # DBUS
+ pass
+ _notifications.clear()
+ try:
+ _notify.uninit()
+ except:
+ logging.exception("stopping desktop notifications")
+ available = False
+ _active = False
+ return _active
- def show(status_code, title, text, icon=None):
+ def active():
+ return _active
+
+
+ def show(status_code, title, text='', icon=None):
"""Show a notification with title and text."""
- if not available:
+ if not available or not _active:
return
if title in _notifications:
@@ -45,17 +72,20 @@ try:
icon = icon or title
notification.update(title, text, title)
try:
- notification.show()
+ if text:
+ notification.show()
+ else:
+ notification.close()
except Exception:
- # DBUS
- pass
+ logging.exception("showing notification %s", notification)
except ImportError:
- import logging
logging.exception("ouch")
logging.warn("python-notify2 not found, desktop notifications are disabled")
available = False
- def start(app_title): pass
- def stop(): pass
+ active = False
+ def init(app_title, active=True): return False
+ def active(): return False
+ def set_active(active=True): return False
def show(status_code, title, text, icon=None): pass
diff --git a/app/ui/window.py b/app/ui/window.py
index ac18f334..57b50a7c 100644
--- a/app/ui/window.py
+++ b/app/ui/window.py
@@ -21,7 +21,10 @@ def update(window, devices):
first = controls[0].get_child()
icon, label = first.get_children()
rstatus = devices[0]
- label.set_markup('%s\n%s' % (rstatus.name, rstatus.text))
+ if rstatus.text:
+ label.set_markup('%s\n%s' % (rstatus.name, rstatus.text))
+ else:
+ label.set_markup('%s' % rstatus.name)
for index in range(1, 1 + _MAX_DEVICES):
devstatus = devices.get(index)
@@ -120,7 +123,7 @@ def _device_box(title):
return frame
-def create(title, rstatus):
+def create(title, rstatus, show=True, close_to_tray=False):
vbox = Gtk.VBox(homogeneous=False, spacing=4)
vbox.set_border_width(4)
@@ -130,6 +133,8 @@ def create(title, rstatus):
vbox.set_visible(True)
window = Gtk.Window()
+ window.add(vbox)
+
window.set_title(title)
window.set_icon_name(title)
window.set_keep_above(True)
@@ -137,16 +142,21 @@ def create(title, rstatus):
# window.set_skip_pager_hint(True)
window.set_deletable(False)
window.set_resizable(False)
+
window.set_position(Gtk.WindowPosition.MOUSE)
window.set_type_hint(Gdk.WindowTypeHint.UTILITY)
+
window.set_wmclass(title, 'status-window')
window.set_role('status-window')
- window.connect('window-state-event', _state_event)
- window.connect('delete-event', lambda w, e: toggle(None, window) or True)
+ if close_to_tray:
+ window.connect('window-state-event', _state_event)
+ window.connect('delete-event', lambda w, e: toggle(None, window) or True)
+ else:
+ window.connect('delete-event', Gtk.main_quit)
- window.add(vbox)
- window.present()
+ if show:
+ window.present()
return window
diff --git a/app/watcher.py b/app/watcher.py
index 1d78c162..beb3290a 100644
--- a/app/watcher.py
+++ b/app/watcher.py
@@ -17,15 +17,15 @@ _THREAD_SLEEP = 5 # seconds
_UNIFYING_RECEIVER = 'Unifying Receiver'
_NO_DEVICES = 'No devices attached.'
-_SCANNING = 'Initializing...'
+_INITIALIZING = 'Initializing...'
+_SCANNING = 'Scanning...'
_NO_RECEIVER = 'not found'
-_FOUND_RECEIVER = 'found'
class _DevStatus(api.AttachedDeviceInfo):
timestamp = time.time()
code = devices.STATUS.UNKNOWN
- text = ''
+ text = _INITIALIZING
refresh = None
@@ -48,20 +48,23 @@ class WatcherThread(threading.Thread):
def run(self):
self.active = True
- self._notify(0, _UNIFYING_RECEIVER, _SCANNING)
while self.active:
if self.listener is None:
+ self._device_status_changed(self.rstatus, (devices.STATUS.UNKNOWN, _INITIALIZING))
+ self._update_status_text()
+
receiver = api.open()
if receiver:
- self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, _FOUND_RECEIVER))
+ self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, _SCANNING))
+ self._update_status_text()
for devinfo in api.list_devices(receiver):
self._new_device(devinfo)
-
- if len(self.devices) == 1:
+ if len(self.devices) > 1:
+ self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, ''))
+ else:
self._device_status_changed(self.rstatus, (devices.STATUS.CONNECTED, _NO_DEVICES))
-
self._update_status_text()
self.listener = EventsListener(receiver, self._events_callback)
@@ -163,20 +166,30 @@ class WatcherThread(threading.Thread):
devstatus.timestamp = time.time()
if type(status) == int:
- devstatus.code = status
- if devstatus.code in devices.STATUS_NAME:
- devstatus.text = devices.STATUS_NAME[devstatus.code]
+ status_code = status
+ if status_code in devices.STATUS_NAME:
+ status_text = devices.STATUS_NAME[status_code]
else:
- devstatus.code = status[0]
+ status_code = status[0]
if isinstance(status[1], str):
- devstatus.text = status[1]
+ status_text = status[1]
elif isinstance(status[1], dict):
+ status_text = ''
for key, value in status[1].items():
- setattr(devstatus, key, value)
+ if key == 'text':
+ status_text = value
+ else:
+ setattr(devstatus, key, value)
+ else:
+ status_code = devices.STATUS.UNKNOWN
+ status_text = ''
- if old_status_code != devstatus.code:
- logging.debug("%s: device '%s' status changed %s => %s: %s", time.asctime(), devstatus.name, old_status_code, devstatus.code, devstatus.text)
- if devstatus.code // 256 != old_status_code // 256:
+ if not (status_code == 0 and old_status_code > 0):
+ devstatus.code = status_code
+ devstatus.text = status_text
+ logging.debug("%s: device '%s' status update %s => %s: %s", time.asctime(), devstatus.name, old_status_code, status_code, status_text)
+
+ if status_code == 0 or old_status_code != status_code:
self._notify(devstatus.code, devstatus.name, devstatus.text)
return True
diff --git a/lib/hidapi/__init__.py b/lib/hidapi/__init__.py
index 4e5973ec..e0a2b217 100644
--- a/lib/hidapi/__init__.py
+++ b/lib/hidapi/__init__.py
@@ -1,5 +1,8 @@
-"""Generic Human Interface Device API.
-"""
+"""Generic Human Interface Device API."""
+
+__author__ = "Daniel Pavel"
+__license__ = "GPL"
+__version__ = "0.3"
#
# In case a future pure-Python implementation is feasible.
diff --git a/lib/logitech/__init__.py b/lib/logitech/__init__.py
index cfe18a79..e5a3437e 100644
--- a/lib/logitech/__init__.py
+++ b/lib/logitech/__init__.py
@@ -1 +1,5 @@
-# pass
+#
+
+__author__ = "Daniel Pavel"
+__license__ = "GPL"
+__version__ = "0.4"
diff --git a/solaar.py b/solaar.py
index 2ed7aeab..566c7a8a 100644
--- a/solaar.py
+++ b/solaar.py
@@ -6,18 +6,23 @@ __version__ = '0.4'
#
#
-import logging
-
-
if __name__ == '__main__':
import argparse
- arg_parser = argparse.ArgumentParser()
+ arg_parser = argparse.ArgumentParser(prog='Solaar')
arg_parser.add_argument('-v', '--verbose', action='count', default=0,
help='increase the logger verbosity')
+ arg_parser.add_argument('-N', '--disable-notifications', action='store_false', dest='notifications',
+ help='disable desktop notifications')
+ arg_parser.add_argument('-H', '--start-hidden', action='store_true', dest='start_hidden',
+ help='hide the application window on start')
+ arg_parser.add_argument('-t', '--close-to-tray', action='store_true',
+ help='closing the application window hides it')
+ arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
args = arg_parser.parse_args()
+ import logging
log_level = logging.root.level - 10 * args.verbose
logging.basicConfig(level=log_level if log_level > 0 else 1)
import app
- app.run()
+ app.run(args)