Skip to content

Commit 3b9fc5a

Browse files
committed
implementing mplayer recording monitoring and pausing
1 parent c541249 commit 3b9fc5a

File tree

1 file changed

+94
-28
lines changed

1 file changed

+94
-28
lines changed

pyradio/player.py

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ def __init__(self,
297297
from .del_vlc_log import RemoveWinVlcLogFiles
298298
threading.Thread(target=RemoveWinVlcLogFiles(self.config_dir)).start()
299299

300+
''' Recording monitor player for MPlayer and VLC '''
301+
self.monitor = self.monitor_process = self.monitor_opts = None
302+
300303
@property
301304
def recording(self):
302305
if self._recording_from_schedule > 0:
@@ -1429,6 +1432,7 @@ def play(self,
14291432
encoding=''
14301433
):
14311434
''' use a multimedia player to play a stream '''
1435+
self.monitor = self.monitor_process = self.monitor_opts = None
14321436
self.recording_filename = ''
14331437
self.volume = -1
14341438
self.close()
@@ -1449,7 +1453,7 @@ def play(self,
14491453
self._station_encoding = self.config_encoding
14501454
opts = []
14511455
isPlayList = streamUrl.split("?")[0][-3:] in ['m3u', 'pls']
1452-
opts = self._buildStartOpts(streamUrl, isPlayList)
1456+
opts, self.monitor_opts = self._buildStartOpts(streamUrl, isPlayList)
14531457
self.stop_mpv_status_update_thread = False
14541458
if logger.isEnabledFor(logging.INFO):
14551459
logger.info('Executing command: {}'.format(' '.join(opts)))
@@ -1535,19 +1539,26 @@ def play(self,
15351539
logger.debug('playback detection thread not starting (timeout is 0)')
15361540
if logger.isEnabledFor(logging.INFO):
15371541
logger.info('----==== {} player started ====----'.format(self.PLAYER_NAME))
1542+
if self.recording == self.RECORD_AND_LISTEN \
1543+
and self.PLAYER_NAME != 'mpv':
1544+
threading.Thread(
1545+
target=self.create_monitor_player,
1546+
args=(lambda: self.stop_mpv_status_update_thread or \
1547+
self.stop_win_vlc_status_update_thread, )
1548+
).start()
15381549

15391550
def _sendCommand(self, command):
15401551
''' send keystroke command to player '''
1541-
1542-
if(self.process is not None):
1543-
if logger.isEnabledFor(logging.DEBUG):
1544-
logger.debug('Sending Command: {}'.format(command).strip())
1545-
try:
1546-
self.process.stdin.write(command.encode('utf-8', 'replace'))
1547-
self.process.stdin.flush()
1548-
except:
1549-
if logger.isEnabledFor(logging.ERROR):
1550-
logger.error('Error while sending Command: {}'.format(command).strip(), exc_info=True)
1552+
for a_process in (self.process, self.monitor_process):
1553+
if a_process is not None:
1554+
if logger.isEnabledFor(logging.DEBUG):
1555+
logger.debug('Sending Command: {}'.format(command).strip())
1556+
try:
1557+
a_process.stdin.write(command.encode('utf-8', 'replace'))
1558+
a_process.stdin.flush()
1559+
except:
1560+
if logger.isEnabledFor(logging.ERROR):
1561+
logger.error('Error while sending Command: {}'.format(command).strip(), exc_info=True)
15511562

15521563
def close_from_windows(self):
15531564
''' kill player instance when window console is closed '''
@@ -1582,6 +1593,13 @@ def close(self):
15821593
pass
15831594
finally:
15841595
self.update_thread = None
1596+
if self.monitor_process is not None:
1597+
self._kill_process_tree(self.monitor_process.pid)
1598+
try:
1599+
self.monitor_process.wait()
1600+
except:
1601+
pass
1602+
self.monitor = self.monitor_process = self.monitor_opts = None
15851603

15861604
def _kill_process_tree(self, pid):
15871605
if psutil.pid_exists(pid):
@@ -1653,9 +1671,10 @@ def togglePause(self):
16531671
if self.PLAYER_NAME == 'mpv':
16541672
self.paused = self._pause()
16551673
elif self.PLAYER_NAME == 'vlc':
1674+
self.paused = not self.paused
16561675
self._pause()
16571676
else:
1658-
self.muted = not self.muted
1677+
self.paused = not self.paused
16591678
self._pause()
16601679
if self.paused:
16611680
# self._stop_delay_thread()
@@ -1916,7 +1935,7 @@ def _buildStartOpts(self, streamUrl, playList=False):
19161935
opts.append('--stream-record=' + self.recording_filename)
19171936
if logger.isEnabledFor(logging.DEBUG):
19181937
logger.debug('---=== Starting Recording: "{}" ===---',format(self.recording_filename))
1919-
return opts
1938+
return opts, None
19201939

19211940

19221941
def _fix_returned_data(self, data):
@@ -2034,6 +2053,7 @@ def _stop(self):
20342053
if not platform.startswith('win'):
20352054
os.system('rm ' + self.mpvsocket + ' 2>/dev/null');
20362055
self._icy_data = {}
2056+
self.monitor = self.monitor_process = self.monitor_opts = None
20372057

20382058
def _volume_up(self):
20392059
''' increase mpv's volume '''
@@ -2296,6 +2316,29 @@ def __init__(self,
22962316
)
22972317
self.config_files = self.all_config_files['mplayer']
22982318

2319+
def create_monitor_player(self, stop):
2320+
while not os.path.exists(self.recording_filename):
2321+
sleep(.1)
2322+
if stop():
2323+
logger.error('Asked to stop. Exiting....')
2324+
return
2325+
while os.path.getsize(self.recording_filename) < 500:
2326+
sleep(.1)
2327+
if stop():
2328+
logger.error('Asked to stop. Exiting....')
2329+
return
2330+
if stop():
2331+
logger.error('Asked to stop. Exiting....')
2332+
return
2333+
if logger.isEnabledFor(logging.INFO):
2334+
logger.info('----==== {} monitor started ====----'.format(self.PLAYER_NAME))
2335+
self.monitor_process = subprocess.Popen(
2336+
self.monitor_opts, shell=False,
2337+
stdout=subprocess.PIPE,
2338+
stdin=subprocess.PIPE,
2339+
stderr=subprocess.STDOUT
2340+
)
2341+
22992342
def save_volume(self):
23002343
if platform.startswith('win'):
23012344
return self._do_save_volume('volume={}\r\n')
@@ -2342,6 +2385,7 @@ def _configHasProfile(self):
23422385
def _buildStartOpts(self, streamUrl, playList=False):
23432386
''' Builds the options to pass to mplayer subprocess.'''
23442387
opts = [self.PLAYER_CMD, '-vo', 'null', '-quiet']
2388+
monitor_opts = None
23452389

23462390
''' this will set the profile too '''
23472391
params = []
@@ -2355,20 +2399,17 @@ def _buildStartOpts(self, streamUrl, playList=False):
23552399
if self.USE_PROFILE == -1:
23562400
self.USE_PROFILE = self._configHasProfile()
23572401

2358-
if self._recording == self.RECORD_WITH_SILENCE:
2359-
opts.append('--profile=silent')
2402+
if self.USE_PROFILE == 1:
2403+
opts.append('-profile')
2404+
opts.append(self.profile_name)
2405+
if (logger.isEnabledFor(logging.INFO)):
2406+
logger.info('Using profile: "[{}]"'.format(self.profile_name))
23602407
else:
2361-
if self.USE_PROFILE == 1:
2362-
opts.append('-profile')
2363-
opts.append(self.profile_name)
2364-
if (logger.isEnabledFor(logging.INFO)):
2365-
logger.info('Using profile: "[{}]"'.format(self.profile_name))
2366-
else:
2367-
if (logger.isEnabledFor(logging.INFO)):
2368-
if self.USE_PROFILE == 0:
2369-
logger.info('Profile "[{}]" not found in config file!!!'.format(self.profile_name))
2370-
else:
2371-
logger.info('No usable profile found')
2408+
if (logger.isEnabledFor(logging.INFO)):
2409+
if self.USE_PROFILE == 0:
2410+
logger.info('Profile "[{}]" not found in config file!!!'.format(self.profile_name))
2411+
else:
2412+
logger.info('No usable profile found')
23722413

23732414
if playList:
23742415
opts.append('-playlist')
@@ -2386,18 +2427,41 @@ def _buildStartOpts(self, streamUrl, playList=False):
23862427
## opts.append(r'C:\Users\Spiros\AppData\Roaming\pyradio\recordings\rec.mkv')
23872428
logger.error('\n\nself._recording = {}'.format(self._recording))
23882429
if self._recording > 0:
2430+
monitor_opts = opts[:]
2431+
if self._recording == self.RECORD_WITH_SILENCE:
2432+
try:
2433+
i = [y for y, x in enumerate(opts) if x == '-profile'][0]
2434+
opts[i+1] = 'silent'
2435+
except IndexError:
2436+
opts.append('-profile')
2437+
opts.append('silent')
2438+
try:
2439+
''' find and remove -playlist url '''
2440+
i = [y for y, x in enumerate(monitor_opts) if x == '-playlist'][0]
2441+
del monitor_opts[i+1]
2442+
del monitor_opts[i]
2443+
except IndexError:
2444+
''' not -playlist, find and remove url '''
2445+
i = [y for y, x in enumerate(monitor_opts) if x == streamUrl][0]
2446+
del monitor_opts[i]
23892447
self.recording_filename = self.getrecording_filename(self.name, '.mkv')
2448+
monitor_opts.append(self.recording_filename)
23902449
opts.append('-dumpstream')
23912450
opts.append('-dumpfile')
23922451
opts.append(self.recording_filename)
23932452
if logger.isEnabledFor(logging.DEBUG):
23942453
logger.debug('---=== Starting Recording: "{}" ===---',format(self.recording_filename))
2395-
return opts
2454+
logger.error('Opts:\n{0}\n{1}'.format(opts, monitor_opts))
2455+
return opts, monitor_opts
23962456

23972457
def _mute(self):
23982458
''' mute mplayer '''
23992459
self._sendCommand('m')
24002460

2461+
def _pause(self):
2462+
''' pause streaming (if possible) '''
2463+
self._sendCommand('p')
2464+
24012465
def pause(self):
24022466
''' pause streaming (if possible) '''
24032467
self._sendCommand('p')
@@ -2584,6 +2648,7 @@ def save_volume(self):
25842648
def _buildStartOpts(self, streamUrl, playList=False):
25852649
''' Builds the options to pass to vlc subprocess.'''
25862650
#opts = [self.PLAYER_CMD, "-Irc", "--quiet", streamUrl]
2651+
monitor_opts = None
25872652
if self.WIN:
25882653
''' Get a random port (44000-44999)
25892654
Create a log file for vlc and make sure it is unique
@@ -2642,7 +2707,7 @@ def _buildStartOpts(self, streamUrl, playList=False):
26422707
opts.append(self.recording_filename)
26432708
if logger.isEnabledFor(logging.DEBUG):
26442709
logger.debug('---=== Starting Recording: "{}" ===---',format(self.recording_filename))
2645-
return opts
2710+
return opts, monitor_opts
26462711

26472712
def _mute(self):
26482713
''' mute vlc '''
@@ -2689,6 +2754,7 @@ def _stop(self):
26892754
self._sendCommand('shutdown\n')
26902755
self._icy_data = {}
26912756
self.volume = -1
2757+
self.monitor = self.monitor_process = self.monitor_opts = None
26922758

26932759
def _remove_vlc_stdout_log_file(self):
26942760
file_to_remove = self._vlc_stdout_log_file

0 commit comments

Comments
 (0)