|
|
@@ -2,12 +2,21 @@ from __future__ import print_function
|
|
|
from argparse import ArgumentParser
|
|
|
from hashlib import md5
|
|
|
from datetime import datetime
|
|
|
+from binascii import hexlify
|
|
|
+from threading import Thread
|
|
|
+from StringIO import StringIO
|
|
|
+from io import BufferedWriter
|
|
|
+from subprocess import PIPE
|
|
|
+import subprocess
|
|
|
import sqlite3
|
|
|
+import signal
|
|
|
+import curses
|
|
|
import time
|
|
|
import json
|
|
|
import sys
|
|
|
import os
|
|
|
|
|
|
+
|
|
|
strptime = datetime.strptime
|
|
|
ARG_DATE_FMT = '%Y-%m-%d %H:%M:%S'
|
|
|
simple_date = lambda s: strptime(s, ARG_DATE_FMT)
|
|
|
@@ -39,6 +48,9 @@ def hash_file(filename):
|
|
|
break
|
|
|
return ahash.hexdigest()
|
|
|
|
|
|
+def parse_stations(string):
|
|
|
+ return string.split(',')
|
|
|
+
|
|
|
def main():
|
|
|
parser = ArgumentParser()
|
|
|
subparsers = parser.add_subparsers(dest='entity')
|
|
|
@@ -57,6 +69,13 @@ def main():
|
|
|
|
|
|
stations_parser = subparsers.add_parser('station')
|
|
|
stations_parser.add_argument('action')
|
|
|
+ stations_parser.add_argument('-stations', dest='stations',
|
|
|
+ type=parse_stations)
|
|
|
+ stations_parser.add_argument('--play-only', dest='play_only',
|
|
|
+ action='store_const',
|
|
|
+ const=True,
|
|
|
+ default=False
|
|
|
+ )
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
action = args.action
|
|
|
@@ -151,7 +170,157 @@ def main():
|
|
|
for dr in dirs:
|
|
|
if '.' not in dr:
|
|
|
print(dr)
|
|
|
+
|
|
|
+ elif action == 'record-all' or action == 'play-all':
|
|
|
+ import pyaudio, wave
|
|
|
+
|
|
|
+ if action == 'play-all':
|
|
|
+ args.play_only = True
|
|
|
+
|
|
|
+ audio = pyaudio.PyAudio()
|
|
|
+ stream = audio.open(format=pyaudio.paInt16,
|
|
|
+ channels=1,
|
|
|
+ rate=44100,
|
|
|
+ output=True)
|
|
|
+
|
|
|
+
|
|
|
+ receivers_count = config['receivers_count']
|
|
|
+ processes = []
|
|
|
+ transcoders = []
|
|
|
+ totals = []
|
|
|
+ basepath = '/var/fourier/tests'
|
|
|
+ env = os.environ
|
|
|
+ stream_index = 0
|
|
|
+
|
|
|
+ if args.stations:
|
|
|
+ stations = args.stations
|
|
|
+ if len(stations) < receivers_count:
|
|
|
+ for i in range(receivers_count) - len(stations):
|
|
|
+ receivers_count.append('98.5')
|
|
|
+ else:
|
|
|
+ stations = ['98.5'] * receivers_count
|
|
|
+
|
|
|
+ print(stations)
|
|
|
+
|
|
|
+ if not os.path.isdir(basepath):
|
|
|
+ os.mkdir(basepath)
|
|
|
+
|
|
|
+ test_id = hexlify(os.urandom(4))
|
|
|
+
|
|
|
+ for index in range(receivers_count):
|
|
|
+ filename = os.path.join(basepath, "{}-{}.mp3"\
|
|
|
+ .format(test_id, index)
|
|
|
+ )
|
|
|
+
|
|
|
+ if not args.play_only:
|
|
|
+ ffmpeg = subprocess.Popen([
|
|
|
+ 'ffmpeg', '-f', 's16le', '-i', 'pipe:0',
|
|
|
+ '-ac', '1', '-ar', '24000',
|
|
|
+ '-ab', '64k',
|
|
|
+ '-nostdin',
|
|
|
+ '-f', 'mp3',
|
|
|
+ filename,
|
|
|
+ ],
|
|
|
+ stdin=PIPE,
|
|
|
+ stdout=PIPE,
|
|
|
+ stderr=PIPE,
|
|
|
+ env=env,
|
|
|
+ preexec_fn=os.setpgrp,
|
|
|
+ close_fds=True,
|
|
|
+ )
|
|
|
+ transcoders.append(ffmpeg)
|
|
|
+
|
|
|
+ rtl = subprocess.Popen([
|
|
|
+ 'rtl_fm', '-M', 'wbfm', '-g', '10',
|
|
|
+ '-d', str(index),
|
|
|
+ '-f', '{}M'.format(stations[index]),
|
|
|
+ '-o', '4',
|
|
|
+ '-F', '8',
|
|
|
+ '-p', '200',
|
|
|
+ '-s', '88200',
|
|
|
+ '-r', '44100',
|
|
|
+ ],
|
|
|
+
|
|
|
+ stdout=PIPE,
|
|
|
+ stdin=PIPE,
|
|
|
+ stderr=PIPE,
|
|
|
+ env=env,
|
|
|
+ preexec_fn=os.setpgrp,
|
|
|
+ close_fds=True,
|
|
|
+ )
|
|
|
+
|
|
|
+ processes.append(rtl)
|
|
|
+ totals.append(0)
|
|
|
+
|
|
|
+ scr = curses.initscr()
|
|
|
+ scr.addstr(0, 0, 'Sintonizadores')
|
|
|
+ scr.addstr(receivers_count + 2, 0,
|
|
|
+ 'Presiona un número para escuchar'
|
|
|
+ )
|
|
|
+ if args.play_only:
|
|
|
+ scr.addstr(receivers_count + 3, 0,
|
|
|
+ 'Solo reproduciendo'
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ scr.addstr(receivers_count + 4, 0,
|
|
|
+ 'Reproduciendo y grabando'
|
|
|
+ )
|
|
|
+ scr.addstr(receivers_count + 4, 0,
|
|
|
+ 'ID de prueba: /var/fourier/tests/{}-x.mp3'\
|
|
|
+ .format(test_id)
|
|
|
+ )
|
|
|
+ scr.addstr(receivers_count + 5, 0,
|
|
|
+ 'Usar --play-only para solo reproducir'
|
|
|
+ )
|
|
|
+ scr.addstr(stream_index + 1, 0, '>')
|
|
|
+ scr.refresh()
|
|
|
+ scr.timeout(0)
|
|
|
+ curses.noecho()
|
|
|
+ curses.curs_set(0)
|
|
|
+
|
|
|
+ try:
|
|
|
+ while 1:
|
|
|
+ refresh = False
|
|
|
+ for index in range(receivers_count):
|
|
|
+ data = processes[index].stdout.read(4096)
|
|
|
+ if data:
|
|
|
+ if index == stream_index:
|
|
|
+ stream.write(data)
|
|
|
+
|
|
|
+ if not args.play_only:
|
|
|
+ transcoders[index].stdin.write(data)
|
|
|
+
|
|
|
+ totals[index] += len(data)
|
|
|
+
|
|
|
+ if totals[index] % 10 == 0:
|
|
|
+ scr.addstr(index + 1, 5, '{:01x} {:>4} {}\n\n'\
|
|
|
+ .format(index, stations[index], totals[index])
|
|
|
+ )
|
|
|
+ refresh = True
|
|
|
+
|
|
|
+ k = scr.getch()
|
|
|
+ if k > -1:
|
|
|
+ key = int(chr(k), 16) if k > 0 else 0
|
|
|
+ if key >= 0 and key < receivers_count:
|
|
|
+ scr.addstr(stream_index + 1, 0, ' ')
|
|
|
+ stream_index = key
|
|
|
+ refresh = True
|
|
|
+
|
|
|
+ if refresh:
|
|
|
+ scr.addstr(stream_index + 1, 0, '>')
|
|
|
+ scr.refresh()
|
|
|
|
|
|
+ except KeyboardInterrupt:
|
|
|
+ curses.endwin()
|
|
|
+ for index in range(receivers_count):
|
|
|
+ if not args.play_only:
|
|
|
+ transcoders[index].send_signal(signal.SIGINT)
|
|
|
+ processes[index].send_signal(signal.SIGINT)
|
|
|
+
|
|
|
+
|
|
|
+ except Exception as ex:
|
|
|
+ curses.endwin()
|
|
|
+ print(ex)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
main()
|