-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
148 lines (127 loc) · 6 KB
/
main.py
File metadata and controls
148 lines (127 loc) · 6 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
import json
from flask import Flask
from flask import render_template
from flask import request
from config import config_utils
from config import station_list_reader
from audio_player import audio_mpd
# TODO : Add logging and send stacktrace of any exceptions to the log, something like this:
# traceback.print_exc()
# We want to keep as much state as possible on the client side, but a radio is a device that
# is either on or off and it can only play one station at a time, so some state has to live
# on the server. These variables hold the state:
# now_playing may contain:
# None = power off
# An ID from the station list = the ID for the live stream that's playing
# On-demand TBC
now_playing = None
# initialise Flask
app = Flask(__name__)
# top level application variables
err_msgs = list ()
info_msgs = dict ()
# initialise configuration
program_config = config_utils.ConfigLocationFinder()
info_msgs["Configuration file"] = program_config.general_config_path
info_msgs["Station list file"] = program_config.station_list_path
info_msgs["Log folder"] = program_config.log_folder
info_msgs["PID folder"] = program_config.pid_folder
info_msgs["MPD player host"] = program_config.config['mpd_host']
info_msgs["MPD player port"] = program_config.config['mpd_port']
if program_config.err is not None:
err_msgs += [program_config.err]
# load list of stations
stations = station_list_reader.StationListReader(program_config.station_list_path)
if len (stations.err) > 0:
err_msgs += stations.err
# initialise audio player
audio_player = audio_mpd.AudioPlayer(program_config.config['mpd_host'],
program_config.config['mpd_port'])
#######################################################################################################################
# Base page for the applications - this is a single page application with sections:
# - An error message component - only displayed if there are errors initialising the app
# - Standby / Region / On-demand station selection pane
# - Live radio selection / On demand schedule selection
# - Play bar - with 'now playing' information
# The final two component parts of the page can be loaded separately into the base page
#######################################################################################################################
# The base page
@app.route('/')
def base_page() -> str:
return render_template('base.html',
error_messages = err_msgs,
info_msgs = info_msgs)
#######################################################################################################################
# component parts of the base page
#######################################################################################################################
# The station/schedule component
@app.route("/component/station_schedule")
def station_schedule() -> str:
operation = request.args.get ('operation')
if operation is None:
operation = ""
if operation == 'live':
zone = request.args.get ('zone')
return render_template('live_station_list.html', stations=stations.get_station_list(zone))
if operation == 'on_demand':
return render_template('schedule_viewer.html')
if operation == 'blank':
return ""
return "/component/schedule: Unrecognised operation [" + operation + "]"
# The play bar component
@app.route('/component/play_bar')
def play_bar() -> str:
operation = request.args.get ('operation')
if operation is None:
operation = ""
if operation == 'stop':
audio_player.stop()
return ""
if operation == 'live_station':
station_id = request.args.get ('station_id')
station = stations.find_station(station_id)
if station is None:
return "/component/play_bar: Missing or invalid 'station_id' parameter"
errmsg = audio_player.play(station['streaming_url'])
if len(errmsg) > 0:
return "Error with audio: " + errmsg
return render_template('playbar_live.html', station=station, volume=audio_player.volume)
return "/component/play_bar: Unrecognised operation [" + operation + "]"
#######################################################################################################################
# audio operations
#######################################################################################################################
@app.route("/audio")
def audio () -> str:
errmsg = ""
# process volume change request
param = request.args.get ('volume')
if param is not None:
try:
volume = int (float (param))
if volume < 0 or volume > 100:
raise ValueError
except ValueError:
return "/audio: bad volume value: [" + param + "]"
errmsg += audio_player.set_volume(volume)
# process pause request
param = request.args.get ('pause')
if param is not None:
try:
pause = int (float (param))
if pause < 0 or pause > 1:
raise ValueError
except ValueError:
return "/audio: bad pause value: [" + param + "]"
errmsg += audio_player.pause(pause)
return errmsg
#######################################################################################################################
# odds and ends
#######################################################################################################################
# we need to process the javascript for the project using a template, so that data can
# be passed from server to client
@app.route("/scripts/radio_player.js")
def process_script () -> str:
return render_template('radio_player.js',
national_stations = stations.get_station_list(station_list_reader.ZONE_NATIONAL),
regional_stations = stations.get_station_list(station_list_reader.ZONE_REGIONAL),
local_stations = stations.get_station_list(station_list_reader.ZONE_LOCAL))