-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
189 lines (154 loc) · 5.21 KB
/
Copy pathmain.py
File metadata and controls
189 lines (154 loc) · 5.21 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#! /usr/bin/env python3
#
# Control program for Recording from an attached USB interface
# This is intended to be used with, for example, a Behringer XR18 mixer to
# record (some subset of) the input channels.
# The number of input channels can be set to less than the maximum on the device
# but it is up to the operator to make sure that the USB interface is configured to
# map the required inputs to the channels on the USB interface
#
# Loop:
# - run a separate thread for OSC commands
# - on command, start up a 'rec' subprocess to record audio data
# - terminate 'rec' on command
#
# TODO - add an audio player
#import io
#import os
import time
import re
import threading
import subprocess
import data_files
import osc
Debug = False
#
usbrecord_terminate_process = False
usbrecord_active = False
usb_channels = 4
probe_device = False
record_device = "Unknown"
# timer_thread - periodic timer
#
def timer_thread():
global probe_device
time.sleep(30) # Give Companion time to start up
while True:
probe_device = True
time.sleep(300)
# find_device - run periodically to discover the connected
# recording device
def find_device():
global record_device
output = subprocess.run([ data_files.probedevice ],
capture_output=True, text=True).stdout
match = re.match("hw:([A-Za-z0-9]+)", output)
if match:
record_device = output.strip("\n")
osc_task.set_custom("record_device", match.group(1))
# rec_parse - parse the output of 'rec'
#
rec_parse_prog = None
def rec_parse(line):
global rec_parse_prog
if rec_parse_prog is None:
rec_parse_prog = re.compile("In:.+ Out:([0-9.]+[kMG]) .+")
match = rec_parse_prog.match(line)
if match:
osc_task.set_custom("record_bytes", match.group(1))
return match
def record_status(onoff):
""" Change in recording status. """
global usbrecord_active
onoff = bool(onoff) # Make sure value is a boolean
usbrecord_active = onoff
osc_task.set_custom("record_status", onoff)
def setchannels(num):
global usb_channels, probe_device
""""Set the number of channels to record"""
usb_channels = num
probe_device = True # force a device probe
def run_usbrecord():
"""Start the usb_record script to run 'rec'"""
global usb_channels
if Debug:
print(f"runrecord: {data_files.runrecord}")
args = [
data_files.runrecord,
"--channels",
str(usb_channels),
"--device",
record_device
]
try:
popen = subprocess.Popen(args,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
text=True)
except (PermissionError, FileNotFoundError):
popen = None
return popen
def kill_usbrecord():
"""Kill the running 'rec' process with a SIGINT"""
args = [
data_files.killrecord
]
subprocess.run(args)
def usbrecord_thread():
""" Thread to run/monitor the 'rec' subprocess"""
global usbrecord_terminate_process, usbrecord_active, probe_device
popen = None
while True:
if popen is None:
if not usbrecord_active:
# No active 'rec' process: perodic check for a change in recording device
#
if probe_device:
find_device()
probe_device = False
time.sleep(2)
continue
else: # usb_acive true, try to run record
popen = run_usbrecord()
if popen is None:
time.sleep(10)
record_status(False)
else: # popen not None, subprocess is active
popen.poll()
if popen.returncode is not None:
popen = None
record_status(False)
else:
if not usbrecord_active or usbrecord_terminate_process:
# try to shut it down
kill_usbrecord()
if usbrecord_terminate_process:
try:
popen.wait(2)
except subprocess.TimeoutExpired:
pass
popen.terminate()
return
# Otherwise try to read a line of output
line = popen.stdout.readline()
if line:
line = line.strip("\n")
if not rec_parse(line):
# if it's not a line we recognize, then output for
# debug
osc_task.set_custom("record_log",
line)
print(f'usbrecord: {line}')
def do_record(onoff):
""""Start/Stop recording"""
record_status(bool(onoff))
if __name__ == '__main__' :
threading.Thread(target=usbrecord_thread, daemon=True).start()
threading.Thread(target=timer_thread, daemon=True).start()
osc_task = osc.OSCTask(do_record=do_record, setchannels=setchannels)
osc_task.set_custom("recorder_reset", str(int(time.time())))
try:
while True:
time.sleep(10)
except KeyboardInterrupt:
usbrecord_terminate_process = True
do_record(0)