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