diff --git a/README.rst b/README.rst index 351ef15..8b0f9d9 100644 --- a/README.rst +++ b/README.rst @@ -160,5 +160,9 @@ using one of the techniques is the Application Writer's guide. :width: 179 .. image:: res/LifeApp.png - :alt: Game of Life runnin in the wasp-os simulator + :alt: Game of Life running in the wasp-os simulator + :width: 179 + +.. image:: res/MusicPlayerApp.png + :alt: Music Player running in the wasp-os simulator :width: 179 diff --git a/res/MusicPlayerApp.png b/res/MusicPlayerApp.png new file mode 100644 index 0000000..9b6b7e3 Binary files /dev/null and b/res/MusicPlayerApp.png differ diff --git a/res/headset.png b/res/headset.png new file mode 100755 index 0000000..4cdc52b Binary files /dev/null and b/res/headset.png differ diff --git a/res/pause.png b/res/pause.png new file mode 100755 index 0000000..9ff29d9 Binary files /dev/null and b/res/pause.png differ diff --git a/res/play.png b/res/play.png new file mode 100755 index 0000000..03fcd4e Binary files /dev/null and b/res/play.png differ diff --git a/wasp/apps/musicplayer.py b/wasp/apps/musicplayer.py new file mode 100644 index 0000000..9b4d9e5 --- /dev/null +++ b/wasp/apps/musicplayer.py @@ -0,0 +1,190 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +# Copyright (C) 2020 Daniel Thompson +# Copyright (C) 2020 Carlos Gil + +"""Music Player for GadgetBridge +~~~~~~~~~~~~~ + +Music Player Controller: +- Touch: play/pause +- Swipe UPDOWN: Volume down/up +- Swipe LEFTRIGHT: next/previous +""" + +import wasp + +import icons +import time + + +class MusicPlayerApp(object): + """ Music Player Controller application. + + .. figure:: res/MusicPlayerApp.png + :width: 179 + + Screenshot of the Music Player application + """ + NAME = 'Music' + ICON = icons.headset + + def __init__(self): + + self._play_icon = icons.play + self._pause_icon = icons.pause + self._play_state = False + self._icon_state = self._play_icon + self._max_display = 240 + self._icon_size = 72 + self._center_at = int((self._max_display - self._icon_size)/2) + self._musicstate = 'pause' + self._artist = '' + self._track = '' + self._state_changed = True + self._track_changed = True + self._artist_changed = True + + def _send_cmd(self, cmd): + print('\r') + for i in range(1): + for i in range(0, len(cmd), 20): + print(cmd[i: i + 20], end='') + time.sleep(0.2) + print(' ') + print(' ') + + def _fill_space(self, key): + if key == 'top': + wasp.watch.drawable.fill( + x=0, y=0, w=self._max_display, h=self._center_at) + elif key == 'mid': + wasp.watch.drawable.fill(x=self._center_at, y=self._center_at, + w=self._icon_size, h=self._icon_size) + elif key == 'down': + wasp.watch.drawable.fill(x=0, y=self._center_at + self._icon_size, + w=self._max_display, + h=self._max_display - (self._center_at + self._icon_size)) + + def foreground(self): + """Activate the application.""" + state = wasp.system.musicstate.get('state') + artist = wasp.system.musicinfo.get('artist') + track = wasp.system.musicinfo.get('track') + if state: + self._musicstate = state + if self._musicstate == 'play': + self._play_state = True + self._icon_state = self._pause_icon + elif self._musicstate == 'pause': + self._play_state = False + self._icon_state = self._play_icon + if artist: + self._artist = artist + if track: + self._track = track + wasp.watch.drawable.fill() + self.draw() + wasp.system.request_tick(1000) + wasp.system.request_event(wasp.EventMask.SWIPE_UPDOWN | + wasp.EventMask.SWIPE_LEFTRIGHT | + wasp.EventMask.TOUCH) + + def background(self): + """De-activate the application (without losing state).""" + self._state_changed = True + self._track_changed = True + self._artist_changed = True + + def tick(self, ticks): + wasp.system.keep_awake() + music_state_now = wasp.system.musicstate.get('state') + music_artist_now = wasp.system.musicinfo.get('artist') + music_track_now = wasp.system.musicinfo.get('track') + if music_state_now: + if music_state_now != self._musicstate: + self._musicstate = music_state_now + self._state_changed = True + else: + self._state_changed = False + wasp.system.musicstate = {} + if music_track_now: + if music_track_now != self._track: + self._track = music_track_now + self._track_changed = True + else: + self._track_changed = False + if music_artist_now: + if music_artist_now != self._artist: + self._artist = music_artist_now + self._artist_changed = True + else: + self._artist_changed = False + wasp.system.musicinfo = {} + self._update() + + def swipe(self, event): + """ + Notify the application of a touchscreen swipe event. + """ + if event[0] == wasp.EventType.UP: + self._send_cmd('{"t":"music", "n":"volumeup"} ') + elif event[0] == wasp.EventType.DOWN: + self._send_cmd('{"t":"music", "n":"volumedown"} ') + elif event[0] == wasp.EventType.LEFT: + self._send_cmd('{"t":"music", "n":"next"} ') + elif event[0] == wasp.EventType.RIGHT: + self._send_cmd('{"t":"music", "n":"previous"} ') + + def touch(self, event): + self._play_state = not self._play_state + if self._play_state: + self._musicstate = 'play' + self._icon_state = self._pause_icon + self._draw_button() + self._send_cmd('{"t":"music", "n":"play"} ') + else: + self._musicstate = 'pause' + self._icon_state = self._play_icon + self._draw_button() + self._send_cmd('{"t":"music", "n":"pause"} ') + + def draw(self): + """Redraw the display from scratch.""" + self._draw() + + def _draw(self): + """Redraw the updated zones.""" + if self._state_changed: + self._draw_button() + if self._track_changed: + self._draw_label(self._track, 24 + 144) + if self._artist_changed: + self._draw_label(self._artist, 12) + + def _draw_button(self): + """Redraw player button""" + self._fill_space('mid') + wasp.watch.drawable.blit(self._icon_state, self._center_at, + self._center_at) + + def _draw_label(self, label, pos): + """Redraw label info""" + if label: + draw = wasp.watch.drawable + chunks = draw.wrap(label, 240) + self._fill_space(pos) + for i in range(len(chunks)-1): + sub = self._track[chunks[i]:chunks[i+1]].rstrip() + draw.string(sub, 0, pos + 24 * i, 240) + + def _update(self): + if self._musicstate == 'play': + self._play_state = True + self._icon_state = self._pause_icon + elif self._musicstate == 'pause': + self._play_state = False + self._icon_state = self._play_icon + self._draw() + + def update(self): + pass diff --git a/wasp/boards/manifest_240x240.py b/wasp/boards/manifest_240x240.py index 6bf88c8..c99fdb8 100644 --- a/wasp/boards/manifest_240x240.py +++ b/wasp/boards/manifest_240x240.py @@ -8,6 +8,7 @@ manifest = ( 'apps/gameoflife.py', 'apps/haiku.py', 'apps/heart.py', + 'apps/musicplayer.py', 'apps/launcher.py', 'apps/pager.py', 'apps/settings.py', diff --git a/wasp/gadgetbridge.py b/wasp/gadgetbridge.py index 4e1abc3..8401d0c 100644 --- a/wasp/gadgetbridge.py +++ b/wasp/gadgetbridge.py @@ -29,13 +29,15 @@ true = True false = False def _info(msg): - json.dump({'t':'info', 'msg':msg}, sys.stdout) + json.dump({'t': 'info', 'msg': msg}, sys.stdout) sys.stdout.write('\r\n') + def _error(msg): - json.dump({'t':'error', 'msg':msg}, sys.stdout) + json.dump({'t': 'error', 'msg': msg}, sys.stdout) sys.stdout.write('\r\n') + def GB(cmd): task = cmd['t'] del cmd['t'] @@ -49,6 +51,10 @@ def GB(cmd): wasp.system.notify(id, cmd) elif task == 'notify-': wasp.system.unnotify(cmd['id']) + elif task == 'musicstate': + wasp.system.toggle_music(cmd) + elif task == 'musicinfo': + wasp.system.set_music_info(cmd) else: pass #_info('Command "{}" is not implemented'.format(cmd)) @@ -57,5 +63,3 @@ def GB(cmd): sys.print_exception(e, msg) _error(msg.getvalue()) msg.close() - - diff --git a/wasp/icons.py b/wasp/icons.py index 6141b40..14465fb 100644 --- a/wasp/icons.py +++ b/wasp/icons.py @@ -176,3 +176,136 @@ blestatus = ( b'\x02\xc4\r\xc3\x01\xc4\x0e\xc7\x0f\xc6\x10\xc5\x11\xc4\x12\xc3' b'\x13\xc2\x14\xc1\x0e' ) + +# 2-bit RLE, generated from res/headset.png, 415 bytes +headset = ( + b'\x02' + b'HH' + b'?\xb6\xc1\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1\xc1\xc1\xc1\xc17' + b'\xc1\xc1\xc1\xcd\xc1\xc1\xc1\xc12\xc1\xc1\xd4\xc1\xc1.\xc1' + b"\xc1\xd8\xc1\xc1*\xc1\xc1\xdb\xc1\xc1\xc1'\xc1\xc1\xde\xc1" + b'\xc1%\xc1\xc1\xca\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1\xc1\xc1\xc1' + b'\xca\xc1\xc1"\xc1\xc1\xc9\xc1\xc1\xc1\x0c\xc1\xc1\xc1\xc8\xc1' + b'\xc1!\xc1\xc8\xc1\xc1\xc1\x10\xc1\xc1\xc1\xc8\xc1\x1f\xc1\xc7' + b'\xc1\xc1\xc1\x14\xc1\xc1\xc7\xc1\xc1\x1d\xc1\xc1\xc6\xc1\xc1\x18' + b'\xc1\xc1\xc6\xc1\xc1\x1b\xc1\xc1\xc6\xc1\xc1\x1a\xc1\xc1\xc6\xc1' + b'\xc1\x1a\xc1\xc6\xc1\xc1\x1c\xc1\xc1\xc6\xc1\x19\xc1\xc6\xc1\xc1' + b'\x1e\xc1\xc1\xc5\xc1\xc1\x17\xc1\xc1\xc5\xc1\xc1 \xc1\xc6\xc1' + b'\x17\xc1\xc6\xc1"\xc1\xc6\xc1\x16\xc1\xc5\xc1\xc1"\xc1\xc1' + b'\xc5\xc1\x15\xc1\xc6\xc1$\xc1\xc6\xc1\x14\xc1\xc5\xc1%\xc1' + b'\xc1\xc5\xc1\x14\xc1\xc5\xc1&\xc1\xc5\xc1\x13\xc1\xc6\xc1&' + b'\xc1\xc5\xc1\xc1\x12\xc1\xc5\xc1(\xc1\xc5\xc1\x12\xc1\xc5\xc1' + b'(\xc1\xc5\xc1\x12\xc1\xc5\xc1(\xc1\xc5\xc1\x12\xc1\xc5\xc1' + b'(\xc1\xc5\xc1\x12\xc1\xc5\xc1(\xc1\xc5\xc1\x12\xc6)\xc1' + b'\xc5\xc1\x12\xc6*\xc6\x12\xc6*\xc6\x12\xc6*\xc6\x12\xc6' + b'*\xc6\x12\xc6*\xc6\x12\xc6*\xc6\x12\xd2\x12\xd2\x12\xd2' + b'\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2' + b'\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2' + b'\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd2' + b'\x12\xd2\x12\xd2\x12\xd2\x12\xd2\x12\xd1\xc1\x12\xc1\xd1\x12\xd1' + b'\xc1\x12\xc1\xd1\x12\xd1\xc1\x12\xc1\xd1\x12\xd1\xc1\x12\xc1\xc1' + b'\xd0\x12\xd0\xc1\x14\xc1\xc1\xcf\x12\xcf\xc1\xc1\x15\xc1\xc1\xce' + b'\x12\xce\xc1\xc1\x17\xc1\xc1\xcd\x12\xcd\xc1\xc1\x19\xc1\xc1\xc1' + b'\xc1\xca\x12\xca\xc1\xc1\xc1?\xff\xff\xff2' +) + +# 2-bit RLE, generated from res/play.png, 712 bytes +play = ( + b'\x02' + b'HH' + b'?\xff\x8f\xc1\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1\xc1\xc1\xc1\xc1' + b'6\xc1\xc1\xc1\xc1\xce\xc1\xc1\xc11\xc1\xc1\xc1\xd4\xc1\xc1' + b'\xc1,\xc1\xc1\xc1\xd8\xc1\xc1\xc1(\xc1\xc1\xc1\xdc\xc1\xc1' + b'\xc1%\xc1\xc1\xe0\xc1\xc1#\xc1\xc1\xca\xc1\xc1\xc1\xc1\xc1' + b'\xc1\xc2\xc1\xc1\xc1\xc1\xc1\xcb\xc1\xc1 \xc1\xc1\xc9\xc1\xc1' + b'\xc1\xc1\x0c\xc1\xc1\xc1\xc1\xc9\xc1\x1e\xc1\xc1\xc8\xc1\xc1\xc1' + b'\x12\xc1\xc1\xc1\xc8\xc1\xc1\x1b\xc1\xc1\xc8\xc1\xc1\x16\xc1\xc1' + b'\xc8\xc1\x1b\xc1\xc7\xc1\xc1\x1a\xc1\xc1\xc7\xc1\x19\xc1\xc7\xc1' + b'\xc1\x1c\xc1\xc1\xc7\xc1\x17\xc1\xc1\xc6\xc1\xc1\x1e\xc1\xc1\xc6' + b'\xc1\xc1\x15\xc1\xc1\xc6\xc1!\xc1\xc1\xc6\xc1\xc1\x14\xc1\xc6' + b'\xc1\xc1"\xc1\xc1\xc6\xc1\x13\xc1\xc1\xc5\xc1\xc1$\xc1\xc1' + b'\xc5\xc1\xc1\x12\xc1\xc5\xc1\xc1\r\xc1\x18\xc1\xc6\xc1\x11\xc1' + b'\xc6\xc1\x0e\xc1\xc1\x18\xc1\xc5\xc1\xc1\x10\xc1\xc5\xc1\xc1\x0e' + b'\xc1\xc1\xc1\xc1\x16\xc1\xc1\xc5\xc1\x0f\xc1\xc1\xc5\xc1\x0f\xc3' + b'\xc1\xc1\x16\xc1\xc5\xc1\x0f\xc1\xc5\xc1\xc1\x0f\xc4\xc1\xc1\x15' + b'\xc1\xc1\xc5\xc1\x0e\xc1\xc5\xc1\x10\xc5\xc1\xc1\xc1\x14\xc1\xc5' + b'\xc1\r\xc1\xc1\xc5\xc1\x10\xc7\xc1\xc1\x13\xc1\xc5\xc1\r\xc1' + b'\xc5\xc1\xc1\x10\xc8\xc1\xc1\x12\xc1\xc6\xc1\x0c\xc1\xc5\xc1\x11' + b'\xc9\xc1\xc1\xc1\x11\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x11\xcb\xc1\xc1' + b'\x10\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x11\xcc\xc1\xc1\x0f\xc1\xc5\xc1' + b'\x0c\xc1\xc5\xc1\x11\xce\xc1\xc1\r\xc1\xc5\xc1\x0c\xc1\xc5\xc1' + b'\x11\xcf\xc1\xc1\x0c\xc1\xc5\xc1\x0c\xc6\x12\xd0\xc1\xc1\x0b\xc1' + b'\xc5\xc1\x0c\xc6\x12\xd0\xc1\xc1\x0b\xc1\xc5\xc1\x0c\xc1\xc5\xc1' + b'\x11\xcf\xc1\xc1\x0c\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x11\xce\xc1\xc1' + b'\r\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x11\xcc\xc1\xc1\x0f\xc1\xc5\xc1' + b'\x0c\xc1\xc5\xc1\x11\xcb\xc1\xc1\x10\xc1\xc5\xc1\x0c\xc1\xc5\xc1' + b'\x11\xca\xc1\xc1\x11\xc1\xc5\xc1\x0c\xc1\xc5\xc1\xc1\x10\xc8\xc1' + b'\xc1\x12\xc1\xc1\xc5\xc1\x0c\xc1\xc1\xc5\xc1\x10\xc7\xc1\xc1\x13' + b'\xc1\xc5\xc1\x0e\xc1\xc5\xc1\x10\xc6\xc1\xc1\x14\xc1\xc5\xc1\x0e' + b'\xc1\xc5\xc1\xc1\x0f\xc4\xc1\xc1\x15\xc1\xc1\xc5\xc1\x0e\xc1\xc6' + b'\xc1\x0f\xc3\xc1\xc1\x16\xc1\xc5\xc1\xc1\x0f\xc1\xc5\xc1\xc1\x0e' + b'\xc2\xc1\xc1\x16\xc1\xc1\xc5\xc1\x10\xc1\xc6\xc1\x0e\xc1\xc1\x18' + b'\xc1\xc5\xc1\xc1\x11\xc1\xc5\xc1\xc1\r\xc1\x18\xc1\xc6\xc1\x12' + b'\xc1\xc6\xc1\xc1$\xc1\xc1\xc5\xc1\xc1\x13\xc1\xc6\xc1\xc1"' + b'\xc1\xc1\xc6\xc1\x14\xc1\xc1\xc6\xc1"\xc1\xc6\xc1\xc1\x15\xc1' + b'\xc7\xc1\xc1\x1e\xc1\xc1\xc6\xc1\xc1\x17\xc1\xc7\xc1\xc1\x1c\xc1' + b'\xc1\xc7\xc1\x18\xc1\xc1\xc7\xc1\xc1\x1a\xc1\xc1\xc7\xc1\x1a\xc1' + b'\xc1\xc7\xc1\xc1\xc1\x16\xc1\xc1\xc1\xc7\xc1\xc1\x1b\xc1\xc1\xc8' + b'\xc1\xc1\xc1\x12\xc1\xc1\xc1\xc8\xc1\xc1\x1d\xc1\xc1\xc9\xc1\xc1' + b'\xc1\xc1\x0c\xc1\xc1\xc1\xc1\xc9\xc1\xc1\x1f\xc1\xc1\xcb\xc1\xc1' + b'\xc1\xc1\xc1\xc1\x02\xc1\xc1\xc1\xc1\xc1\xc1\xca\xc1\xc1#\xc1' + b'\xc1\xe0\xc1\xc1%\xc1\xc1\xdd\xc1\xc1\xc1(\xc1\xc1\xda\xc1' + b'\xc1,\xc1\xc1\xd5\xc1\xc1\xc10\xc1\xc1\xc1\xc1\xce\xc1\xc1' + b'\xc1\xc15\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1\xc1\xc1\xc1' + b'\xc1\xc1?\xff\x8e' +) + +# 2-bit RLE, generated from res/pause.png, 699 bytes +pause = ( + b'\x02' + b'HH' + b'?\xff\x8f\xc1\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1\xc1\xc1\xc1\xc1' + b'6\xc1\xc1\xc1\xc1\xce\xc1\xc1\xc11\xc1\xc1\xc1\xd4\xc1\xc1' + b'\xc1,\xc1\xc1\xc1\xd8\xc1\xc1\xc1(\xc1\xc1\xc1\xdc\xc1\xc1' + b'\xc1%\xc1\xc1\xe0\xc1\xc1#\xc1\xc1\xca\xc1\xc1\xc1\xc1\xc1' + b'\xc1\xc2\xc1\xc1\xc1\xc1\xc1\xcb\xc1\xc1 \xc1\xc1\xc9\xc1\xc1' + b'\xc1\xc1\x0c\xc1\xc1\xc1\xc1\xc9\xc1\x1e\xc1\xc1\xc8\xc1\xc1\xc1' + b'\x12\xc1\xc1\xc1\xc8\xc1\xc1\x1b\xc1\xc1\xc8\xc1\xc1\x16\xc1\xc1' + b'\xc8\xc1\x1b\xc1\xc7\xc1\xc1\x1a\xc1\xc1\xc7\xc1\x19\xc1\xc7\xc1' + b'\xc1\x1c\xc1\xc1\xc7\xc1\x17\xc1\xc1\xc6\xc1\xc1\x1e\xc1\xc1\xc6' + b'\xc1\xc1\x15\xc1\xc1\xc6\xc1!\xc1\xc1\xc6\xc1\xc1\x14\xc1\xc6' + b'\xc1\xc1"\xc1\xc1\xc6\xc1\x13\xc1\xc1\xc5\xc1\xc1$\xc1\xc1' + b'\xc5\xc1\xc1\x12\xc1\xc5\xc1\xc1&\xc1\xc6\xc1\x11\xc1\xc6\xc1' + b'(\xc1\xc5\xc1\xc1\x10\xc1\xc5\xc1\xc1\x0b\xc6\x06\xc6\x0b\xc1' + b'\xc1\xc5\xc1\x0f\xc1\xc1\xc5\xc1\x0c\xc6\x06\xc6\x0c\xc1\xc5\xc1' + b'\x0f\xc1\xc5\xc1\xc1\x0c\xc6\x06\xc6\x0c\xc1\xc1\xc5\xc1\x0e\xc1' + b'\xc5\xc1\r\xc6\x06\xc6\r\xc1\xc5\xc1\r\xc1\xc1\xc5\xc1\r' + b'\xc6\x06\xc6\r\xc1\xc5\xc1\r\xc1\xc5\xc1\xc1\r\xc6\x06\xc6' + b'\r\xc1\xc6\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1' + b'\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1' + b'\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6' + b'\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1' + b'\x0c\xc6\x0f\xc6\x06\xc6\x0e\xc1\xc5\xc1\x0c\xc6\x0f\xc6\x06\xc6' + b'\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1' + b'\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1' + b'\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6' + b'\x0e\xc1\xc5\xc1\x0c\xc1\xc5\xc1\x0e\xc6\x06\xc6\x0e\xc1\xc5\xc1' + b'\x0c\xc1\xc5\xc1\xc1\r\xc6\x06\xc6\r\xc1\xc1\xc5\xc1\x0c\xc1' + b'\xc1\xc5\xc1\r\xc6\x06\xc6\r\xc1\xc5\xc1\x0e\xc1\xc5\xc1\r' + b'\xc6\x06\xc6\r\xc1\xc5\xc1\x0e\xc1\xc5\xc1\xc1\x0c\xc6\x06\xc6' + b'\x0c\xc1\xc1\xc5\xc1\x0e\xc1\xc6\xc1\x0c\xc6\x06\xc6\x0c\xc1\xc5' + b'\xc1\xc1\x0f\xc1\xc5\xc1\xc1\x0b\xc6\x06\xc6\x0b\xc1\xc1\xc5\xc1' + b'\x10\xc1\xc6\xc1(\xc1\xc5\xc1\xc1\x11\xc1\xc5\xc1\xc1&\xc1' + b'\xc6\xc1\x12\xc1\xc6\xc1\xc1$\xc1\xc1\xc5\xc1\xc1\x13\xc1\xc6' + b'\xc1\xc1"\xc1\xc1\xc6\xc1\x14\xc1\xc1\xc6\xc1"\xc1\xc6\xc1' + b'\xc1\x15\xc1\xc7\xc1\xc1\x1e\xc1\xc1\xc6\xc1\xc1\x17\xc1\xc7\xc1' + b'\xc1\x1c\xc1\xc1\xc7\xc1\x18\xc1\xc1\xc7\xc1\xc1\x1a\xc1\xc1\xc7' + b'\xc1\x1a\xc1\xc1\xc7\xc1\xc1\xc1\x16\xc1\xc1\xc1\xc7\xc1\xc1\x1b' + b'\xc1\xc1\xc8\xc1\xc1\xc1\x12\xc1\xc1\xc1\xc8\xc1\xc1\x1d\xc1\xc1' + b'\xc9\xc1\xc1\xc1\xc1\x0c\xc1\xc1\xc1\xc1\xc9\xc1\xc1\x1f\xc1\xc1' + b'\xcb\xc1\xc1\xc1\xc1\xc1\xc1\x02\xc1\xc1\xc1\xc1\xc1\xc1\xca\xc1' + b'\xc1#\xc1\xc1\xe0\xc1\xc1%\xc1\xc1\xdd\xc1\xc1\xc1(\xc1' + b'\xc1\xda\xc1\xc1,\xc1\xc1\xd5\xc1\xc1\xc10\xc1\xc1\xc1\xc1' + b'\xce\xc1\xc1\xc1\xc15\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc2\xc1\xc1' + b'\xc1\xc1\xc1\xc1\xc1?\xff\x8e' +) diff --git a/wasp/wasp.py b/wasp/wasp.py index e2e728a..0b99c0d 100644 --- a/wasp/wasp.py +++ b/wasp/wasp.py @@ -107,6 +107,8 @@ class Manager(): self.launcher_ring = [] self.notifier = NotificationApp() self.notifications = {} + self.musicstate = {} + self.musicinfo = {} self.blank_after = 15 @@ -234,6 +236,12 @@ class Manager(): if id in self.notifications: del self.notifications[id] + def toggle_music(self, state): + self.musicstate = state + + def set_music_info(self, info): + self.musicinfo = info + def request_event(self, event_mask): """Subscribe to events.