-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroon_remote.py
138 lines (111 loc) · 4.58 KB
/
roon_remote.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
Implement a Roon Remote extension that reads keybaord events
from a FLIRC device and converts those events into transport
commands towards a certain _Zone_ in Roon.
"""
# !/usr/bin/python
import logging
import signal
import sys
from pathlib import Path
import evdev
from evdev import InputDevice
from app import RoonController, RoonOutput, RemoteConfig, RemoteConfigE, RemoteKeycodeMapping, RoonControllerE
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(module)s: %(message)s')
logger = logging.getLogger('roon_remote')
def exit_handler(_received_signal, _frame):
"""Handle SIGINT and SIGTERM signals"""
logger.info("Signaling internal jobs to stop...")
sys.exit(0)
def get_event_device_for_string(dev_name: str):
"""Scan the Input Device tree for Flirc unit and return the device"""
dev = None
logger.debug('looking for input device "%s"', dev_name)
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
if not devices:
logger.error('no device found, invalid permissions?')
return None
for device in devices:
logger.debug("name: %s" % device.name)
if dev_name in device.name:
dev = device
logger.debug('found device with name: "%s" on path: %s', device.name, device.path)
break
return dev
def monitor_remote(zone: RoonOutput, dev: InputDevice, mapping: RemoteKeycodeMapping):
"""start an event loop on InputDevice"""
logger.info("Job monitorRemote started")
if not dev:
raise BaseException('could not open DEV')
logger.debug('opening exclusively InputDevice: %s', dev.path)
for event in dev.read_loop():
if event.value != 1:
# ignore everything that is not KEY_DOWN
continue
# logging.debug(str(categorize(event)))
try:
# logging.debug("Status: {}".format('uninitialized'))
# logging.debug("KeyCode: {}".format(event.code))
if event.code in mapping.to_key_code('prev'):
zone.previous()
elif event.code in mapping.to_key_code('skip'):
zone.skip()
elif event.code in mapping.to_key_code('stop'):
zone.stop()
elif event.code in mapping.to_key_code('play_pause'):
if zone.state == "playing":
zone.pause()
else:
zone.repeat(False)
zone.play()
elif event.code in mapping.to_key_code('vol_up'):
zone.volume_up(2)
elif event.code in mapping.to_key_code('vol_down'):
zone.volume_down(2)
elif event.code in mapping.to_key_code('mute'):
zone.mute(not zone.is_muted())
elif event.code in mapping.to_key_code('fall_asleep'):
zone.play_playlist('wellenrauschen')
elif event.code in mapping.to_key_code('play_radio'):
zone.play_radio_station(station_name="Radio Paradise (320k aac)")
logger.debug("Received Code: %s", repr(event.code))
except Exception as exception:
logging.error("Caught exception: %s (%s)", exception, type(exception))
logger.info("Job monitorRemote stopped")
def main():
"""main function, initiate InputDevice and runs the forever loop"""
logger.info("starting %s", __file__)
signal.signal(signal.SIGINT, exit_handler)
signal.signal(signal.SIGTERM, exit_handler)
controller = None
try:
config = RemoteConfig(Path('app_info.json'))
except RemoteConfigE as ex:
logging.error(ex.msg)
sys.exit(1)
mapping = config.key_mapping
logging.info(mapping.edge)
input_dev_name = "flirc Keyboard"
event_dev = get_event_device_for_string(input_dev_name)
if not event_dev:
logging.error('Could not find any InputDevice with name: "%s"', input_dev_name)
sys.exit(1)
logging.debug('found input device: %s', event_dev)
try:
controller = RoonController(config.app_info, Path('.roon-token'))
except RoonControllerE as ex:
logging.error("Failed to initiate the controller: %s" % ex.msg)
output = controller.get_output(config.zone)
if not output:
logging.error('failed to find zone "{}"'.format(config.zone))
sys.exit(1)
try:
monitor_remote(output, event_dev, config.key_mapping)
except Exception as exception:
logging.error("Critical exception: %s", exception)
controller.shutdown()
logging.info("terminated")
sys.exit(0)
if __name__ == '__main__':
main()