Parent: [14ca5b] (diff)

Download this file

radio-paradise-get-flac.py    155 lines (132 with data), 5.1 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/python3
# Checked to run with either Python 2 or 3
#
# Copyright (C) 2017-2018 J.F.Dockes
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Handling the Flac channel from radio-paradise. This is made of
# 'blocks' which are multi-title periods with a single audio
# url. Metadata should be displayed according to the elapsed time in
# the audio (each metadata entry in the array gives the start and
# duration for the song in mS). If metadata is re-fetched during the
# block, it is front-truncated, more or less according to the current
# time, and it may happen that the metadata for the song playing
# locally is not there any more (someone starting at this point would
# begin with the next point). The thing which does not change for
# successive fetches of the same block is the "end_event" value. We
# cache the first fetch for any block so that we are sure to have the
# right metadata available when upmpdcli calls us
from __future__ import print_function
import requests
import json
import sys
import os
PY3 = sys.version > '3'
tmpname = '/tmp/up-rp-pldata.json'
def debug(x):
print("radio-paradise-get-flac.py: %s" % x, file=sys.stderr)
pass
# Write new block data to cache. We always output the audio url in this case.
def newcache(jsd):
global out
s = json.dumps(jsd,sort_keys=True, indent=4)
open(tmpname, 'wb').write(s.encode('utf-8'))
os.chmod(tmpname, 0o666)
out["audioUrl"] = jsd['url'] + "?src=alexa"
def makebytes(data):
if type(data) == type(u''):
return data.encode("UTF-8", errors='replace')
return data
##### Main script
# We're expecting args as successive pairs of "name value", and we
# need elapsedms (elapsed milliseconds in current track)
# (e.g. myscript elapsedms 134)
if (len(sys.argv)+1) % 2:
debug("argv len not odd")
sys.exit(1)
args = {}
for i in range(len(sys.argv)-2):
nm = sys.argv[i+1]
val = sys.argv[i+2]
args[nm] = val
elapsedms = -1
try:
elapsedms = int(args["elapsedms"])
except:
pass
debug("rp-get-flac: got elapsed %d" % elapsedms)
# Try to read the current cached data.
cached = None
try:
s = open(tmpname, 'rb').read().decode('utf-8', errors = 'replace')
cached = json.loads(s)
except Exception as err:
debug("No cached data read: %s" % err)
pass
r = requests.get("https://api.radioparadise.com/api/get_block",
params={"bitrate": "4", "info":"true"})
r.raise_for_status()
newjsd = r.json()
out = {}
# If we are currently playing, check if our cached data is still
# relevant. If it is, it is more complete than the new data which is
# front-truncated, so we use it, so that we can check if we are still
# playing a track which might not be in the new list. Also if we go to
# a new block, we output the audio URL
if cached:
debug("Cached end_event %s new %s"%(cached['end_event'], newjsd['end_event']))
if elapsedms >= 0 and cached and 'end_event' in cached and \
cached['end_event'] == newjsd['end_event']:
debug("rp-get-flac: using cached data")
jsd = cached
else:
debug("outputting audio url because using new metadata or not playing")
jsd = newjsd
elapsedms = -1
newcache(jsd)
currentk = None
if elapsedms > 0:
songs = jsd['song']
for k in sorted(songs.keys()):
startms = songs[k]['elapsed']
endms = startms + songs[k]['duration']
debug("k %s Startms %d endms %d" % (k, startms, endms))
if elapsedms >= startms and elapsedms <= endms:
currentk = k
break
if not currentk:
# Not found ?? Try to reset the thing
debug(("outputting audio url because current elapsed %d " + \
" not found in song array") % elapsedms)
jsd = newjsd
newcache(jsd)
out['reload'] = 3
else:
songs = jsd['song']
out['title'] = songs[currentk]['title']
out['artist'] = songs[currentk]['artist']
out['album'] = songs[currentk]['album']
out['artUrl'] = 'http:%s%s' % (jsd['image_base'],
songs[currentk]['cover'])
reload = int((endms - elapsedms)/1000)
# Last song: reload a bit earlier so that we can queue the URL
if currentk == len(songs) -1 and reload > 3:
reload -= 2
out['reload'] = reload
if PY3:
sys.stdout.buffer.write(makebytes(json.dumps(out)))
else:
print("%s" % makebytes(json.dumps(out)))