From 333146a182223eb08b152671e54e82f458894157 Mon Sep 17 00:00:00 2001 From: rdl technix Date: Fri, 3 Sep 2021 19:08:48 +0200 Subject: [PATCH] remove baresip for now, use ices2 --- backend/bin.mjs | 6 ++-- backend/darkice.mjs | 4 +-- backend/ices2.mjs | 61 +++++++++++++++++++++++++++++++++++++++ backend/package.json | 6 +++- backend/server.mjs | 24 +++++++++++---- common/state.mjs | 7 +++-- frontend/src/app.jsx | 10 +++++-- frontend/src/css/app.scss | 10 ++++++- frontend/src/state.js | 1 - package.json | 14 +++++++-- 10 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 backend/ices2.mjs diff --git a/backend/bin.mjs b/backend/bin.mjs index 1289135..7ecbb63 100755 --- a/backend/bin.mjs +++ b/backend/bin.mjs @@ -12,13 +12,15 @@ async function main () { port: 3030, host: '0.0.0.0', input: 'alsa:default', - output: 'alsa:default' + output: 'alsa:default', + dev: false }, alias: { p: 'port', h: 'host', i: 'input', - o: 'output' + o: 'output', + d: 'dev' } }) diff --git a/backend/darkice.mjs b/backend/darkice.mjs index 2c93395..2df007a 100644 --- a/backend/darkice.mjs +++ b/backend/darkice.mjs @@ -11,8 +11,8 @@ import { action, STREAM_STATUS, LOG_MESSAGE } from './state.mjs' export class Darkice { constructor (opts = {}) { this.command = opts.command || 'darkice' - this.config = opts.config || p.join(__dirname, 'etc', '..', 'darkice.cfg') - this.logLevel = 5 + this.config = opts.config || p.join(__dirname, '..', 'etc', 'darkice.cfg') + this.logLevel = 8 this.stream = new Readable() this.log = [] this.stream.on('data', row => this.log.push(row)) diff --git a/backend/ices2.mjs b/backend/ices2.mjs new file mode 100644 index 0000000..7a0661e --- /dev/null +++ b/backend/ices2.mjs @@ -0,0 +1,61 @@ +import p from 'path' +import split2 from 'split2' +import { Readable } from 'streamx' +import { spawn } from 'child_process' +import { fileURLToPath } from 'url'; + +const __dirname = p.dirname(fileURLToPath(import.meta.url)) + +import { action, STREAM_STATUS, LOG_MESSAGE } from './state.mjs' + +export class Darkice { + constructor (opts = {}) { + this.command = opts.command || 'ices2' + this.config = opts.config || p.join(__dirname, '..', 'etc', 'ices2.xml') + this.logLevel = 8 + this.stream = new Readable() + this.log = [] + this.stream.on('data', row => this.log.push(row)) + this.id = 'darkice' + this.url = 'https://stream.rdl.de/rdl_ob1.ogg' + } + + restart () { + if (!this.process) return this.start() + this.process.once('close', () => { + process.nextTick(() => { + this.start() + }) + }) + this.stop() + } + + stop () { + this.process.kill() + } + + start () { + if (this.process) return + const args = [this.config] + this.process = spawn(this.command, args) + this.process.stdout.pipe(split2()).on('data', message => { + this.stream.push(action(LOG_MESSAGE, { id: this.id, type: 'stdout', message })) + // this.stream.push({ type: 'stdout', data }) + }) + this.process.stderr.pipe(split2()).on('data', message => { + this.stream.push(action(LOG_MESSAGE, { id: this.id, type: 'stdout', message })) + // this.stream.push({ type: 'stderr', data }) + }) + + this.process.on('close', () => { + this.stream.push(action(STREAM_STATUS, { id: this.id, status: 'stopped', url: this.url })) + this.process = null + }) + + this.stream.push(action(STREAM_STATUS, { id: this.id, status: 'started', url: this.url })) + + return new Promise((resolve, reject) => { + resolve() + }) + } +} diff --git a/backend/package.json b/backend/package.json index e3188b8..40b0f84 100644 --- a/backend/package.json +++ b/backend/package.json @@ -6,17 +6,21 @@ "license": "MIT", "bin": "bin.mjs", "scripts": { - "start": "node bin.mjs" + "start": "node bin.mjs", + "dev": "node bin.mjs --dev" }, "dependencies": { "baresip-wrapper": "^1.0.10", "debug": "^4.3.1", + "es-main": "^1.0.2", "fastify": "^3.15.1", "fastify-cors": "^6.0.1", + "fastify-http-proxy": "^6.2.0", "fastify-sse-v2": "^2.0.4", "fastify-static": "^4.0.1", "is-online": "^9.0.0", "minimist": "^1.2.5", + "node-jsonrpc-client": "^1.0.4", "split2": "^3.2.2", "streamx": "^2.10.3" }, diff --git a/backend/server.mjs b/backend/server.mjs index 90cc187..37e7f18 100644 --- a/backend/server.mjs +++ b/backend/server.mjs @@ -9,8 +9,10 @@ import { Transform, Readable } from 'streamx' import fastifyStatic from 'fastify-static' import fastifyCors from 'fastify-cors' import fastifySSE from 'fastify-sse-v2' +import fastifyProxy from 'fastify-http-proxy' -import { Darkice } from './darkice.mjs' +//import { Darkice } from './darkice.mjs' +import { Darkice } from './ices2.mjs' import { Baresip } from './baresip.mjs' import { AlsaMeter } from './lib/ffmpeg-meter.mjs' import { ConnectivityCheck } from './lib/is-online.mjs' @@ -26,7 +28,9 @@ function deviceToFFMPEG (device) { export async function run (config = {}) { const app = fastify() const darkice = new Darkice() - const baresip = new Baresip() + const baresip = new Baresip({ + destination: 901 + }) const isOnline = new ConnectivityCheck() const meter = new AlsaMeter({ @@ -57,10 +61,18 @@ export async function run (config = {}) { // const state = new StateContainer(reducer, INITIAL_STATE) // state.ingestActionStream(actions) - app.register(fastifyStatic, { - root: p.join(__dirname, '..', 'frontend', 'dist'), - prefix: '/' - }) + + if (config.dev) { + app.register(fastifyProxy, { + upstream: 'http://localhost:3000', + prefix: '/' + }) + } else { + app.register(fastifyStatic, { + root: p.join(__dirname, '..', 'frontend', 'dist'), + prefix: '/' + }) + } app.register(fastifyCors, { origin: '*' diff --git a/common/state.mjs b/common/state.mjs index 6aae066..084befb 100644 --- a/common/state.mjs +++ b/common/state.mjs @@ -17,7 +17,7 @@ export const INITIAL_STATE = { pings: 0, meter: {}, connectionState: { connected: false, error: null }, - connectivity: { internet: false } + connectivity: { internet: false }, } export function reducer (state, event) { @@ -32,14 +32,15 @@ export function reducer (state, event) { } } if (action === STREAM_STATUS) { - const { id, status } = data + const { id, status, url } = data return { ...state, streams: { ...(state.streams || {}), [id]: { ...state.streams[id], - status + status, + url } } } diff --git a/frontend/src/app.jsx b/frontend/src/app.jsx index 99ca391..38d2a68 100644 --- a/frontend/src/app.jsx +++ b/frontend/src/app.jsx @@ -14,7 +14,7 @@ function App () {
- + {/* */}
@@ -69,7 +69,9 @@ function Meters (props) { function StreamControl (props = {}) { const { id = 'darkice', state = {} } = props const command = useCommand() - const status = (state && state.streams && state.streams[id]) ? state.streams[id].status : 'stopped' + const stream = state && state.streams && state.streams[id] + const status = (stream && stream.status) || 'stopped' + const url = (stream && stream.url) || JSON.stringify(stream) const disabled = command.pending || status === 'unknown' let label switch (status) { @@ -84,6 +86,10 @@ function StreamControl (props = {}) { {label} +
+

Stream address

+ {url && {url}} +
) diff --git a/frontend/src/css/app.scss b/frontend/src/css/app.scss index 8cc06e4..a755549 100644 --- a/frontend/src/css/app.scss +++ b/frontend/src/css/app.scss @@ -50,7 +50,14 @@ .StreamControl { display: flex; flex-direction: column; - /* width: 200px; */ + //width: 250px; + width: 100%; + .StreamControl-url { + code { + font-weight: bold; + } + margin: 1rem 0; + } } .Meters { padding: 10px; @@ -94,6 +101,7 @@ .StatusBar { display: flex; + padding: 1rem; > * { display: block; margin-right: 1rem; diff --git a/frontend/src/state.js b/frontend/src/state.js index e8680de..18fcc42 100644 --- a/frontend/src/state.js +++ b/frontend/src/state.js @@ -66,7 +66,6 @@ export function useRemoteState (opts = {}) { dispatch(action) } eventSource.onerror = () => { - console.log('ONERROR!!') dispatch(action(CONNECTION_STATE, { error: `Failed to connect to backend` })) if (retryInterval) setTimeout(reconnect, retryInterval) } diff --git a/package.json b/package.json index 265016e..c79e02f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,18 @@ { "private": true, - "workspaces": ["backend", "frontend", "common"], + "workspaces": [ + "backend", + "frontend", + "common" + ], "scripts": { "build": "cd frontend && yarn build", - "start": "cd backend && yarn start" + "start": "cd backend && yarn start", + "dev": "concurrently npm:dev:*", + "dev:backend": "cd backend && yarn dev", + "dev:frontend": "cd frontend && yarn dev" + }, + "dependencies": { + "concurrently": "^6.2.1" } }