Skip to content

Commit b6653b7

Browse files
committed
- pyradio_client:
- the "i" / "info" response has been beautified - the IP and PORT will only be printed as a response to the "i" / "info" command, provided that the -s command line parameter has not been used - adding referer stations' support - updating docs
1 parent 78ace51 commit b6653b7

File tree

9 files changed

+143
-19
lines changed

9 files changed

+143
-19
lines changed

docs/index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ <h2 id="table-of-contents">Table of Contents <span style="padding-left: 10px;"><
119119
<li><a href="#player-detection-/-selection">Player detection / selection</a>
120120
<ul>
121121
<li><a href="#changing-player-mid-session">Changing player mid-session</a></li>
122+
<li><a href="#specifying-a-station&#39;s-referer-url">Specifying a station’s Referer URL</a>
123+
<ul>
124+
<li><a href="#a-note-of-caution">A note of caution</a></li>
125+
</ul></li>
122126
<li><a href="#extra-player-parameters">Extra Player Parameters</a>
123127
<ul>
124128
<li><a href="#using-the-configuration-window">Using the Configuration Window</a></li>
@@ -1762,6 +1766,17 @@ <h3 id="changing-player-mid-session">Changing player mid-session</h3>
17621766
<p>Pressing “<strong>\m</strong>” will bring up the “<em>Switch Media Player</em>” window, where a different player can be activated.</p>
17631767
<p>If <strong>recording is on</strong> while using the previously activated player, it will remain on with the newly activated one. This actually means that the recording will stop when the old player is stopped and resumed when the new player is activated (creating a new recorder file). There is just one exception to that; selecting <strong>VLC</strong> is not possible on <strong>Windows</strong>, since <strong>VLC</strong> does not support recording on this platform.</p>
17641768
<p style="margin: 1.5em 4em 0 4em; text-indent: -2.5em;"><strong>Note:</strong> The activated player will not be saved; <strong>PyRadio</strong> will still use the player defined at its config next time it is executed.</p>
1769+
<h3 id="specifying-a-stations-referer-url">Specifying a station’s Referer URL</h3>
1770+
<p>Although <strong>PyRadio</strong> is meant to be a readio station player, it can also be used to listen to video stations transmitting m3u8 playlists (HTTP Live Streaming or HLS).</p>
1771+
<p>The thing with these transmissions is that usually a <strong>Referer URL</strong> has to be provided so that the connection does not fail.</p>
1772+
<p><strong>PyRadio</strong> now does support the declaration of a <strong>Referer URL</strong> for individual stations; it does it in an “anorthodox” way, but it is possible.</p>
1773+
<p>So, let us imagine that a station called “<em>My video station</em>” has been added to a playlist. The user tries to play it but it fails; the referer URL is missing.</p>
1774+
<p>To rectify the situation, a file containing the referer URL would have to be saved in the config directory: its name must be the name of the station as it is in the playlist, followed by the “<strong>.referer.txt</strong>” extension.</p>
1775+
<p>In our example above, the file will have to be named:</p>
1776+
<p><strong>“My video station.referer.txt”</strong></p>
1777+
<h4 id="a-note-of-caution">A note of caution</h4>
1778+
<p>If such a file has been created for a station, please do not rename the station in the playlist manually; the “link” to the referer file will be lost.</p>
1779+
<p>Rename the station using <strong>PyRadio</strong> rename functionality and save the playlist instead; the referer file will be renamed as well.</p>
17651780
<h3 id="extra-player-parameters">Extra Player Parameters</h3>
17661781
<p>All three supported players can accept a significant number of “<em>command line options</em>”, which are well documented and accessible through man pages (on linux and MacOs) or the documentation (on Windows).</p>
17671782
<p><strong>PyRadio</strong> uses some of these parameters in order to execute and communicate with the players. In particular, the following parameters are in use <strong>by default</strong>:</p>

docs/index.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ To ensure the correct operation, please take these actions:
8282
* [Global encoding declaration](#global-encoding-declaration)
8383
* [Player detection / selection](#player-detection-/-selection)
8484
* [Changing player mid-session](#changing-player-mid-session)
85+
* [Specifying a station's Referer URL](#specifying-a-station's-referer-url)
86+
* [A note of caution](#a-note-of-caution)
8587
* [Extra Player Parameters](#extra-player-parameters)
8688
* [Using the Configuration Window](#using-the-configuration-window)
8789
* [Player connection protocol](#player-connection-protocol)
@@ -747,6 +749,28 @@ If **recording is on** while using the previously activated player, it will rema
747749

748750
**Note:** The activated player will not be saved; **PyRadio** will still use the player defined at its config next time it is executed.
749751

752+
### Specifying a station's Referer URL
753+
754+
Although **PyRadio** is meant to be a readio station player, it can also be used to listen to video stations transmitting m3u8 playlists (HTTP Live Streaming or HLS).
755+
756+
The thing with these transmissions is that usually a **Referer URL** has to be provided so that the connection does not fail.
757+
758+
**PyRadio** now does support the declaration of a **Referer URL** for individual stations; it does it in an "anorthodox" way, but it is possible.
759+
760+
So, let us imagine that a station called "*My video station*" has been added to a playlist. The user tries to play it but it fails; the referer URL is missing.
761+
762+
To rectify the situation, a file containing the referer URL would have to be saved in the config directory: its name must be the name of the station as it is in the playlist, followed by the "**.referer.txt**" extension.
763+
764+
In our example above, the file will have to be named:
765+
766+
**"My video station.referer.txt"**
767+
768+
#### A note of caution
769+
770+
If such a file has been created for a station, please do not rename the station in the playlist manually; the "link" to the referer file will be lost.
771+
772+
Rename the station using **PyRadio** rename functionality and save the playlist instead; the referer file will be renamed as well.
773+
750774
### Extra Player Parameters
751775

752776
All three supported players can accept a significant number of "*command line options*", which are well documented and accessible through man pages (on linux and MacOs) or the documentation (on Windows).

docs/pyradio.1

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,37 @@ Pressing "\fI\\m\fR" will bring up the "\fBSwitch Media Player\fR" window, where
837837
.IP \fBNote\fR
838838
The activated player will not be saved; **PyRadio** will still use the player defined at its config next time it is executed.
839839

840+
841+
842+
843+
844+
.SH Specifying a station's Referer URL
845+
846+
Although \fBpyradio\fR is meant to be a readio station player, it can also be used to listen to video stations transmitting m3u8 playlists (HTTP Live Streaming or HLS).
847+
848+
The thing with these transmissions is that usually a \fBReferer URL\fR has to be provided so that the connection does not fail.
849+
850+
\fBpyradio\fR now does support the declaration of a \fBReferer URL\fR for individual stations; it does it in an "anorthodox" way, but it is possible.
851+
852+
So, let us imagine that a station called "\fIMy video station\fR" has been added to a playlist. The user tries to play it but it fails; the referer URL is missing.
853+
854+
To rectify the situation, a file containing the referer URL would have to be saved in the config directory: its name must be the name of the station as it is in the playlist, followed by the "\fB.referer.txt\fR" extension.
855+
856+
In our example above, the file will have to be named:
857+
858+
.RS
859+
"\fIMy video station.referer.txt\fR"
860+
.RE
861+
862+
\fBA note of caution\fR
863+
.RS
864+
If such a file has been created for a station, please do not rename the station in the playlist manually; the "link" to the referer file will be lost.
865+
866+
Rename the station using \fBpyradio\fR rename functionality and save the playlist instead; the referer file will be renamed as well.
867+
.RE
868+
869+
870+
840871
.SH Extra Player Parameters
841872

842873
All three supported players can accept a significant number of "\fIcommand line parameters\fR", which are well documented and accessible through man pages (on linux and macOs) or the documentation (on Windows).

pyradio/client.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,19 +101,21 @@ def last_reply(self):
101101
return self._last_reply.split('<b>')[1][:-6]
102102
except IndexError:
103103
return 'Error retrieving title!'
104-
elif self._last_command in ('i', 'info') and \
105-
self._discovered:
106-
out = self._last_reply.splitlines()
107-
out.insert(1, ' Server: ' + self._host + ':' + self._port)
108-
self._last_reply = '\n'.join(out)
104+
elif self._last_command in ('i', 'info'):
105+
if self._discovered:
106+
out = self._last_reply.splitlines()
107+
out.insert(1, ' Server: ' + self._host + ':' + self._port)
108+
self._last_reply = '\n'.join(out) + '\n'
109+
if 'Title: ' in self._last_reply:
110+
self._last_reply = re.sub(r'Title: "([^"]*)"', r'Title: "[red3]\1[/red3]"', self._last_reply)
111+
self._last_reply = self._last_reply.replace(r'PyRadio', r'[magenta]PyRadio[/magenta]')
112+
self._last_reply = self._last_reply.replace(r'headless', r'[blue]headless[/blue]')
109113
if 'retry: ' in self._last_reply:
110114
self._last_reply = 'Command executed\n'
111115
return self._last_reply
112116
# empty reply
113117
if self._type == -1:
114118
return 'Command executed\n'
115-
else:
116-
return server_id + 'Command Executed\n'
117119

118120
def _get_files(self):
119121
if self._files is None:

pyradio/config.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ class PyRadioStations(object):
166166

167167
show_no_themes_message = True
168168

169+
renamed_stations = []
170+
169171
def __init__(self, stationFile='', user_config_dir=None):
170172
if platform.startswith('win'):
171173
self._open_string_id = 1
@@ -857,6 +859,25 @@ def save_playlist_file(self, stationFile=''):
857859
logger.debug('Cannot rename playlist file...')
858860
return -2
859861
self.dirty_playlist = False
862+
if self.renamed_stations:
863+
for n in self.renamed_stations:
864+
chk_referer_file = path.join(self.stations_dir, n[0] + '.referer.txt')
865+
if path.exists(chk_referer_file):
866+
new_referer_file = path.join(self.stations_dir, n[1] + '.referer.txt')
867+
try:
868+
rename(chk_referer_file, new_referer_file)
869+
if logger.isEnabledFor(logging.DEBUG):
870+
logger.debug('referer file renamed from "{}" to "{}"'.format(
871+
path.basename(chk_referer_file),
872+
path.basename(new_referer_file)
873+
))
874+
except:
875+
pass
876+
if logger.isEnabledFor(logging.DEBUG):
877+
logger.debug('failed to rename referer file from "{}" to "{}"'.format(
878+
path.basename(chk_referer_file),
879+
path.basename(new_referer_file)
880+
))
860881
return 0
861882

862883
def _format_playlist_row(self, a_row):

pyradio/player.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,7 +2022,7 @@ def play(self,
20222022
self._station_encoding = self.config_encoding
20232023
opts = []
20242024
isPlayList = streamUrl.split("?")[0][-3:] in ['m3u', 'pls']
2025-
opts, self.monitor_opts = self._buildStartOpts(streamUrl, isPlayList)
2025+
opts, self.monitor_opts = self._buildStartOpts(name, streamUrl, isPlayList)
20262026
self.stop_mpv_status_update_thread = False
20272027
if logger.isEnabledFor(logging.INFO):
20282028
try:
@@ -2282,7 +2282,7 @@ def _killall(self, name):
22822282
except:
22832283
pass
22842284

2285-
def _buildStartOpts(self, streamUrl, playList):
2285+
def _buildStartOpts(self, streamName, streamUrl, playList):
22862286
pass
22872287

22882288
def _write_silenced_profile(self):
@@ -2315,6 +2315,17 @@ def _write_silenced_profile(self):
23152315
if logger.isEnabledFor(logging.DEBUG):
23162316
logger.debug('Cannot wirte [silent] profile in: "{}"'.format(self.config_files[0]))
23172317

2318+
def _get_referer(self, streamName):
2319+
referer = None
2320+
ref = os.path.join(self._cnf.xdg.stations_dir, streamName + '.referer.txt')
2321+
if os.path.exists(ref):
2322+
try:
2323+
with open(ref, 'r', encoding='utf-8') as f:
2324+
referer = f.read().strip()
2325+
except:
2326+
pass
2327+
return referer
2328+
23182329
def togglePause(self):
23192330
if self.PLAYER_NAME == 'mpv':
23202331
self.paused = self._pause()
@@ -2493,7 +2504,7 @@ def save_volume(self):
24932504
self.volume = -2
24942505
return self._do_save_volume(self.profile_token + '\nvolume={}\n')
24952506

2496-
def _buildStartOpts(self, streamUrl, playList=False):
2507+
def _buildStartOpts(self, streamName, streamUrl, playList=False):
24972508
# logger.error('\n\nself._recording = {}'.format(self._recording))
24982509
# logger.error('self.profile_name = "{}"'.format(self.profile_name))
24992510
''' Builds the options to pass to mpv subprocess.'''
@@ -2553,11 +2564,9 @@ def _buildStartOpts(self, streamUrl, playList=False):
25532564
if logger.isEnabledFor(logging.DEBUG):
25542565
logger.debug('---=== Starting Recording: "{}" ===---',format(self.recording_filename))
25552566

2556-
# ##################################################################
2557-
# if streamUrl == r'https://player-culturaam.stream.uol.com.br/live/culturaam.m3u8' or \
2558-
# streamUrl == r'http://player-culturaam.stream.uol.com.br/live/culturaam.m3u8':
2559-
# opts.append(r'--http-header-fields="User-Agent: PyRadio,Referer: https://cultura.uol.com.br/aovivo/67_ao-vivo-radio-cultura-brasil.html"')
2560-
# ##################################################################
2567+
referer = self._get_referer(streamName)
2568+
if referer is not None:
2569+
opts.append(r'--http-header-fields="User-Agent: ' + self._cnf.user_agent_string + r',Referer:' + referer)
25612570

25622571
if playList:
25632572
if newerMpv:
@@ -2981,14 +2990,19 @@ def save_volume(self):
29812990
return 0
29822991
return self._do_save_volume(self.profile_token + '\nvolstep=1\nvolume={}\n')
29832992

2984-
def _buildStartOpts(self, streamUrl, playList=False):
2993+
def _buildStartOpts(self, streamName, streamUrl, playList=False):
29852994
''' Builds the options to pass to mplayer subprocess.'''
29862995
opts = [self.PLAYER_CMD, '-vo', 'null', '-msglevel', 'all=6']
29872996
if self._cnf.buffering_data:
29882997
opts.extend(self._cnf.buffering_data)
29892998
# opts = [self.PLAYER_CMD, '-vo', 'null']
29902999
monitor_opts = None
29913000

3001+
referer = self._get_referer(streamName)
3002+
if referer is not None:
3003+
opts.append(r'-http-header-fields')
3004+
opts.append(r'Referer: ' + referer)
3005+
29923006
''' Do I have user profile in config?
29933007
If so, can I use it?
29943008
'''
@@ -3322,7 +3336,7 @@ def set_volume(self, vol):
33223336
def save_volume(self):
33233337
return self._do_save_volume('{}')
33243338

3325-
def _buildStartOpts(self, streamUrl, playList=False):
3339+
def _buildStartOpts(self, streamName, streamUrl, playList=False):
33263340
''' Builds the options to pass to vlc subprocess.'''
33273341
#opts = [self.PLAYER_CMD, "-Irc", "--quiet", streamUrl]
33283342
monitor_opts = None
@@ -3384,6 +3398,13 @@ def _buildStartOpts(self, streamUrl, playList=False):
33843398
if self._cnf.buffering_data:
33853399
opts.extend(self._cnf.buffering_data)
33863400

3401+
referer = self._get_referer(streamName)
3402+
if referer is not None:
3403+
opts.append('--http-user-agent')
3404+
opts.append(self._cnf.user_agent_string)
3405+
opts.append(r'--http-referrer')
3406+
opts.append(referer)
3407+
33873408
''' this will set the profile too '''
33883409
if self.params[0] > 1:
33893410
params = self.params[self.params[0]]

pyradio/radio.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ def _text_info(self):
817817
# logger.error('self.log.song_title: {}'.format(self.log.song_title))
818818
# logger.error('============================')
819819
if self.stations[self.playing][0] not in self.log.song_title:
820-
out.append(' Title: {}'.format(fix_chars(self.log.song_title)))
820+
out.append(' Title: "{}"'.format(fix_chars(self.log.song_title)))
821821
else:
822822
out.append(' Status: Idle')
823823
out.append(' Selection (id={0}): "{1}"'.format(self.selection+1, self.stations[self.selection][0]))
@@ -3719,6 +3719,7 @@ def _open_playlist(self, a_url=None):
37193719
Parameters:
37203720
a_url: this should be an online service url
37213721
'''
3722+
self._cnf.renamed_stations = []
37223723
self._cnf.save_station_position(self.startPos, self.selection, self.playing)
37233724
self._set_active_stations()
37243725
self._update_status_bar_right()
@@ -7211,7 +7212,9 @@ def keypress(self, char):
72117212
self._station_editor.new_station[0]
72127213
)
72137214
self._cnf.dirty_playlist = True
7215+
self._cnf.renamed_stations.append([self.stations[self.selection][0], ''])
72147216
self.stations[self.selection] = self._station_editor.new_station
7217+
self._cnf.renamed_stations[-1][-1] = self.stations[self.selection][0]
72157218
if self.selection == self.playing:
72167219
self._last_played_station = self._station_editor.new_station
72177220
else:
@@ -8315,6 +8318,10 @@ def keypress(self, char):
83158318
self._update_status_bar_right()
83168319
icy_data_name = self.player.icy_data('icy-name')
83178320
if char == ord('r') and self.stations[self.playing][0] != icy_data_name:
8321+
self._cnf.renamed_stations.append([
8322+
self.stations[self.playing][0],
8323+
icy_data_name
8324+
])
83188325
self._cnf.stations_history.rename_station(
83198326
self._cnf.station_title,
83208327
self.stations[self.playing][0],

pyradio/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ def _handle_client_connection(self, address, request):
14111411
self._commands['/jump'](ret)
14121412
self._send_raw('<div class="alert alert-success">Playing <b>{}</b></div>'.format(self.lists()[0][-1][ret-1][0]))
14131413
else:
1414-
self._send_text(' Playing station: {}'.format(self.lists()[0][-1][ret-1][0]))
1414+
self._send_text(' Playing station: "{}"'.format(self.lists()[0][-1][ret-1][0]))
14151415
self._commands['/jump'](ret)
14161416
has_error = False
14171417
else:

pyradio/xdg.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ def _get_files(self):
120120
flag_files.extend([x[0] for x in self.files_to_state])
121121

122122
self.files_to_other = [[x, self._replace_dir_in_path(x, self.other_dir) ] for x in files_in_path if x not in flag_files]
123+
for n in range(len(self.files_to_other)-1, -1, -1):
124+
if self.files_to_other[0][0].endswith('.referer.txt'):
125+
self.files_to_other.pop(n)
123126

124127
def _get_max_length(self):
125128
to_print = []

0 commit comments

Comments
 (0)