Add TOML configuration and reorganize param names

This commit is contained in:
Max Goodhart
2020-06-30 17:11:41 -07:00
parent df81a7d4fe
commit cc79f387fd
5 changed files with 132 additions and 56 deletions

View File

@@ -29,6 +29,22 @@ Under the hood, think of Streamwall as a specialized web browser for mosaicing v
3. Use the browser window to load or control streams. The initial list will be populated from https://woke.net/#streams
4. If you enter the same stream code in multiple cells, it will merge them together for a larger stream.
## Configuration
Streamwall has a growing number of configuration options. To get a summary run:
```
npm start -- --help
```
For long-term installations, it's recommended to put your options into a configuration file. To use a config file, run:
```
npm start -- --config="../streamwall.json"
```
See `config.example.toml` for an example.
## Hotkeys
The following hotkeys are available with the "control" webpage focused:

32
example.config.toml Normal file
View File

@@ -0,0 +1,32 @@
# Set the background color (useful for chroma-keying)
#background-color = "#0f0"
[control]
# Address to serve control server from
address = "http://localhost:80"
# Override hostname and port
#hostname = "localhost"
#port = 80
# Username and password
password = "woke"
username = "woke"
[cert]
# SSL certificates (optional)
# If you specify an https:// URL for the "webserver" option, a certificate will be automatically generated and signed by Let's Encrypt.
# For this to work, Streamwall must be accessible from both ports 80 and 443.
# Uncomment to obtain a real certificate (otherwise a testing cert will be generated)
#production = true
# Email address to use when registering SSL certificate with Let's Encrypt
#email = "hi@streamwall.io"
# Directory to store certificate
#dir = "../streamwall-cert"
[streamdelay]
#endpoint = "http://localhost:8404"
#key = "super-secret"

5
package-lock.json generated
View File

@@ -1181,6 +1181,11 @@
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
"integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
},
"@iarna/toml": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
},
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",

View File

@@ -6,12 +6,13 @@
"scripts": {
"build": "webpack",
"start": "npm run build -- --display=errors-only && electron dist",
"start-local": "npm run build -- --display=errors-only && electron dist --webserver=http://localhost:4444 --username=woke --password=woke",
"start-local": "npm run build -- --display=errors-only && electron dist --control.address=http://localhost:4444 --control.username=woke --control.password=woke",
"test": "jest"
},
"author": "Max Goodhart <c@chromakode.com>",
"license": "MIT",
"dependencies": {
"@iarna/toml": "^2.2.5",
"ejs": "^3.1.3",
"electron": "^9.0.4",
"koa": "^2.12.1",

View File

@@ -1,5 +1,6 @@
import fs from 'fs'
import yargs from 'yargs'
import TOML from '@iarna/toml'
import { app, shell, session, BrowserWindow } from 'electron'
import { ensureValidURL } from '../util'
@@ -8,59 +9,80 @@ import StreamWindow from './StreamWindow'
import StreamdelayClient from './StreamdelayClient'
import initWebServer from './server'
async function main() {
const argv = yargs
function parseArgs() {
return yargs
.config('config', (configPath) => {
return JSON.parse(fs.readFileSync(configPath, 'utf-8'))
})
.group(
['webserver', 'cert-dir', 'cert-email', 'hostname', 'port'],
'Web Server Configuration',
)
.option('webserver', {
describe: 'Enable control webserver and specify the URL',
implies: ['username', 'password'],
})
.option('hostname', {
describe: 'Override hostname the control server listens on',
})
.option('port', {
describe: 'Override port the control server listens on',
number: true,
})
.option('cert-dir', {
describe: 'Private directory to store SSL certificate in',
implies: ['email'],
})
.option('cert-production', {
describe: 'Obtain a real SSL certificate using production servers',
})
.option('email', {
describe: 'Email for owner of SSL certificate',
})
.option('username', {
describe: 'Web control server username',
})
.option('password', {
describe: 'Web control server password',
})
.option('open', {
describe: 'After launching, open the control website in a browser',
boolean: true,
default: true,
return TOML.parse(fs.readFileSync(configPath, 'utf-8'))
})
.option('background-color', {
describe: 'Background color of wall (useful for chroma-keying)',
default: '#000',
})
.option('streamdelay-endpoint', {
.group(
[
'control.username',
'control.password',
'control.address',
'control.hostname',
'control.port',
'control.open',
],
'Control Webserver',
)
.option('control.username', {
describe: 'Web control server username',
})
.option('control.password', {
describe: 'Web control server password',
})
.option('control.open', {
describe: 'After launching, open the control website in a browser',
boolean: true,
default: true,
})
.option('control.address', {
describe: 'Enable control webserver and specify the URL',
implies: ['control.username', 'control.password'],
})
.option('control.hostname', {
describe: 'Override hostname the control server listens on',
})
.option('control.port', {
describe: 'Override port the control server listens on',
number: true,
})
.group(
['cert.dir', 'cert.production', 'cert.email'],
'Automatic SSL Certificate',
)
.option('cert.dir', {
describe: 'Private directory to store SSL certificate in',
implies: ['email'],
default: null,
})
.option('cert.production', {
describe: 'Obtain a real SSL certificate using production servers',
})
.option('cert.email', {
describe: 'Email for owner of SSL certificate',
})
.group(['streamdelay.endpoint', 'streamdelay.key'], 'Streamdelay')
.option('streamdelay.endpoint', {
describe: 'URL of Streamdelay endpoint',
default: 'http://localhost:8404',
})
.option('streamdelay-key', {
.option('streamdelay.key', {
describe: 'Streamdelay API key',
default: null,
})
.help().argv
}
async function main() {
const argv = parseArgs()
if (argv.help) {
return
}
// Reject all permission requests from web content.
session
@@ -132,28 +154,28 @@ async function main() {
}
}
if (argv.webserver) {
if (argv.control.address) {
;({ broadcastState } = await initWebServer({
certDir: argv.certDir,
certProduction: argv.certProduction,
email: argv.email,
url: argv.webserver,
hostname: argv.hostname,
port: argv.port,
username: argv.username,
password: argv.password,
certDir: argv.cert.dir,
certProduction: argv.cert.production,
email: argv.cert.email,
url: argv.control.address,
hostname: argv.control.hostname,
port: argv.control.port,
username: argv.control.username,
password: argv.control.password,
getInitialState,
onMessage,
}))
if (argv.open) {
shell.openExternal(argv.webserver)
if (argv.control.open) {
shell.openExternal(argv.control.address)
}
}
if (argv.streamdelayKey) {
if (argv.streamdelay.key) {
streamdelayClient = new StreamdelayClient({
endpoint: argv.streamdelayEndpoint,
key: argv.streamdelayKey,
endpoint: argv.streamdelay.endpoint,
key: argv.streamdelay.key,
})
streamdelayClient.on('state', (state) => {
clientState.streamdelay = state