|
| 1 | +# TODO |
| 2 | +# mediakey-remote.py |
| 3 | +# |
| 4 | +# service install scripts |
| 5 | +# - linux |
| 6 | +# - windows |
| 7 | +# - mac |
| 8 | +# |
| 9 | +# externalize config |
| 10 | +# - controller: |
| 11 | +# |
| 12 | +# - global |
| 13 | +# - volume step (default: 1) |
| 14 | +# - refresh |
| 15 | +# |
| 16 | +# - media keys |
| 17 | +# - lower volume key (default: 114) |
| 18 | +# - raise volume key (default: 115) |
| 19 | +# |
| 20 | +# - sonos |
| 21 | +# - scan for controller |
| 22 | +# |
| 23 | +# - spotify |
| 24 | +# - ... |
| 25 | + |
| 26 | + |
| 27 | +import time |
| 28 | +from threading import Thread |
| 29 | +import keyboard |
| 30 | +import soco |
| 31 | +import toml |
| 32 | + |
| 33 | + |
| 34 | +# load config |
| 35 | +config_path="/home/kbouck/dev/mediakey-remote/mediakey-remote-config.toml" |
| 36 | +config = {} |
| 37 | +with open(config_path, 'r') as f: |
| 38 | + config = toml.load(f) |
| 39 | +print("Loaded config from " + config_path) |
| 40 | + |
| 41 | + |
| 42 | +# discover sonos devices on network |
| 43 | +# - todo: error handling |
| 44 | +# - todo: make reconnection loop |
| 45 | + |
| 46 | +#sonos_speakers = soco.discover() |
| 47 | +#if (len(sonos_speakers) > 0): |
| 48 | +# print("Discovered sonos speakers:") |
| 49 | +# for speaker in sonos_speakers: |
| 50 | +# print(speaker.name) |
| 51 | +#else: |
| 52 | +# # todo - need reconnection loop |
| 53 | +# system.exit("No sonos speakers discovered") |
| 54 | +#sonos = sonos_speakers.pop() |
| 55 | + |
| 56 | + |
| 57 | +sonos = soco.discovery.any_soco() |
| 58 | +print("Connected to '" + str(sonos.player_name) + "'") |
| 59 | + |
| 60 | +state = "" |
| 61 | +volume = 0 |
| 62 | +volume_step = config['sonos']['vol_step'] |
| 63 | +vol_init_max = config['sonos']['vol_init_max'] |
| 64 | + |
| 65 | +def play_pause(): |
| 66 | + global state |
| 67 | + sonos.pause() if (state == "PLAYING") else sonos.play() |
| 68 | + transport_info = sonos.get_current_transport_info() |
| 69 | + state = transport_info['current_transport_state'] |
| 70 | + |
| 71 | +def poll_state(): |
| 72 | + global state |
| 73 | + while True: |
| 74 | + volume = sonos.volume |
| 75 | + transport_info = sonos.get_current_transport_info() |
| 76 | + state = transport_info['current_transport_state'] |
| 77 | + time.sleep(10) |
| 78 | + |
| 79 | + |
| 80 | +# map keys to api calls |
| 81 | +keyboard.add_hotkey(config['keys']['volume_down'], lambda: sonos.set_relative_volume(volume_step*-1), trigger_on_release=False) |
| 82 | +keyboard.add_hotkey(config['keys']['volume_up'], lambda: sonos.set_relative_volume(volume_step), trigger_on_release=False) |
| 83 | +keyboard.add_hotkey(config['keys']['next'], lambda: sonos.next(), trigger_on_release=False) |
| 84 | +keyboard.add_hotkey(config['keys']['previous'], lambda: sonos.previous(), trigger_on_release=False) |
| 85 | +keyboard.add_hotkey(config['keys']['play_pause'], lambda: play_pause(), trigger_on_release=False) |
| 86 | +# todo: mute/seek? |
| 87 | + |
| 88 | +# start state polling thread |
| 89 | +poller = Thread(target=poll_state) |
| 90 | +poller.start() |
| 91 | + |
| 92 | +# block app to wait for keyboard events |
| 93 | +keyboard.wait() |
| 94 | + |
| 95 | + |
0 commit comments