implemented / fixed start, resume, pause and stop functionality
This commit is contained in:
parent
7dc3fb6ece
commit
ac1fca8368
3 changed files with 55 additions and 24 deletions
|
@ -40,17 +40,19 @@ class Api {
|
|||
}
|
||||
global.audioserver = new AudioServer('/home/velvettear/mounts/kingston/public/test.pcm');
|
||||
});
|
||||
this.#registerEndpoint(constants.API_RESUME, constants.REQUEST_METHOD_POST, async () => {
|
||||
if (global.audioserver === undefined) {
|
||||
return;
|
||||
}
|
||||
await global.audioserver.destroy();
|
||||
global.audioserver = new AudioServer('/home/velvettear/mounts/kingston/public/test.pcm', global.audioserver.progress);
|
||||
});
|
||||
this.#registerEndpoint(constants.API_PAUSE, constants.REQUEST_METHOD_POST, async () => {
|
||||
if (global.audioserver === undefined) {
|
||||
return;
|
||||
}
|
||||
global.audioserver.pausePlayback();
|
||||
});
|
||||
this.#registerEndpoint(constants.API_RESUME, constants.REQUEST_METHOD_POST, async () => {
|
||||
if (global.audioserver === undefined) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.#registerEndpoint(constants.API_STOP, constants.REQUEST_METHOD_POST, async () => {
|
||||
if (global.audioserver === undefined) {
|
||||
return;
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
const sleep = require('../libs/util.js').sleep;
|
||||
|
||||
const net = require('net');
|
||||
const fs = require('fs');
|
||||
const stat = require('fs/promises').stat;
|
||||
const { stat, open } = require('fs/promises');
|
||||
|
||||
const Message = require('./Message.js');
|
||||
const constants = require('../libs/constants.js');
|
||||
|
||||
class AudioServer {
|
||||
|
||||
constructor(file) {
|
||||
constructor(file, progress) {
|
||||
this.listen = config?.server?.listen || '0.0.0.0';
|
||||
this.port = 0;
|
||||
this.buffer = {
|
||||
file: file,
|
||||
stream: fs.createReadStream(file)
|
||||
file: file
|
||||
};
|
||||
this.clients = [];
|
||||
this.sockets = [];
|
||||
this.broadcasts = {};
|
||||
this.progress = 0;
|
||||
this.progress = progress || 0;
|
||||
this.server = net.createServer();
|
||||
this.#prepare();
|
||||
}
|
||||
|
@ -41,17 +38,35 @@ class AudioServer {
|
|||
});
|
||||
this.server.on('error', (err) => {
|
||||
logger.error('ERROR IN AUDIOSERVER ' + err);
|
||||
reject('an error occured preparing the audio server for file \'' + this.file + '\' > ' + err);
|
||||
reject('audio server encountered an error: ' + err);
|
||||
});
|
||||
this.server.on('close', () => {
|
||||
logger.info('audio server closed');
|
||||
});
|
||||
});
|
||||
await this.#prepareBuffer();
|
||||
this.#announceAudioServer();
|
||||
}
|
||||
|
||||
async #prepareBuffer() {
|
||||
if (this.buffer.fd !== undefined) {
|
||||
this.buffer.fd.close();
|
||||
}
|
||||
if (this.buffer.stream?.destroyed === false) {
|
||||
this.buffer.stream.close();
|
||||
this.buffer.stream.destroy();
|
||||
}
|
||||
this.buffer.fd = await open(this.buffer.file);
|
||||
this.buffer.stream = this.buffer.fd.createReadStream({
|
||||
start: this.progress
|
||||
});
|
||||
const stats = await stat(this.buffer.file);
|
||||
this.buffer.size = stats.size;
|
||||
this.buffer.size = stats.size - this.progress;
|
||||
let percentage = 30;
|
||||
if (!(isNaN(config.audio?.threshold))) {
|
||||
percentage = config.audio.threshold;
|
||||
}
|
||||
this.buffer.threshold = (this.buffer.size / 100) * percentage;
|
||||
this.#announceAudioServer();
|
||||
}
|
||||
|
||||
#handleEvents() {
|
||||
|
@ -145,6 +160,9 @@ class AudioServer {
|
|||
if (client === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this.progress < data?.progress) {
|
||||
this.progress = data.progress;
|
||||
}
|
||||
switch (client.state) {
|
||||
case constants.CLIENT_STATE_REGISTERED:
|
||||
return this.#handleStateRegistered(client);
|
||||
|
@ -174,7 +192,7 @@ class AudioServer {
|
|||
if (!this.#allClientsInState(constants.CLIENT_STATE_READY)) {
|
||||
return;
|
||||
}
|
||||
this.#startPlayback();
|
||||
this.startPlayback();
|
||||
}
|
||||
|
||||
async #handleStatePlaying(client) {
|
||||
|
@ -196,6 +214,10 @@ class AudioServer {
|
|||
|
||||
async #handleStateStopped(client, data) {
|
||||
logger.debug(client.getTag() + ' stopped playback, progress: ' + data.progress + '/' + this.buffer.size + '...');
|
||||
if (!this.#allClientsInState(constants.CLIENT_STATE_STOPPED)) {
|
||||
return;
|
||||
}
|
||||
this.destroy();
|
||||
}
|
||||
|
||||
async #handleStateError(client, data) {
|
||||
|
@ -232,7 +254,7 @@ class AudioServer {
|
|||
logger.debug('sent broadcast for audio server to client(s) \'' + this.broadcasts[constants.CLIENT_STATE_REGISTERED] + '\'...');
|
||||
}
|
||||
|
||||
async #startPlayback() {
|
||||
async startPlayback() {
|
||||
this.broadcasts[constants.CLIENT_STATE_PLAYING] = await new Message('audio:play').broadcast();
|
||||
logger.debug('sent broadcast to start playback to client(s) \'' + this.broadcasts[constants.CLIENT_STATE_PLAYING] + '\'...');
|
||||
}
|
||||
|
@ -289,16 +311,22 @@ class AudioServer {
|
|||
}
|
||||
audiosocket.destroy();
|
||||
}
|
||||
this.buffer.fd.close();
|
||||
this.buffer.stream.close();
|
||||
this.buffer.stream.destroy();
|
||||
if (this.server?.listening !== true) {
|
||||
return;
|
||||
}
|
||||
await new Promise((resolve, reject) => {
|
||||
this.server.close((err) => {
|
||||
if (err !== undefined) {
|
||||
logger.error('ERROR CLOSING AUDIOSERVER ' + err);
|
||||
reject(err);
|
||||
this.server.close((error) => {
|
||||
if (error !== undefined) {
|
||||
logger.error('an error occured closing the audio server: ' + error);
|
||||
// TODO: reject and try/catch later?
|
||||
// reject(error);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ module.exports = {
|
|||
CLIENT_STATE_READY: 'ready',
|
||||
CLIENT_STATE_PLAYING: 'playing',
|
||||
CLIENT_STATE_PAUSED: 'paused',
|
||||
CLIENT_STATE_RESUMING: 'resuming',
|
||||
CLIENT_STATE_STOPPED: 'stopped',
|
||||
CLIENT_STATE_ERROR: 'error',
|
||||
|
||||
|
|
Loading…
Reference in a new issue