mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 15:39:11 +00:00
refactor: allow aux change direction while playing
This commit is contained in:
committed by
Carlos Valente
parent
9a6ca7ac67
commit
16fd44a441
@@ -230,8 +230,9 @@ const actionHandlers: Record<string, ActionHandler> = {
|
|||||||
} else if (command && typeof command === 'object') {
|
} else if (command && typeof command === 'object') {
|
||||||
const reply = { payload: {} };
|
const reply = { payload: {} };
|
||||||
if ('duration' in command) {
|
if ('duration' in command) {
|
||||||
const time = numberOrError(command.duration);
|
// convert duration in seconds to ms
|
||||||
reply.payload = auxTimerService.setTime(time * 1000); //frontend is seconds based
|
const timeInMs = numberOrError(command.duration) * 1000;
|
||||||
|
reply.payload = auxTimerService.setTime(timeInMs);
|
||||||
}
|
}
|
||||||
if ('direction' in command) {
|
if ('direction' in command) {
|
||||||
if (command.direction === SimpleDirection.CountUp || command.direction === SimpleDirection.CountDown) {
|
if (command.direction === SimpleDirection.CountUp || command.direction === SimpleDirection.CountDown) {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import { initialiseProject } from './services/project-service/ProjectService.js'
|
|||||||
import { clearUploadfolder } from './utils/upload.js';
|
import { clearUploadfolder } from './utils/upload.js';
|
||||||
import { generateCrashReport } from './utils/generateCrashReport.js';
|
import { generateCrashReport } from './utils/generateCrashReport.js';
|
||||||
import { getNetworkInterfaces } from './utils/networkInterfaces.js';
|
import { getNetworkInterfaces } from './utils/networkInterfaces.js';
|
||||||
|
import { timerConfig } from './config/config.js';
|
||||||
|
|
||||||
console.log('\n');
|
console.log('\n');
|
||||||
consoleHighlight(`Starting Ontime version ${ONTIME_VERSION}`);
|
consoleHighlight(`Starting Ontime version ${ONTIME_VERSION}`);
|
||||||
@@ -187,8 +188,8 @@ export const startServer = async (
|
|||||||
eventNext: state.eventNext,
|
eventNext: state.eventNext,
|
||||||
publicEventNext: state.publicEventNext,
|
publicEventNext: state.publicEventNext,
|
||||||
auxtimer1: {
|
auxtimer1: {
|
||||||
duration: 0,
|
duration: timerConfig.auxTimerDefault,
|
||||||
current: 0,
|
current: timerConfig.auxTimerDefault,
|
||||||
playback: SimplePlayback.Stop,
|
playback: SimplePlayback.Stop,
|
||||||
direction: SimpleDirection.CountDown,
|
direction: SimpleDirection.CountDown,
|
||||||
},
|
},
|
||||||
@@ -198,7 +199,7 @@ export const startServer = async (
|
|||||||
// initialise logging service, escalateErrorFn is only exists in electron
|
// initialise logging service, escalateErrorFn is only exists in electron
|
||||||
logger.init(escalateErrorFn);
|
logger.init(escalateErrorFn);
|
||||||
|
|
||||||
// initialise rundown service
|
// initialise rundown service
|
||||||
const persistedRundown = getDataProvider().getRundown();
|
const persistedRundown = getDataProvider().getRundown();
|
||||||
const persistedCustomFields = getDataProvider().getCustomFields();
|
const persistedCustomFields = getDataProvider().getCustomFields();
|
||||||
initRundown(persistedRundown, persistedCustomFields);
|
initRundown(persistedRundown, persistedCustomFields);
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ export class SimpleTimer {
|
|||||||
};
|
};
|
||||||
private startedAt: number | null = null;
|
private startedAt: number | null = null;
|
||||||
private pausedAt: number | null = null;
|
private pausedAt: number | null = null;
|
||||||
|
private initialDuration = 0;
|
||||||
|
|
||||||
|
constructor(initialTime: number = 0) {
|
||||||
|
this.state.duration = initialTime;
|
||||||
|
this.initialDuration = initialTime;
|
||||||
|
this.state.current = initialTime;
|
||||||
|
}
|
||||||
|
|
||||||
public reset() {
|
public reset() {
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -25,14 +32,19 @@ export class SimpleTimer {
|
|||||||
*/
|
*/
|
||||||
public setTime(time: number): SimpleTimerState {
|
public setTime(time: number): SimpleTimerState {
|
||||||
this.state.duration = time;
|
this.state.duration = time;
|
||||||
|
this.initialDuration = time;
|
||||||
this.state.current = time;
|
this.state.current = time;
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setDirection(direction: SimpleDirection): SimpleTimerState {
|
public setDirection(direction: SimpleDirection, timeNow: number): SimpleTimerState {
|
||||||
this.state.playback = SimplePlayback.Stop;
|
// if we are playing, we need to reset the targets
|
||||||
this.state.current = this.state.duration;
|
if (this.state.playback === SimplePlayback.Start) {
|
||||||
|
this.startedAt = timeNow;
|
||||||
|
this.state.duration = this.state.current;
|
||||||
|
}
|
||||||
this.state.direction = direction;
|
this.state.direction = direction;
|
||||||
|
this.update(timeNow);
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +69,8 @@ export class SimpleTimer {
|
|||||||
|
|
||||||
public stop(): SimpleTimerState {
|
public stop(): SimpleTimerState {
|
||||||
this.state.playback = SimplePlayback.Stop;
|
this.state.playback = SimplePlayback.Stop;
|
||||||
this.state.current = this.state.duration;
|
this.state.duration = this.initialDuration;
|
||||||
|
this.state.current = this.initialDuration;
|
||||||
this.startedAt = null;
|
this.startedAt = null;
|
||||||
return this.state;
|
return this.state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ describe('SimpleTimer count-down', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('count-up mode', () => {
|
test('count-up mode', () => {
|
||||||
const initialState = timer.setDirection(SimpleDirection.CountUp);
|
const initialState = timer.setDirection(SimpleDirection.CountUp, 0);
|
||||||
expect(initialState.current).toBe(initialTime);
|
expect(initialState.current).toBe(initialTime);
|
||||||
|
|
||||||
let newState = timer.start(0);
|
let newState = timer.start(0);
|
||||||
@@ -114,16 +114,68 @@ describe('SimpleTimer count-down', () => {
|
|||||||
expect(newState).toStrictEqual(expected);
|
expect(newState).toStrictEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('changing direction stops the timer', () => {
|
test('changing direction keeps the current time', () => {
|
||||||
const newState = timer.setDirection(SimpleDirection.CountDown);
|
timer.reset();
|
||||||
const expected: SimpleTimerState = {
|
timer.setTime(1000);
|
||||||
duration: initialTime,
|
|
||||||
current: initialTime,
|
|
||||||
direction: SimpleDirection.CountDown,
|
|
||||||
playback: SimplePlayback.Stop,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(newState).toStrictEqual(expected);
|
const initialState = timer.setDirection(SimpleDirection.CountUp, 0);
|
||||||
|
expect(initialState.current).toBe(1000);
|
||||||
|
|
||||||
|
let newState = timer.start(0);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1000,
|
||||||
|
current: 1000,
|
||||||
|
direction: SimpleDirection.CountUp,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.update(100);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1000,
|
||||||
|
current: initialTime + 100,
|
||||||
|
direction: SimpleDirection.CountUp,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.update(500);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1000,
|
||||||
|
current: 1500,
|
||||||
|
direction: SimpleDirection.CountUp,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.setDirection(SimpleDirection.CountDown, 600);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1500,
|
||||||
|
current: 1500,
|
||||||
|
direction: SimpleDirection.CountDown,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.update(700);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1500,
|
||||||
|
current: 1400,
|
||||||
|
direction: SimpleDirection.CountDown,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.setDirection(SimpleDirection.CountUp, 700);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1400,
|
||||||
|
current: 1400,
|
||||||
|
direction: SimpleDirection.CountUp,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
|
|
||||||
|
newState = timer.update(800);
|
||||||
|
expect(newState).toStrictEqual({
|
||||||
|
duration: 1400,
|
||||||
|
current: 1500,
|
||||||
|
direction: SimpleDirection.CountUp,
|
||||||
|
playback: SimplePlayback.Start,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
import { MILLIS_PER_MINUTE } from 'ontime-utils';
|
||||||
|
|
||||||
export const timerConfig = {
|
export const timerConfig = {
|
||||||
skipLimit: 1000, // threshold of skip for recalculating
|
skipLimit: 1000, // threshold of skip for recalculating
|
||||||
updateRate: 32, // how often do we update the timer
|
updateRate: 32, // how often do we update the timer
|
||||||
notificationRate: 1000, // how often do we notify clients and integrations
|
notificationRate: 1000, // how often do we notify clients and integrations
|
||||||
triggerAhead: 10, // how far ahead do we trigger the end event
|
triggerAhead: 10, // how far ahead do we trigger the end event
|
||||||
|
auxTimerDefault: 5 * MILLIS_PER_MINUTE, // default aux timer duration
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { SimpleDirection, SimpleTimerState } from 'ontime-types';
|
|||||||
|
|
||||||
import { SimpleTimer } from '../../classes/simple-timer/SimpleTimer.js';
|
import { SimpleTimer } from '../../classes/simple-timer/SimpleTimer.js';
|
||||||
import { eventStore } from '../../stores/EventStore.js';
|
import { eventStore } from '../../stores/EventStore.js';
|
||||||
|
import { timerConfig } from '../../config/config.js';
|
||||||
|
|
||||||
export type EmitFn = (state: SimpleTimerState) => void;
|
export type EmitFn = (state: SimpleTimerState) => void;
|
||||||
export type GetTimeFn = () => number;
|
export type GetTimeFn = () => number;
|
||||||
@@ -13,7 +14,7 @@ export class AuxTimerService {
|
|||||||
private getTime: GetTimeFn;
|
private getTime: GetTimeFn;
|
||||||
|
|
||||||
constructor(emit: EmitFn, getTime: GetTimeFn) {
|
constructor(emit: EmitFn, getTime: GetTimeFn) {
|
||||||
this.timer = new SimpleTimer();
|
this.timer = new SimpleTimer(timerConfig.auxTimerDefault);
|
||||||
this.emit = emit;
|
this.emit = emit;
|
||||||
this.getTime = getTime;
|
this.getTime = getTime;
|
||||||
}
|
}
|
||||||
@@ -30,7 +31,7 @@ export class AuxTimerService {
|
|||||||
|
|
||||||
@broadcastReturn
|
@broadcastReturn
|
||||||
setDirection(direction: SimpleDirection) {
|
setDirection(direction: SimpleDirection) {
|
||||||
return this.timer.setDirection(direction);
|
return this.timer.setDirection(direction, this.getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
@broadcastReturn
|
@broadcastReturn
|
||||||
|
|||||||
Reference in New Issue
Block a user