From Python to shell script
- Allowing to run mpd + icecast2 + fip relay with metadatas on a VM with 128Mo of memory. - Calculating when to update (given the end field in the JSON)
This commit is contained in:
parent
d35735cf65
commit
bcafd50a3d
5 changed files with 52 additions and 213 deletions
24
README.txt
24
README.txt
|
|
@ -1,13 +1,14 @@
|
|||
Usage :
|
||||
-------
|
||||
|
||||
./fip_current.py [-c CONFIG.ini] [-u]
|
||||
Edit the script to change the value of :
|
||||
host -> icecast2 host & port
|
||||
mount -> mountpoint name
|
||||
login -> icecast2 login
|
||||
passwd -> icecast2 password
|
||||
|
||||
#Show current song metadata
|
||||
./fip_current.py
|
||||
|
||||
#Update icecast2 metadata
|
||||
./fip_current.py -c CONFIG.ini -u
|
||||
Then run :
|
||||
./fip_current.sh
|
||||
|
||||
Instances :
|
||||
-----------
|
||||
|
|
@ -19,8 +20,9 @@ Requierments :
|
|||
--------------
|
||||
|
||||
icecast2
|
||||
python3
|
||||
python3-requests
|
||||
jq
|
||||
curl
|
||||
sed
|
||||
|
||||
Icecast2 configuration sample :
|
||||
-------------------------------
|
||||
|
|
@ -32,9 +34,3 @@ Icecast2 configuration sample :
|
|||
<local-mount>/fip-metadata.mp3</local-mount>
|
||||
<relay-shoutcast-metadata>0</relay-shoutcast-metadata>
|
||||
</relay>
|
||||
|
||||
Crontab :
|
||||
---------
|
||||
|
||||
#Update every minute
|
||||
* * * * * /path/fip_current.py -uc /path/conf.ini
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
[conf]
|
||||
debug=false
|
||||
loop-delay=15
|
||||
host=127.0.0.1:8000
|
||||
mount=/fip.mp3
|
||||
login=admin
|
||||
password=hackme
|
||||
185
fip_current.py
185
fip_current.py
|
|
@ -1,185 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
#
|
||||
# Copyright 2016 Yann Weber
|
||||
#
|
||||
# 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 3 of the License, or
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
import configparser
|
||||
from argparse import ArgumentParser
|
||||
|
||||
API_URL = 'http://www.fipradio.fr/livemeta/7'
|
||||
DEBUG = False
|
||||
|
||||
|
||||
def main():
|
||||
""" Parse arguments and run wanted function """
|
||||
parser = ArgumentParser(description="Fetch FIP radio stream metadata")
|
||||
parser.add_argument(
|
||||
'-u', '--icecast-update',
|
||||
dest='update',
|
||||
action='store_const',
|
||||
const=True,
|
||||
default=False,
|
||||
help="Run Icecast2 metadata update")
|
||||
parser.add_argument(
|
||||
'-c', '--config',
|
||||
dest='conf',
|
||||
type=str,
|
||||
default='conf.ini',
|
||||
help="Configuration file")
|
||||
parser.add_argument(
|
||||
'-l', '--loop',
|
||||
dest='loop',
|
||||
action='store_const',
|
||||
const=True,
|
||||
default=False,
|
||||
help="Combined with -u enables loop update")
|
||||
"""
|
||||
parser.add_argument(
|
||||
'-d', '--loop-delay',
|
||||
dest='delay',
|
||||
type=int,
|
||||
default=15,
|
||||
help="Loop delay in seconds")
|
||||
"""
|
||||
args = parser.parse_args()
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read(args.conf)
|
||||
debug = conf.get('conf', 'debug', fallback="False").lower() == 'true'
|
||||
globals()['DEBUG'] = debug
|
||||
if args.update:
|
||||
host = conf.get('conf', 'host', fallback='127.0.0.1:8000')
|
||||
mount = conf.get('conf', 'mount', fallback='/example.ogg')
|
||||
login = conf.get('conf', 'login', fallback='admin')
|
||||
password = conf.get('conf', 'password', fallback='hackme')
|
||||
if args.loop:
|
||||
delay = conf.get('conf', 'loop-delay', fallback='15')
|
||||
try:
|
||||
delay = int(delay)
|
||||
except ValueError:
|
||||
msg = "loop-delay expected to be an integer '%s' found"
|
||||
raise ValueError( msg % delay)
|
||||
prev = None
|
||||
while True:
|
||||
try:
|
||||
if globals()['DEBUG']:
|
||||
print("Update start");
|
||||
prev = icecast_update(host, mount, login, password, prev)
|
||||
if globals()['DEBUG']:
|
||||
print("Updated");
|
||||
time.sleep(delay)
|
||||
except Exception as e:
|
||||
prev = None
|
||||
print(str(e), file=sys.stderr)
|
||||
|
||||
else:
|
||||
icecast_update(host, mount, login, password)
|
||||
else:
|
||||
print(format_current())
|
||||
|
||||
|
||||
def get_all():
|
||||
""" Return a dict containing all FIP API metadatas """
|
||||
res = requests.get(API_URL)
|
||||
if res.status_code != 200:
|
||||
msg = "Got status code %d for %s"
|
||||
msg %= (res.status_code, API_URL)
|
||||
raise RuntimeError(msg)
|
||||
return res.json()
|
||||
|
||||
|
||||
def get_current():
|
||||
""" Return a dict containing currently playing song metadatas """
|
||||
datas = get_all()
|
||||
if len(datas['levels'])==2:
|
||||
level = 1
|
||||
else:
|
||||
level = 0
|
||||
position = datas['levels'][level]['position']
|
||||
item_id = datas['levels'][level]['items'][position]
|
||||
item = datas['steps'][item_id]
|
||||
expt = ['authors', 'title', 'titreAlbum', 'visual', 'lienYoutube']
|
||||
for k in expt:
|
||||
if k not in item:
|
||||
item[k] = ''
|
||||
|
||||
return item
|
||||
|
||||
|
||||
def format_current():
|
||||
""" Return a string representing formated current playing song
|
||||
metadatas """
|
||||
item = get_current()
|
||||
infos = """Title :\t\t{title}
|
||||
Authors :\t{author}
|
||||
Album :\t\t{album}
|
||||
Visual :\t{image}
|
||||
Youtube :\t{youtube}
|
||||
"""
|
||||
res = infos.format(
|
||||
title=item['title'].title(),
|
||||
author=item['authors'].title(),
|
||||
album=item['titreAlbum'].title(),
|
||||
image=item['visual'],
|
||||
youtube=item['lienYoutube'])
|
||||
if globals()['DEBUG']:
|
||||
res = "[debug mode]\n"+res
|
||||
return res
|
||||
|
||||
|
||||
def icecast_infos():
|
||||
""" Return formated Icecast2 metadatas from FIP current song
|
||||
metadatas """
|
||||
item = get_current()
|
||||
infos = item['title'].title()
|
||||
if len(item['authors']) > 0:
|
||||
infos += ' - '+item['authors'].title()
|
||||
if len(item['titreAlbum']):
|
||||
infos += ' ('+item['titreAlbum'].title()+')'
|
||||
if globals()['DEBUG']:
|
||||
infos = infos + str(time.time())
|
||||
return infos
|
||||
|
||||
|
||||
def icecast_update(host, mount, login=None, password=None, prev = None):
|
||||
""" Update metadatas to an Icecast2 mount """
|
||||
infos = icecast_infos()
|
||||
url = "http://{host}/admin/metadata"
|
||||
url = url.format(host=host)
|
||||
params = {
|
||||
'mount': mount,
|
||||
'mode': 'updinfo',
|
||||
'song': infos}
|
||||
auth = None
|
||||
if login is not None and password is not None:
|
||||
auth = (login, password)
|
||||
|
||||
if infos != prev:
|
||||
try:
|
||||
res = requests.get(url, auth=auth, params=params)
|
||||
except requests.exceptions.ConnectionError:
|
||||
raise RuntimeError("Connection refuse for "+res.url)
|
||||
|
||||
if res.status_code != 200:
|
||||
msg = "Got status code %d for %s"
|
||||
msg %= (res.status_code, res.url)
|
||||
raise RuntimeError(msg)
|
||||
|
||||
return infos
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
38
fip_current.sh
Executable file
38
fip_current.sh
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/sh
|
||||
host="ICECAST2_HOST:PORT"
|
||||
mount="/MOUNTPOINT"
|
||||
login="admin"
|
||||
passwd="hackme"
|
||||
|
||||
|
||||
|
||||
fip_url="https://www.fip.fr/livemeta/7"
|
||||
fipmeta="/tmp/fip-meta"
|
||||
start=$(date "+%s")
|
||||
touch $fipmeta
|
||||
while [ 1 ]
|
||||
do
|
||||
q='.["steps"][.["levels"][0]["items"][.["levels"][0]["position"]]] |.["end"], .["title"]+" - "+.["authors"]+" ("+.["titreAlbum"]+")"'
|
||||
infos=$(curl -s $fip_url | jq -r "$q" )
|
||||
title=$(echo $infos |cut -d" " -f"2-"| sed 's/[^ ]\+/\L\u&/g')
|
||||
end=$(echo $infos |cut -d" " -f1)
|
||||
|
||||
if [ "$(cat $fipmeta)" != "$title" ]
|
||||
then
|
||||
echo -n $title > $fipmeta
|
||||
echo $title
|
||||
curl -s -G "http://${login}:${passwd}@${host}/admin/metadata" \
|
||||
-d "mount=${mount}"
|
||||
-d "mode=updinfo"
|
||||
--data-urlencode "song=${title}" > /dev/null
|
||||
fi
|
||||
|
||||
now=$(date "+%s")
|
||||
if [ "$now" -gt "$end" ]
|
||||
then
|
||||
sleep 1
|
||||
else
|
||||
delay=$(expr $end - $now)
|
||||
sleep $delay
|
||||
fi
|
||||
done
|
||||
11
init_script
11
init_script
|
|
@ -9,14 +9,11 @@
|
|||
# Description: Start updating Icecast2 metadatas using FIP radio wep API
|
||||
### END INIT INFO
|
||||
|
||||
DPATH=/PUT/SCRIPT/PATH/HERE
|
||||
DPATH="PATH TO SCRIPT"
|
||||
|
||||
SCRIPT="fip_current.py"
|
||||
DAEMON="${DPATH}/${SCRIPT}"
|
||||
CONFIG="${DPATH}/conf.ini"
|
||||
DAEMON="${DPATH}/fip_current.sh"
|
||||
NAME="fip-current"
|
||||
DESC="fip-current update script"
|
||||
DAEMON_OPTS="-ul -c $CONFIG"
|
||||
PIDFILE="/run/fip-current.pid"
|
||||
|
||||
set_path()
|
||||
|
|
@ -38,14 +35,14 @@ case $1 in
|
|||
echo -n " allready running"
|
||||
log_end_msg 1
|
||||
else
|
||||
start-stop-daemon --quiet --start --background -m -p $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
|
||||
start-stop-daemon --quiet --start --background -m -p $PIDFILE --exec $DAEMON
|
||||
log_end_msg $?
|
||||
fi
|
||||
|
||||
;;
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC"
|
||||
start-stop-daemon --stop -p $PIDFILE --remove-pidfile -x $DAEMON
|
||||
start-stop-daemon --stop -p $PIDFILE --remove-pidfile
|
||||
log_end_msg $?
|
||||
;;
|
||||
restart)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue