Skip to content

Commit 6a25e7f

Browse files
committed
cleanup and improve output
1 parent 5216c22 commit 6a25e7f

File tree

2 files changed

+93
-88
lines changed

2 files changed

+93
-88
lines changed

server.py

Lines changed: 92 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -960,46 +960,18 @@ def songs_preview():
960960

961961

962962
def signal_handler(signum, frame):
963-
print(f"Received signal {signum}, shutting down gracefully...")
963+
logger.info("Received signal %d, shutting down gracefully...", signum)
964964
WebRTCMicrophoneManager().stop()
965-
print("All microphones stopped. Exiting now.")
966-
# Cleanup iptables entries for port remapping if they were created
967-
if 'args' in globals() and getattr(args, 'remap_ssl_port', False):
968-
print("Cleaning up iptables port remapping rules...")
969-
try:
970-
ip_list = []
971-
for iface in socket.if_nameindex():
972-
name = iface[1]
973-
try:
974-
for fam, _, _, _, sockaddr in socket.getaddrinfo(name, None):
975-
if fam == socket.AF_INET:
976-
ip = sockaddr[0]
977-
if ip != "0.0.0.0" and ip != "127.0.0.1" and ip not in ip_list:
978-
ip_list.append(ip)
979-
except Exception:
980-
continue
981-
for ip in ip_list:
982-
del_cmd = [
983-
"sudo", "iptables", "-t", "nat", "-D", "PREROUTING",
984-
"-p", "tcp", "-d", ip, "--dport", "443",
985-
"-j", "REDIRECT", "--to-port", str(args.port)
986-
]
987-
print("Removing:", " ".join(del_cmd))
988-
result = subprocess.run(del_cmd, capture_output=True, text=True)
989-
if result.returncode == 0:
990-
print(f"Removed iptables rule for {ip}:443 -> {args.port}")
991-
else:
992-
print(f"Failed to remove rule for {ip}: {result.stderr}")
993-
except Exception as e:
994-
print("Error cleaning up iptables rules:", e)
995-
#time.sleep(0.1) # Give some time for cleanup
996-
raise RuntimeError("Server going down")
965+
print("Terminating server...")
966+
sys.exit(0)
997967

998968
def initialize_record_section():
969+
"""Initialize the [Record] section in config.ini for 6 virtual sinks."""
970+
print("Initializing [Record] section in config.ini for 6 virtual sinks...")
999971
base_dir = os.path.dirname(__file__)
1000972
cfg_path = os.path.realpath(os.path.join(base_dir, args.usdx_dir, 'config.ini'))
1001973
if not os.path.exists(cfg_path):
1002-
print(f"Config path not found: {cfg_path}")
974+
logger.error(f"Config path not found: {cfg_path}")
1003975
sys.exit(1)
1004976
cp = NoSpaceConfigParser()
1005977
cp.optionxform = str
@@ -1013,8 +985,8 @@ def initialize_record_section():
1013985
for k in keys_to_remove:
1014986
cp.remove_option('Record', k)
1015987
# Add 6 virtual sinks
1016-
for i in range(1, 7):
1017-
cp['Record'][f'DeviceName[{i}]'] = f'smartphone-mic-{i-1}-sink Audio/Source/Virtual sink'
988+
for i in range(1, 6):
989+
cp['Record'][f'DeviceName[{i}]'] = f'smartphone-mic-{i}-sink Audio/Source/Virtual sink'
1018990
cp['Record'][f'Input[{i}]'] = '0'
1019991
cp['Record'][f'Latency[{i}]'] = '-1'
1020992
cp['Record'][f'Channel1[{i}]'] = str(i)
@@ -1023,11 +995,11 @@ def initialize_record_section():
1023995
with open(tmp_path, 'w', encoding='utf-8') as fh:
1024996
cp.write(fh)
1025997
os.replace(tmp_path, cfg_path)
1026-
print(f"[Record] section in config.ini initialized for 6 virtual sinks.")
998+
logger.info("[Record] section in config.ini initialized for 6 virtual sinks.")
1027999

10281000
def setup_domain_hotspot_mapping(domain):
1001+
print(f"Setting up domain '{domain}' to map to Wi-Fi hotspot IP addresses...")
10291002
CONF_PATH = "/etc/NetworkManager/dnsmasq-shared.d/usdx.conf"
1030-
print("Detecting Wi-Fi hotspots...")
10311003
try:
10321004
iw_result = subprocess.run(["iw", "dev"], capture_output=True, text=True)
10331005
hotspots = []
@@ -1039,7 +1011,7 @@ def setup_domain_hotspot_mapping(domain):
10391011
hotspots.append(iface)
10401012
iface = None
10411013
if not hotspots:
1042-
print("No Wi-Fi hotspot found.")
1014+
logger.info("No Wi-Fi hotspot found.")
10431015
for IFACE in hotspots:
10441016
ip_result = subprocess.run(["ip", "-4", "-o", "addr", "show", "dev", IFACE], capture_output=True, text=True)
10451017
ip = None
@@ -1048,11 +1020,11 @@ def setup_domain_hotspot_mapping(domain):
10481020
ip = part.split("/")[0]
10491021
break
10501022
if not ip:
1051-
print(f"Could not determine IP address for {IFACE}. Skipping.")
1023+
logger.info(f"Could not determine IP address for {IFACE}. Skipping.")
10521024
continue
1053-
print(f"Hotspot device: {IFACE}")
1054-
print(f"IP address: {ip}")
1055-
print("----")
1025+
logger.info(f"Hotspot device: {IFACE}")
1026+
logger.info(f"IP address: {ip}")
1027+
logger.info("----")
10561028
# Prepare new config content
10571029
new_content = f"address=/{domain}/{ip}\nlocal-ttl=86400\n"
10581030
# Read current config if exists
@@ -1068,33 +1040,33 @@ def setup_domain_hotspot_mapping(domain):
10681040
# Backup config with sudo
10691041
if os.path.exists(CONF_PATH):
10701042
subprocess.run(["sudo", "cp", CONF_PATH, CONF_PATH + ".bak"])
1071-
print(f"Backed up {CONF_PATH} to {CONF_PATH}.bak")
1043+
logger.info(f"Backed up {CONF_PATH} to {CONF_PATH}.bak")
10721044
# Write new config with sudo tee
10731045
proc = subprocess.run(["echo", new_content], capture_output=True, text=True)
10741046
tee_proc = subprocess.run(["sudo", "tee", CONF_PATH], input=proc.stdout, text=True, capture_output=True)
10751047
if tee_proc.returncode != 0:
1076-
print(f"Failed to write {CONF_PATH}: {tee_proc.stderr}")
1048+
logger.error(f"Failed to write {CONF_PATH}: {tee_proc.stderr}")
10771049
sys.exit(1)
10781050
# Set world-readable permissions
10791051
subprocess.run(["sudo", "chmod", "644", CONF_PATH])
1080-
print(f"Updated {CONF_PATH}:")
1081-
print(new_content)
1052+
logger.info(f"Updated {CONF_PATH}:")
1053+
logger.info(new_content)
10821054
# Restart NetworkManager
1083-
print("Restarting NetworkManager to apply changes...")
1055+
logger.info("Restarting NetworkManager to apply changes...")
10841056
result = subprocess.run(["sudo", "systemctl", "restart", "NetworkManager"])
10851057
if result.returncode == 0:
1086-
print("NetworkManager restarted successfully.")
1058+
logger.info("NetworkManager restarted successfully.")
10871059
else:
1088-
print("Failed to restart NetworkManager. Please check manually.")
1060+
logger.error("Failed to restart NetworkManager. Please check manually.")
10891061
else:
1090-
print(f"No changes needed for {CONF_PATH}.")
1091-
print("All done!")
1062+
logger.info(f"No changes needed for {CONF_PATH}.")
1063+
logger.info("All done!")
10921064
except Exception as e:
1093-
print("Error during domain setup:", e, file=sys.stderr)
1065+
logger.error("Error during domain setup:", e)
10941066
sys.exit(1)
10951067

10961068
def remap_ssl_port():
1097-
print("Remapping port 443 to port", args.port, "using iptables...")
1069+
print("Remapping port 443 to", args.port, "using iptables...")
10981070
try:
10991071
# Use 'ip -4 -o addr show' to get all IPv4 addresses
11001072
ip_list = []
@@ -1112,43 +1084,29 @@ def remap_ssl_port():
11121084
continue
11131085
ip_list.append(ip)
11141086
if not ip_list:
1115-
print("No valid global IPv4 addresses found for remapping.")
1087+
logger.info("No valid global IPv4 addresses found for remapping.")
11161088
for ip in ip_list:
11171089
# Check if rule already exists
11181090
check_cmd = ["sudo", "iptables", "-t", "nat", "-C", "PREROUTING", "-p", "tcp", "-d", ip, "--dport", "443", "-j", "REDIRECT", "--to-port", str(args.port)]
11191091
check_result = subprocess.run(check_cmd, capture_output=True, text=True)
11201092
if check_result.returncode == 0:
1121-
print(f"Rule for {ip}:443 -> {args.port} already exists, skipping.")
1093+
logger.info(f"Rule for {ip}:443 -> {args.port} already exists, skipping.")
11221094
continue
11231095
cmd = ["sudo", "iptables", "-t", "nat", "-A", "PREROUTING", "-p", "tcp", "-d", ip, "--dport", "443", "-j", "REDIRECT", "--to-port", str(args.port)]
1124-
print("Running:", " ".join(cmd))
1096+
logger.info("Running: %s", " ".join(cmd))
11251097
result = subprocess.run(cmd, capture_output=True, text=True)
11261098
if result.returncode == 0:
1127-
print(f"Remapped 443 to {args.port} for {ip}")
1099+
logger.info("Remapped 443 to %d for %s", args.port, ip)
11281100
else:
1129-
print(f"Failed to remap for {ip}: {result.stderr}")
1101+
logger.error("Failed to remap for %s: %s", ip, result.stderr)
11301102
except Exception as e:
1131-
print("Error remapping SSL port:", e)
1103+
logger.error("Error remapping SSL port: %s", e)
11321104

11331105
def handle_start_hotspot(hotspot_name):
11341106
if not hotspot_name:
11351107
return
1136-
status = subprocess.run(["nmcli", "c", "show", hotspot_name], capture_output=True, text=True)
1137-
if status.returncode == 0:
1138-
for line in status.stdout.splitlines():
1139-
if line.strip().startswith("ipv4.addresses:"):
1140-
ip = line.split(":", 1)[1].strip()
1141-
if ip and ip != '--':
1142-
print(f"Hotspot '{hotspot_name}' is up with IP {ip}.")
1143-
return
1144-
print(f"Bringing up hotspot '{hotspot_name}' with nmcli...")
1145-
result = subprocess.run(["nmcli", "c", "up", hotspot_name], capture_output=True, text=True)
1146-
if result.returncode != 0:
1147-
print(f"Failed to start hotspot '{hotspot_name}': {result.stderr}")
1148-
sys.exit(1)
1149-
print(f"Hotspot '{hotspot_name}' activation requested. Waiting for it to have an IP address...")
1150-
# Wait for the hotspot to be up and have an IP address
1151-
for _ in range(20):
1108+
waiting = 0
1109+
while waiting < 30:
11521110
status = subprocess.run(["nmcli", "c", "show", hotspot_name], capture_output=True, text=True)
11531111
if status.returncode == 0:
11541112
for line in status.stdout.splitlines():
@@ -1157,10 +1115,48 @@ def handle_start_hotspot(hotspot_name):
11571115
if ip and ip != '--':
11581116
print(f"Hotspot '{hotspot_name}' is up with IP {ip}.")
11591117
return
1160-
time.sleep(1)
1161-
print(f"Timeout waiting for hotspot '{hotspot_name}' to have an IP address.")
1118+
elif waiting == 0:
1119+
logger.info(f"Bringing up hotspot '{hotspot_name}' with nmcli...")
1120+
result = subprocess.run(["nmcli", "c", "up", hotspot_name], capture_output=True, text=True)
1121+
waiting = 1
1122+
if result.returncode != 0:
1123+
logger.error(f"Failed to start hotspot '{hotspot_name}': {result.stderr}")
1124+
sys.exit(1)
1125+
else:
1126+
logger.info(f"Waiting for an IP address...")
1127+
waiting += 1
1128+
time.sleep(1)
1129+
logger.error(f"Timeout waiting for hotspot '{hotspot_name}' to have an IP address.")
11621130
sys.exit(1)
11631131

1132+
def setup_iptables_forwarding(internet_device, hotspot_device):
1133+
print(f"Setting up forwarding from internet={internet_device} to hotspot={hotspot_device}")
1134+
rules = [
1135+
{
1136+
"check": ["sudo", "iptables", "-t", "nat", "-C", "POSTROUTING", "-o", hotspot_device, "-j", "MASQUERADE"],
1137+
"add": ["sudo", "iptables", "-t", "nat", "-A", "POSTROUTING", "-o", hotspot_device, "-j", "MASQUERADE"]
1138+
},
1139+
{
1140+
"check": ["sudo", "iptables", "-C", "FORWARD", "-i", hotspot_device, "-o", internet_device, "-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"],
1141+
"add": ["sudo", "iptables", "-A", "FORWARD", "-i", hotspot_device, "-o", internet_device, "-m", "state", "--state", "RELATED,ESTABLISHED", "-j", "ACCEPT"]
1142+
},
1143+
{
1144+
"check": ["sudo", "iptables", "-C", "FORWARD", "-i", internet_device, "-o", hotspot_device, "-j", "ACCEPT"],
1145+
"add": ["sudo", "iptables", "-A", "FORWARD", "-i", internet_device, "-o", hotspot_device, "-j", "ACCEPT"]
1146+
}
1147+
]
1148+
for rule in rules:
1149+
logger.info("Checking: %s", " ".join(rule["check"]))
1150+
check_result = subprocess.run(rule["check"], capture_output=True, text=True)
1151+
if check_result.returncode == 0:
1152+
logger.info("Rule already exists: %s", " ".join(rule['add']))
1153+
continue
1154+
add_result = subprocess.run(rule["add"], capture_output=True, text=True)
1155+
if add_result.returncode == 0:
1156+
logger.info("Added rule: %s", " ".join(rule["add"]))
1157+
else:
1158+
logger.error("Failed to add rule: %s\n%s", " ".join(rule["add"]), add_result.stderr)
1159+
11641160

11651161
if __name__ == '__main__':
11661162

@@ -1169,12 +1165,14 @@ def handle_start_hotspot(hotspot_name):
11691165
# Networking & Security
11701166
net_group = parser.add_argument_group('Networking & Security')
11711167
net_group.add_argument('--start-hotspot', type=str, default='', help='Start the given hotspot using nmcli before domain setup')
1168+
net_group.add_argument('--internet-device', type=str, default='', help='Network interface providing internet connectivity (e.g., wlan0)')
1169+
net_group.add_argument('--hotspot-device', type=str, default='', help='Network interface for the hotspot (e.g., wlan1)')
11721170
net_group.add_argument('--ssl', action='store_true', help='Enable SSL (requires --chain and --key)')
11731171
net_group.add_argument('--chain', type=str, default=None, help='SSL chain/cert file (fullchain.pem or cert.pem)')
11741172
net_group.add_argument('--key', type=str, default=None, help='SSL private key file (privkey.pem)')
11751173
net_group.add_argument('--port', type=int, default=5000, help='Port to run the server on (default: 5000)')
11761174
net_group.add_argument('--remap-ssl-port', action='store_true', help='Remap ports so that users can access the server on the default HTTPS port. Invokes iptables and sudo!')
1177-
net_group.add_argument('--domain', type=str, default='', help='Setup a domain to hotspot IP mapping via NetworkManager/dnsmasq, requires sudo')
1175+
net_group.add_argument('--domain', type=str, default='localhost', help='Setup a domain to hotspot IP mapping via NetworkManager/dnsmasq, requires sudo')
11781176

11791177
# UltraStar Deluxe Integration
11801178
usdx_group = parser.add_argument_group('UltraStar Deluxe Integration')
@@ -1194,13 +1192,17 @@ def handle_start_hotspot(hotspot_name):
11941192

11951193
logging.basicConfig(filename='virtual-microphone.log', level=logging.INFO if not args.debug else logging.DEBUG)
11961194

1195+
# Run iptables forwarding if both devices are provided
1196+
if args.internet_device and args.hotspot_device:
1197+
setup_iptables_forwarding(args.internet_device, args.hotspot_device)
1198+
11971199
if args.start_hotspot:
11981200
handle_start_hotspot(args.start_hotspot)
11991201

12001202
if args.set_inputs:
12011203
initialize_record_section()
12021204

1203-
if args.domain != '':
1205+
if args.domain != 'localhost':
12041206
setup_domain_hotspot_mapping(args.domain)
12051207

12061208
WebRTCMicrophoneManager()
@@ -1265,6 +1267,7 @@ def stale_cleanup_loop():
12651267

12661268
# Build/update song index at startup
12671269
try:
1270+
print("Scanning songs and building index...")
12681271
scan_songs_and_build_index(find_root=args.usdx_dir)
12691272
except Exception:
12701273
logger.exception('Error scanning songs at startup')
@@ -1278,7 +1281,7 @@ def stale_cleanup_loop():
12781281
# Truncate/create the file
12791282
with open(upl_path, 'w', encoding='utf-8') as fh:
12801283
fh.truncate(0)
1281-
logger.info('Initialized playlist at %s', upl_path)
1284+
print(f'Initialized playlist {upl_path}')
12821285
except Exception:
12831286
logger.exception('Failed to create/truncate playlist file')
12841287

@@ -1296,21 +1299,23 @@ def stale_cleanup_loop():
12961299
exe_path = os.path.abspath(os.path.join(args.usdx_dir, "ultrastardx"))
12971300
cwd_path = os.path.abspath(args.usdx_dir)
12981301
subprocess.Popen([exe_path], cwd=cwd_path)
1299-
print("UltraStar Deluxe launched.")
1302+
logger.info("UltraStar Deluxe launched.")
13001303
except Exception as e:
1301-
print("Failed to launch UltraStar Deluxe:", e)
1304+
logger.error("Failed to launch UltraStar Deluxe: %s", e)
13021305

13031306
# SSL context handling
13041307
ssl_context = None
13051308
if args.ssl:
13061309
if args.chain and args.key:
13071310
ssl_context = (args.chain, args.key)
1311+
13081312
if ssl_context:
1309-
print(f"Starting SmartMicrophone server with SSL on port {port}...")
1310-
if port == 443:
1311-
print(f"Access the server at: https://<server-ip>/")
1313+
logger.info("Starting SmartMicrophone server with SSL on port %d...", port)
1314+
if port == 443 or args.remap_ssl_port:
1315+
print(f"Access the server at: https://{args.domain}/")
13121316
else:
1313-
print(f"Access the server at: https://<server-ip>:{port}/")
1317+
print(f"Access the server at: https://{args.domain}:{port}/")
13141318
app.run(host='0.0.0.0', port=port, debug=args.debug, use_reloader=False, ssl_context=ssl_context)
13151319
else:
13161320
app.run(host='0.0.0.0', port=port, debug=args.debug, use_reloader=False)
1321+
print(f"Access the server at: https://{args.domain}:{port}/")

templates/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ <h3>Debug</h3>
338338
<!-- change name moved into Settings tab -->
339339

340340
<!-- Bottom video (replaces previous lock button). Clicking requests fullscreen for the video -->
341-
<video id="lockVideo"
341+
<video id="lockBtn"
342342
playsinline
343343
muted
344344
loop

0 commit comments

Comments
 (0)