6 from django.core.management.base import BaseCommand, CommandError
8 from nonstop.app_settings import app_settings
15 logger = logging.getLogger('switch-jack')
18 class Command(BaseCommand):
19 help = 'jack source switch'
21 def handle(self, verbosity, **options):
23 raise CommandError('missing jack module (install python3-jack-client?)')
24 self.verbosity = verbosity
25 asyncio.run(self.main())
28 if not app_settings.SWITCH_WS_URL:
29 raise CommandError('missing switch_ws_url')
30 currently_active = None
34 async with aiohttp.ClientSession() as session:
35 async with session.ws_connect(app_settings.SWITCH_WS_URL) as ws:
36 logger.info('waiting for messages')
37 sleep_duration = 0.2 # reset sleep duration to baseline
39 if msg.type == aiohttp.WSMsgType.TEXT:
41 msg = json.loads(msg.data)
44 if msg.get('active') != currently_active:
45 currently_active = msg.get('active')
46 self.update_jack_connections(currently_active)
47 elif msg.type == aiohttp.WSMsgType.ERROR:
49 logger.debug('lost websocket connection')
50 except aiohttp.ClientError as e:
51 logger.warning('websocket error (%s)' % e)
53 await asyncio.sleep(min(sleep_duration, 5))
54 except asyncio.CancelledError:
55 # most probably because of a keyboard interrupt, quit silently
58 def update_jack_connections(self, active):
59 if active not in app_settings.SWITCH_IN_PORTS:
60 logger.info('unsupported source: %s', active)
62 logger.info('setting source: %s', active)
63 out_ports = app_settings.SWITCH_OUT_PORTS
64 with jack.Client('switch-jack') as client:
65 known_ports = {x.name for x in client.get_ports(is_audio=True)}
66 for dports in out_ports.values():
67 if any(x not in known_ports for x in dports):
68 logger.error('unavailable destination ports %r', dports)
70 for port_id, port_names in app_settings.SWITCH_IN_PORTS.items():
71 if any(x not in known_ports for x in port_names):
72 logger.error('unavailable source ports %r', port_names)
76 self.jack_connect(client, port_names[0], dports[0])
77 self.jack_connect(client, port_names[1], dports[1])
79 self.jack_disconnect(client, port_names[0], dports[0])
80 self.jack_disconnect(client, port_names[1], dports[1])
81 except jack.JackError as e:
82 logger.error('jack error: %s' % e)
84 def jack_connect(self, client, in_port, out_port):
85 connections = [x.name for x in client.get_all_connections(in_port)]
86 if out_port not in connections:
88 logger.info('connecting %s and %s', in_port, out_port)
89 client.connect(in_port, out_port)
91 def jack_disconnect(self, client, in_port, out_port):
92 connections = [x.name for x in client.get_all_connections(in_port)]
93 if out_port in connections:
95 logger.info('disconnecting %s and %s', in_port, out_port)
96 client.disconnect(in_port, out_port)