diff --git a/weboob/applications/radioob/radioob.py b/weboob/applications/radioob/radioob.py index 4c15a43c..9efd5218 100644 --- a/weboob/applications/radioob/radioob.py +++ b/weboob/applications/radioob/radioob.py @@ -19,14 +19,10 @@ from __future__ import print_function -import subprocess # FIXME use subprocess everywhere instead of os.spawn* +import subprocess import os -import sys import re import requests -import signal -import copy -import time from weboob.capabilities.radio import CapRadio, Radio from weboob.capabilities.audio import CapAudio, BaseAudio, Playlist, Album @@ -202,6 +198,14 @@ class Radioob(ReplApplication): audio.url = _obj.url + def check_exec(executable): + with open(os.devnull, 'w') as devnull: + process = subprocess.Popen(['which', executable], stdout=devnull) + if process.wait() != 0: + print('Please install "%s"' % executable, file=self.stderr) + return False + return True + def audio_to_file(_audio): ext = _audio.ext if not ext: @@ -216,188 +220,23 @@ class Radioob(ReplApplication): dest = audio_to_file(audio) if audio.url.startswith('rtmp'): - if not self.check_exec('rtmpdump'): + if not check_exec('rtmpdump'): return 1 args = ('rtmpdump', '-e', '-r', audio.url, '-o', dest) elif audio.url.startswith('mms'): - if not self.check_exec('mimms'): + if not check_exec('mimms'): return 1 args = ('mimms', '-r', audio.url, dest) else: - if self.check_exec('wget'): + if check_exec('wget'): args = ('wget', '-c', audio.url, '-O', dest) - elif self.check_exec('curl'): + elif check_exec('curl'): args = ('curl', '-C', '-', audio.url, '-o', dest) else: return 1 os.spawnlp(os.P_WAIT, args[0], *args) - - def check_exec(self, executable): - with open(os.devnull, 'w') as devnull: - process = subprocess.Popen(['which', executable], stdout=devnull) - if process.wait() != 0: - print('Please install "%s"' % executable, file=self.stderr) - return False - return True - - - def do_record(self, line): - """ - record ID [STREAM] - - Record each track of an audio stream in a separate file in a directory. - """ - - streams, dest = self.record_parse(line) - if isinstance(streams, int): - return streams - - for stream in streams: - self.record_stream(stream, dest, background = False) - - - def do_recordplay(self, line): - """ - recordplay ID [STREAM] - - Record each track of an audio stream in a separate file AND play it at the same time. - This takes care of not wasting bandwidth: only one connection to the stream is used. - """ - - streams,dest = self.record_parse(line) - if isinstance(streams, int): - return streams - - for stream in streams: - # Start the recorder in the background - # recpid = self.record_stream(stream, dest, background=True) - recpid = self.record_stream(stream, dest, background=True) - time.sleep(1) - self.logger.debug(u'streamripper recorder in background with PID: %i' % recpid) - - # Play the local relay server, not the original stream. - relay_port = self.config.get('relay_port') - if not relay_port: - relay_port = 8000 - self.logger.debug(u'No relay_port in config file, will use default: %i' % relay_port) - # Build a local stream to avoid changing the stream URL. - # localstream = copy.deepcopy(stream) # FIXME reference kept, why? - # localstream.url = u'http://localhost:%i' % relay_port - class Media: - def __init__(self, url, title, _id): - self.url = url - self.title = title - self.id = _id - localstream = Media(u'http://localhost:%i' % relay_port, stream.title, stream.id) - - player_name = self.config.get('media_player') - media_player_args = self.config.get('media_player_args') - if not player_name: - self.logger.debug(u'No media_player in config file, will try to guess.') - try: - self.player.play(localstream, player_name=player_name, player_args=media_player_args) - except KeyboardInterrupt: - self.logger.debug(u'Player closed') - pass - except: - e = sys.exc_info()[0] - self.logger.debug(u'Encountered an error: %s' % e) - raise - finally: - # Once player ends, terminate the recorder too. - self.logger.debug(u'Terminate the recorder') - # os.kill(recpid, signal.SIGTERM) - os.kill(recpid, signal.SIGKILL) - - - def record_parse(self, line): - _id, stream_id = self.parse_command_args(line, 2, 1) - - - try: - stream_id = int(stream_id) - except (ValueError, TypeError): - stream_id = 0 - - obj = self.retrieve_obj(_id) - - if obj is None: - print('No object matches with this id:', _id, file=self.stderr) - return 3 - - if isinstance(obj, Radio): - try: - streams = [obj.streams[stream_id]] - except IndexError: - print('Stream %d not found' % stream_id, file=self.stderr) - return 1 - elif isinstance(obj, BaseAudio): - streams = [obj] - - else: - streams = obj.tracks_list - - - if len(streams) == 0: - print('Radio or Audio file not found:', _id, file=self.stderr) - return 3 - - dest = "records" - return streams, dest - - - def record_stream(self, stream, dest, background = False): - """ - Run streamripper on the given stream and save files in the given directory. - - If background is False, this function returns the process id of the new process; - if background is True, returns the process’s exit code if it exits normally, - or -signal, where signal is the signal that killed the process. - """ - if dest is None: - title = stream.title if stream.title else stream.id - dest = '%s' % re.sub('[?:/]', '-', title) - - if not os.path.exists(dest): - os.makedirs(dest) - - if not os.path.isdir(dest): - print('The destination "%s" is not a directory' % dest, file=self.stderr) - return 5 - - if not self.check_exec('streamripper'): - print('streamripper not found, please install it', file=self.stderr) - return 1 - - if background: - # Start a relay server, but do not try to find a free port. - relay_port = self.config.get('relay_port') - if not relay_port: - relay_port = 8000 - args = ['streamripper', stream.url, '-d', dest, '-z', '-r', str(relay_port)] - spawn = subprocess.Popen - else: - args = ['streamripper', stream.url, '-d', dest] - spawn = subprocess.call - - try: - self.logger.debug(u'Invoking: %s' % (u' '.join([str(a) for a in args]))) - proc = spawn(args) - except OSError: - print(u'Failed to start the recorder') - return 7 - - if proc.returncode: - print('The recorder ended unexpectedly', file=self.stderr) - self.logger.debug(u'streamripper error, pid=%i, code=%i' % (proc.pid, proc.returncode)) - return 8 - - return proc.pid - - - def complete_play(self, text, line, *ignored): args = line.split(' ') if len(args) == 2: