Fix schedule image reload, more config options
This commit is contained in:
parent
732ede8986
commit
a6a51a24a6
@ -4,8 +4,8 @@ const configFile = path.join(__dirname, '..', 'config.json')
|
||||
|
||||
const defvals = {
|
||||
api: {
|
||||
host: '0.0.0.0',
|
||||
port: 7005,
|
||||
host: '0.0.0.0',
|
||||
port: 7005,
|
||||
mount: '/api'
|
||||
},
|
||||
rtmp: {
|
||||
@ -19,14 +19,26 @@ const defvals = {
|
||||
},
|
||||
liquidsoap: {
|
||||
fallback: '',
|
||||
bitrate: 2000,
|
||||
entry: 'liq/view.liq'
|
||||
entry: 'liq/view.liq',
|
||||
output: {
|
||||
bitrate: 2000,
|
||||
width: 1280,
|
||||
height: 720,
|
||||
samplerate: 25
|
||||
}
|
||||
},
|
||||
calendar: {
|
||||
googleKey: '',
|
||||
calendar: '',
|
||||
interval: 60,
|
||||
timeFrame: 120000,
|
||||
schedule: {
|
||||
width: 300,
|
||||
height: 400,
|
||||
background: 'rgba(0,126,255,0.8)',
|
||||
font: 'sans-serif',
|
||||
fontColor: '#fff'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,10 +46,13 @@ function getKeys (obj, vals) {
|
||||
let keys = {}
|
||||
|
||||
for (let key in obj) {
|
||||
if (key === 'rtmp') {
|
||||
if (key === 'calendar') {
|
||||
keys['calendar.width'] = vals.calendar.schedule.width
|
||||
keys['calendar.height'] = vals.calendar.schedule.height
|
||||
} else if (key === 'rtmp') {
|
||||
keys['rtmp.url'] = 'rtmp://' + vals.rtmp.host + vals.rtmp.mount
|
||||
keys['rtmp.key'] = vals.rtmp.key
|
||||
} else if (typeof vals[key] == 'object') {
|
||||
} else if (typeof vals[key] === 'object') {
|
||||
let ks = getKeys(defvals[key], vals[key])
|
||||
for (let i in ks) {
|
||||
keys[key + '.' + i] = ks[i]
|
||||
|
@ -9,10 +9,15 @@ liq.start()
|
||||
|
||||
let scheduler = new Scheduler(config.calendar)
|
||||
scheduler.startTimers()
|
||||
|
||||
scheduler.runner = function (event) {
|
||||
liq.queue(event.descriptor)
|
||||
}
|
||||
|
||||
scheduler.reload = function (calendar) {
|
||||
liq.sendCommand('schedule.reload').catch((e) => console.error('Failed to reload schedule:', e.message))
|
||||
}
|
||||
|
||||
// User input handler
|
||||
rl.on('line', function (line) {
|
||||
let argv = line.split(' ')
|
||||
@ -46,6 +51,19 @@ rl.on('line', function (line) {
|
||||
console.log('Refreshing scheduler..')
|
||||
scheduler.calendarFetch().catch((e) => console.error('Calendar fetch failed!', e.stack))
|
||||
break
|
||||
case 'reload':
|
||||
console.log('Reloading configuration..')
|
||||
config.read().then(
|
||||
() => {
|
||||
console.log('Configuration reloaded successfully.')
|
||||
|
||||
// Restart scheduler
|
||||
scheduler.stopTimers()
|
||||
scheduler.startTimers()
|
||||
},
|
||||
(e) => console.error('Configuration reload failed:', e.stack)
|
||||
)
|
||||
break
|
||||
default:
|
||||
console.log('Unknown command.')
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class Liquidsoap {
|
||||
|
||||
queue (item) {
|
||||
if (typeof item !== 'object') item = [item]
|
||||
|
||||
|
||||
let q = []
|
||||
for (let i in item) {
|
||||
q.push('queue.push smart:' + item[i])
|
||||
|
@ -18,16 +18,19 @@ function dateFormat (date, yr) {
|
||||
}
|
||||
|
||||
class Drawer {
|
||||
constructor (w, h) {
|
||||
this.canvas = c.createCanvas(w, h)
|
||||
constructor () {
|
||||
this.canvas = c.createCanvas(config.calendar.schedule.width, config.calendar.schedule.height)
|
||||
this.ctx = this.canvas.getContext('2d')
|
||||
}
|
||||
|
||||
draw (cal) {
|
||||
async draw (cal) {
|
||||
let ctx = this.ctx
|
||||
let font = config.calendar.schedule.font
|
||||
let fontColor = config.calendar.schedule.fontColor
|
||||
|
||||
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
|
||||
|
||||
ctx.fillStyle = 'rgba(0,126,255,0.8)'
|
||||
ctx.fillStyle = config.calendar.schedule.background
|
||||
ctx.fillRect(5, 5, this.canvas.width - 10, this.canvas.height - 10)
|
||||
|
||||
let added = 0
|
||||
@ -38,7 +41,7 @@ class Drawer {
|
||||
if (i > 5) break // Can't fit so many on here :P
|
||||
if (ev.eventStartTime < Date.now() || ev.eventEndTime < Date.now()) continue
|
||||
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.fillStyle = fontColor
|
||||
let y = (i * 60) + 30
|
||||
|
||||
// Write event name
|
||||
@ -47,16 +50,16 @@ class Drawer {
|
||||
evn = evn.substring(0, 14) + '…'
|
||||
}
|
||||
|
||||
ctx.font = '26px sans-serif'
|
||||
ctx.font = '26px ' + font
|
||||
ctx.fillText(evn, 10, y)
|
||||
|
||||
// Write event description
|
||||
ctx.font = '16px sans-serif'
|
||||
ctx.font = '16px ' + font
|
||||
ctx.fillText(ev.description, 10, y + 20)
|
||||
|
||||
// Write event time
|
||||
let time = dateFormat(ev.eventStartTime)
|
||||
ctx.font = '26px sans-serif'
|
||||
ctx.font = '26px ' + font
|
||||
let tlen = ctx.measureText(time).width
|
||||
ctx.fillText(time, (this.canvas.width - 10) - tlen, y)
|
||||
|
||||
@ -70,12 +73,12 @@ class Drawer {
|
||||
}
|
||||
|
||||
if (added === 0) {
|
||||
ctx.fillStyle = '#fff'
|
||||
ctx.font = '26px sans-serif'
|
||||
ctx.fillStyle = fontColor
|
||||
ctx.font = '26px ' + font
|
||||
ctx.fillText('No events scheduled.', 10, 35)
|
||||
}
|
||||
|
||||
this.toFile()
|
||||
await this.toFile()
|
||||
}
|
||||
|
||||
toFile () {
|
||||
@ -96,17 +99,26 @@ class Calendar {
|
||||
|
||||
this.config = conf
|
||||
|
||||
this.drawer = new Drawer(300, 400)
|
||||
this.drawer = new Drawer()
|
||||
this.schedRunner = null
|
||||
this.schedReload = null
|
||||
|
||||
this.started = []
|
||||
this.timers = { a: null, b: null, c: null }
|
||||
}
|
||||
|
||||
update () {
|
||||
this.drawer.draw(this).then(() => {
|
||||
setTimeout(() => {
|
||||
this.schedReload && this.schedReload.call(this, this)
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
startTimers () {
|
||||
// Initial run
|
||||
this.calendarFetch().then(
|
||||
(e) => this.drawer.draw(this),
|
||||
(e) => this.update(),
|
||||
(e) => console.error('Calendar fetch failed!', e.stack)
|
||||
)
|
||||
|
||||
@ -114,7 +126,7 @@ class Calendar {
|
||||
this.timers = {
|
||||
a: setInterval(() => this.calendarFetch().catch((e) => console.error('Calendar fetch failed!', e.stack)), this.config.interval * 1000),
|
||||
b: setInterval(() => this.runners(), 60 * 1000),
|
||||
c: setInterval(() => this.drawer.draw(this), 120 * 1000)
|
||||
c: setInterval(() => this.update(), 120 * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,6 +210,10 @@ class Calendar {
|
||||
this.schedRunner = runner
|
||||
}
|
||||
|
||||
set reload (reload) {
|
||||
this.schedReload = reload
|
||||
}
|
||||
|
||||
runners () {
|
||||
if (!this.schedRunner) return
|
||||
for (let i in this.events) {
|
||||
|
11
liq/view.liq
11
liq/view.liq
@ -8,16 +8,17 @@ set("server.telnet", true)
|
||||
set("server.telnet.bind_addr", confstr("control.host", "0.0.0.0"))
|
||||
set("server.telnet.port", confint("control.port", 7004))
|
||||
|
||||
set("frame.video.width",1280)
|
||||
set("frame.video.height",720)
|
||||
set("frame.video.samplerate",25)
|
||||
set("frame.video.width",confint("liquidsoap.output.width", 1280))
|
||||
set("frame.video.height",confint("liquidsoap.output.height", 720))
|
||||
set("frame.video.samplerate",confint("liquidsoap.output.samplerate", 25))
|
||||
|
||||
video_no_queue = single(confstr("liquidsoap.fallback",""), conservative=true)
|
||||
video_base = video.add_image(
|
||||
width=300,height=400,
|
||||
width=confint("calendar.width", 300),height=confint("calendar.height", 400),
|
||||
x=900,y=80,
|
||||
file="schedule.png",
|
||||
video_no_queue)
|
||||
add_skip_command(command="schedule.reload", video_base)
|
||||
|
||||
queue1 = request.equeue(id="queue", conservative=true, length=60., timeout=1000.)
|
||||
add_skip_command(command="queue.skip", queue1)
|
||||
@ -30,5 +31,5 @@ source = on_end(delay=0., file_end_cleanup, source)
|
||||
output.rtmp.live(
|
||||
key=confstr("rtmp.key",""),
|
||||
url=confstr("rtmp.url","rtmp://localhost/live"),
|
||||
video_bitrate=confint("liquidsoap.bitrate", 2000),
|
||||
video_bitrate=confint("liquidsoap.output.bitrate", 2000),
|
||||
source)
|
||||
|
Loading…
Reference in New Issue
Block a user