Skip to content

Commit

Permalink
refactor: roll handover (#451)
Browse files Browse the repository at this point in the history
* style: tweak active colour

* refactor: create shared playback validation

* feat: allow handover from and to roll
  • Loading branch information
cpvalente authored Jul 15, 2023
1 parent 91a2d39 commit b89d078
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { IoPlaySkipBack } from '@react-icons/all-files/io5/IoPlaySkipBack';
import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward';
import { IoReload } from '@react-icons/all-files/io5/IoReload';
import { IoStop } from '@react-icons/all-files/io5/IoStop';
import { IoTime} from '@react-icons/all-files/io5/IoTime';
import { IoTime } from '@react-icons/all-files/io5/IoTime';
import { Playback } from 'ontime-types';
import { validatePlayback } from 'ontime-utils';

import { setPlayback } from '../../../../common/hooks/useSocket';
import { tooltipDelayMid } from '../../../../ontimeConfig';
Expand Down Expand Up @@ -34,7 +35,13 @@ export default function PlaybackButtons(props: PlaybackButtonsProps) {
const noEvents = numEvents === 0;

const disableGo = isRolling || noEvents || (isLast && !isArmed);
const disablePrev = isRolling || noEvents || isFirst;
const disablePrev = noEvents || isFirst;

const playbackCan = validatePlayback(playback);
const disableStart = !playbackCan.start;
const disablePause = !playbackCan.pause;
const disableRoll = !playbackCan.roll || noEvents;
const disableStop = !playbackCan.stop;

const goModeText = selectedEventIndex === null || isArmed ? 'Start' : 'Next';
const goModeAction = () => {
Expand All @@ -51,21 +58,11 @@ export default function PlaybackButtons(props: PlaybackButtonsProps) {
{goModeText}
</TapButton>
<div className={style.playbackContainer}>
<TapButton
onClick={setPlayback.start}
disabled={isStopped || isRolling}
theme={Playback.Play}
active={isPlaying}
>
<TapButton onClick={setPlayback.start} disabled={disableStart} theme={Playback.Play} active={isPlaying}>
<IoPlay />
</TapButton>

<TapButton
onClick={setPlayback.pause}
disabled={isStopped || isRolling || isArmed}
theme={Playback.Pause}
active={isPaused}
>
<TapButton onClick={setPlayback.pause} disabled={disablePause} theme={Playback.Pause} active={isPaused}>
<IoPause />
</TapButton>
</div>
Expand All @@ -82,21 +79,16 @@ export default function PlaybackButtons(props: PlaybackButtonsProps) {
</Tooltip>
</div>
<div className={style.extra}>
<TapButton
onClick={setPlayback.roll}
disabled={!isStopped || noEvents}
theme={Playback.Roll}
active={isRolling}
>
<TapButton onClick={setPlayback.roll} disabled={disableRoll} theme={Playback.Roll} active={isRolling}>
<IoTime />
</TapButton>
<Tooltip label='Reload event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.reload} disabled={isStopped || isRolling}>
<TapButton onClick={setPlayback.reload} disabled={isStopped}>
<IoReload className={style.invertX} />
</TapButton>
</Tooltip>
<Tooltip label='Unload Event' openDelay={tooltipDelayMid}>
<TapButton onClick={setPlayback.stop} disabled={isStopped && !isRolling} theme={Playback.Stop}>
<TapButton onClick={setPlayback.stop} disabled={disableStop} theme={Playback.Stop}>
<IoStop />
</TapButton>
</Tooltip>
Expand Down
2 changes: 1 addition & 1 deletion apps/client/src/theme/_v2Styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ $ontime-delay-text: #E69056;
$ontime-paused: #c05621;
$ontime-stop: #E4281E;
$playback-negative: $red-500;
$active-indicator: #899948;
$active-indicator: #8bb33d;
$text-black: $gray-1350;

// interface panels
Expand Down
9 changes: 5 additions & 4 deletions apps/server/src/services/PlaybackService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { OntimeEvent, Playback } from 'ontime-types';
import { OntimeEvent } from 'ontime-types';
import { validatePlayback } from 'ontime-utils';

import { eventLoader, EventLoader } from '../classes/event-loader/EventLoader.js';
import { eventStore } from '../stores/EventStore.js';
Expand Down Expand Up @@ -133,7 +134,7 @@ export class PlaybackService {
* Starts playback on selected event
*/
static start() {
if (eventTimer.playback === Playback.Armed || eventTimer.playback === Playback.Pause) {
if (validatePlayback(eventTimer.playback).start) {
eventTimer.start();
const newState = eventTimer.playback;
logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`);
Expand All @@ -155,7 +156,7 @@ export class PlaybackService {
* Pauses playback on selected event
*/
static pause() {
if (eventTimer.playback === Playback.Play) {
if (validatePlayback(eventTimer.playback).pause) {
eventTimer.pause();
const newState = eventTimer.playback;
logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`);
Expand All @@ -166,7 +167,7 @@ export class PlaybackService {
* Stops timer and unloads any events
*/
static stop() {
if (eventTimer.playback !== Playback.Stop) {
if (validatePlayback(eventTimer.playback).stop) {
eventLoader.reset();
eventTimer.stop();
const newState = eventTimer.playback;
Expand Down
32 changes: 22 additions & 10 deletions apps/server/src/services/TimerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import { DAY_TO_MS } from '../utils/time.js';
import { integrationService } from './integration-service/IntegrationService.js';
import { getCurrent, getElapsed, getExpectedFinish } from './timerUtils.js';
import { clock } from './Clock.js';
import { logger } from '../classes/Logger.js';

type initialLoadingData = {
startedAt?: number | null;
expectedFinish?: number | null;
current?: number | null;
};

export class TimerService {
private readonly _interval: NodeJS.Timer;
Expand Down Expand Up @@ -113,7 +120,7 @@ export class TimerService {
* @param {string} timer.timerType
* @param {boolean} timer.skip
*/
load(timer) {
load(timer, initialData?: initialLoadingData) {
if (timer.skip) {
throw new Error('Refuse load of skipped event');
}
Expand All @@ -129,6 +136,10 @@ export class TimerService {
this.pausedTime = 0;
this.pausedAt = 0;

if (typeof initialData !== 'undefined') {
this.timer = { ...this.timer, ...initialData };
}

this._onLoad();
}

Expand All @@ -146,6 +157,9 @@ export class TimerService {

start() {
if (!this.loadedTimerId) {
if (this.playback === Playback.Roll) {
logger.error('PLAYBACK', 'Cannot start while waiting for event');
}
return;
}

Expand All @@ -155,12 +169,12 @@ export class TimerService {

this.timer.clock = clock.timeNow();

// add paused time
// add paused time if it exists
if (this.pausedTime) {
this.timer.addedTime += this.pausedTime;
this.pausedAt = null;
this.pausedTime = 0;
} else {
} else if (this.timer.startedAt === null) {
this.timer.startedAt = this.timer.clock;
}

Expand Down Expand Up @@ -188,10 +202,6 @@ export class TimerService {
}

pause() {
if (this.playback !== Playback.Play) {
return;
}

this.playback = Playback.Pause;
this.timer.clock = clock.timeNow();
this.pausedAt = this.timer.clock;
Expand Down Expand Up @@ -370,9 +380,11 @@ export class TimerService {

// when we load a timer in roll, we do the same things as before
// but also pre-populate some data as to the running state
this.load(currentEvent);
this.timer.startedAt = currentEvent.timeStart;
this.timer.expectedFinish = currentEvent.timeEnd;
this.load(currentEvent, {
startedAt: currentEvent.timeStart,
expectedFinish: currentEvent.timeEnd,
current: currentEvent.timeEnd - this.timer.clock,
});
} else if (nextEvent) {
// account for day after
const nextStart = nextEvent.timeStart < this.timer.clock ? nextEvent.timeStart + DAY_TO_MS : nextEvent.timeStart;
Expand Down
1 change: 1 addition & 0 deletions packages/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { formatFromMillis } from './src/date-utils/formatFromMillis.js';
export { isTimeString } from './src/date-utils/isTimeString.js';
export { millisToString } from './src/date-utils/millisToString.js';
export { generateId } from './src/generate-id/generateId.js';
export { validatePlayback } from './src/validate-action/validatePlayback.js';
1 change: 1 addition & 0 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^8.0.0",
"ontime-types": "workspace:*",
"prettier": "^2.8.3",
"typescript": "^4.9.4",
"vitest": "^0.30.1"
Expand Down
10 changes: 10 additions & 0 deletions packages/utils/src/validate-action/validatePlayback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Playback } from 'ontime-types';

export function validatePlayback(currentPlayback: Playback) {
return {
start: currentPlayback !== Playback.Stop,
pause: currentPlayback === Playback.Play || currentPlayback === Playback.Roll,
roll: true,
stop: currentPlayback !== Playback.Stop,
};
}
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b89d078

Please sign in to comment.