Fading and keyboard shortcuts
This commit is contained in:
parent
7b8da70aea
commit
4151b753f5
6 changed files with 523 additions and 338 deletions
|
@ -5,6 +5,7 @@
|
|||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^1.0.4",
|
||||
"@types/jest": "24.0.22",
|
||||
"@types/keymaster": "^1.6.28",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/node": "12.12.7",
|
||||
"@types/qs": "^6.9.0",
|
||||
|
@ -14,6 +15,7 @@
|
|||
"@types/react-redux": "^7.1.5",
|
||||
"@types/webpack-env": "^1.14.1",
|
||||
"between.js": "^0.1.2-fix.2",
|
||||
"keymaster": "^1.6.2",
|
||||
"lodash": "^4.17.15",
|
||||
"qs": "^6.9.1",
|
||||
"react": "^0.0.0-experimental-38dd17ab9",
|
||||
|
|
628
src/lib/between.d.ts
vendored
628
src/lib/between.d.ts
vendored
|
@ -2,374 +2,376 @@
|
|||
// Declare your modules properly, people!
|
||||
|
||||
declare module "between.js" {
|
||||
/**
|
||||
* Loop mode
|
||||
*/
|
||||
export type LoopMode = "repeat" | "bounce";
|
||||
export type EventEmmit = "start" | "update" | "complete";
|
||||
|
||||
/**
|
||||
* A collection of easing methods defining ease-in ease-out curves.
|
||||
*/
|
||||
export interface Easing extends Function {
|
||||
declare namespace Between {
|
||||
/**
|
||||
* Linear easing.
|
||||
*
|
||||
* @class Easing.Linear
|
||||
* Loop mode
|
||||
*/
|
||||
Linear: {
|
||||
/**
|
||||
* Ease-in.
|
||||
*
|
||||
* @method Easing.Linear#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k^2.
|
||||
*/
|
||||
None: Function;
|
||||
};
|
||||
export type LoopMode = "repeat" | "bounce";
|
||||
export type EventEmmit = "start" | "update" | "complete";
|
||||
|
||||
/**
|
||||
* Quadratic easing.
|
||||
*
|
||||
* @class Easing.Quadratic
|
||||
* A collection of easing methods defining ease-in ease-out curves.
|
||||
*/
|
||||
Quadratic: {
|
||||
export interface Easing extends Function {
|
||||
/**
|
||||
* Ease-in.
|
||||
* Linear easing.
|
||||
*
|
||||
* @method Easing.Quadratic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k^2.
|
||||
* @class Easing.Linear
|
||||
*/
|
||||
In: Function;
|
||||
Linear: {
|
||||
/**
|
||||
* Ease-in.
|
||||
*
|
||||
* @method Easing.Linear#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k^2.
|
||||
*/
|
||||
None: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ease-out.
|
||||
* Quadratic easing.
|
||||
*
|
||||
* @method Easing.Quadratic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k* (2-k).
|
||||
* @class Easing.Quadratic
|
||||
*/
|
||||
Out: Function;
|
||||
Quadratic: {
|
||||
/**
|
||||
* Ease-in.
|
||||
*
|
||||
* @method Easing.Quadratic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k^2.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Ease-out.
|
||||
*
|
||||
* @method Easing.Quadratic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} k* (2-k).
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Ease-in/out.
|
||||
*
|
||||
* @method Easing.Quadratic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ease-in/out.
|
||||
* Cubic easing.
|
||||
*
|
||||
* @method Easing.Quadratic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Cubic
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
Cubic: {
|
||||
/**
|
||||
* Cubic ease-in.
|
||||
*
|
||||
* @method Easing.Cubic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Cubic easing.
|
||||
*
|
||||
* @class Easing.Cubic
|
||||
*/
|
||||
Cubic: {
|
||||
/**
|
||||
* Cubic ease-in.
|
||||
*
|
||||
* @method Easing.Cubic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
/**
|
||||
* Cubic ease-out.
|
||||
*
|
||||
* @method Easing.Cubic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Cubic ease-in/out.
|
||||
*
|
||||
* @method Easing.Cubic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cubic ease-out.
|
||||
* Quartic easing.
|
||||
*
|
||||
* @method Easing.Cubic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Quartic
|
||||
*/
|
||||
Out: Function;
|
||||
Quartic: {
|
||||
/**
|
||||
* Quartic ease-in.
|
||||
*
|
||||
* @method Easing.Quartic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Quartic ease-out.
|
||||
*
|
||||
* @method Easing.Quartic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Quartic ease-in/out.
|
||||
*
|
||||
* @method Easing.Quartic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cubic ease-in/out.
|
||||
* Quintic easing.
|
||||
*
|
||||
* @method Easing.Cubic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Quintic
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
Quintic: {
|
||||
/**
|
||||
* Quintic ease-in.
|
||||
*
|
||||
* @method Easing.Quintic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Quartic easing.
|
||||
*
|
||||
* @class Easing.Quartic
|
||||
*/
|
||||
Quartic: {
|
||||
/**
|
||||
* Quartic ease-in.
|
||||
*
|
||||
* @method Easing.Quartic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
/**
|
||||
* Quintic ease-out.
|
||||
*
|
||||
* @method Easing.Quintic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Quintic ease-in/out.
|
||||
*
|
||||
* @method Easing.Quintic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quartic ease-out.
|
||||
* Sinusoidal easing.
|
||||
*
|
||||
* @method Easing.Quartic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Sinusoidal
|
||||
*/
|
||||
Out: Function;
|
||||
Sinusoidal: {
|
||||
/**
|
||||
* Sinusoidal ease-in.
|
||||
*
|
||||
* @method Easing.Sinusoidal#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Sinusoidal ease-out.
|
||||
*
|
||||
* @method Easing.Sinusoidal#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Sinusoidal ease-in/out.
|
||||
*
|
||||
* @method Easing.Sinusoidal#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quartic ease-in/out.
|
||||
* Exponential easing.
|
||||
*
|
||||
* @method Easing.Quartic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Exponential
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
Exponential: {
|
||||
/**
|
||||
* Exponential ease-in.
|
||||
*
|
||||
* @method Easing.Exponential#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Quintic easing.
|
||||
*
|
||||
* @class Easing.Quintic
|
||||
*/
|
||||
Quintic: {
|
||||
/**
|
||||
* Quintic ease-in.
|
||||
*
|
||||
* @method Easing.Quintic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
/**
|
||||
* Exponential ease-out.
|
||||
*
|
||||
* @method Easing.Exponential#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Exponential ease-in/out.
|
||||
*
|
||||
* @method Easing.Exponential#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quintic ease-out.
|
||||
* Circular easing.
|
||||
*
|
||||
* @method Easing.Quintic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Circular
|
||||
*/
|
||||
Out: Function;
|
||||
Circular: {
|
||||
/**
|
||||
* Circular ease-in.
|
||||
*
|
||||
* @method Easing.Circular#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Circular ease-out.
|
||||
*
|
||||
* @method Easing.Circular#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Circular ease-in/out.
|
||||
*
|
||||
* @method Easing.Circular#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quintic ease-in/out.
|
||||
* Elastic easing.
|
||||
*
|
||||
* @method Easing.Quintic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Elastic
|
||||
*/
|
||||
InOut: Number;
|
||||
};
|
||||
Elastic: {
|
||||
/**
|
||||
* Elastic ease-in.
|
||||
*
|
||||
* @method Easing.Elastic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Sinusoidal easing.
|
||||
*
|
||||
* @class Easing.Sinusoidal
|
||||
*/
|
||||
Sinusoidal: {
|
||||
/**
|
||||
* Sinusoidal ease-in.
|
||||
*
|
||||
* @method Easing.Sinusoidal#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
/**
|
||||
* Elastic ease-out.
|
||||
*
|
||||
* @method Easing.Elastic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Elastic ease-in/out.
|
||||
*
|
||||
* @method Easing.Elastic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sinusoidal ease-out.
|
||||
* Back easing.
|
||||
*
|
||||
* @method Easing.Sinusoidal#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Back
|
||||
*/
|
||||
Out: Function;
|
||||
Back: {
|
||||
/**
|
||||
* Back ease-in.
|
||||
*
|
||||
* @method Easing.Back#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Back ease-out.
|
||||
*
|
||||
* @method Easing.Back#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Back ease-in/out.
|
||||
*
|
||||
* @method Easing.Back#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sinusoidal ease-in/out.
|
||||
* Bounce easing.
|
||||
*
|
||||
* @method Easing.Sinusoidal#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
* @class Easing.Bounce
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
Bounce: {
|
||||
/**
|
||||
* Bounce ease-in.
|
||||
*
|
||||
* @method Easing.Bounce#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Exponential easing.
|
||||
*
|
||||
* @class Easing.Exponential
|
||||
*/
|
||||
Exponential: {
|
||||
/**
|
||||
* Exponential ease-in.
|
||||
*
|
||||
* @method Easing.Exponential#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
/**
|
||||
* Bounce ease-out.
|
||||
*
|
||||
* @method Easing.Bounce#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Exponential ease-out.
|
||||
*
|
||||
* @method Easing.Exponential#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Exponential ease-in/out.
|
||||
*
|
||||
* @method Easing.Exponential#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Circular easing.
|
||||
*
|
||||
* @class Easing.Circular
|
||||
*/
|
||||
Circular: {
|
||||
/**
|
||||
* Circular ease-in.
|
||||
*
|
||||
* @method Easing.Circular#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Circular ease-out.
|
||||
*
|
||||
* @method Easing.Circular#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Circular ease-in/out.
|
||||
*
|
||||
* @method Easing.Circular#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Elastic easing.
|
||||
*
|
||||
* @class Easing.Elastic
|
||||
*/
|
||||
Elastic: {
|
||||
/**
|
||||
* Elastic ease-in.
|
||||
*
|
||||
* @method Easing.Elastic#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Elastic ease-out.
|
||||
*
|
||||
* @method Easing.Elastic#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Elastic ease-in/out.
|
||||
*
|
||||
* @method Easing.Elastic#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Back easing.
|
||||
*
|
||||
* @class Easing.Back
|
||||
*/
|
||||
Back: {
|
||||
/**
|
||||
* Back ease-in.
|
||||
*
|
||||
* @method Easing.Back#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Back ease-out.
|
||||
*
|
||||
* @method Easing.Back#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Back ease-in/out.
|
||||
*
|
||||
* @method Easing.Back#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bounce easing.
|
||||
*
|
||||
* @class Easing.Bounce
|
||||
*/
|
||||
Bounce: {
|
||||
/**
|
||||
* Bounce ease-in.
|
||||
*
|
||||
* @method Easing.Bounce#In
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
In: Function;
|
||||
|
||||
/**
|
||||
* Bounce ease-out.
|
||||
*
|
||||
* @method Easing.Bounce#Out
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
Out: Function;
|
||||
|
||||
/**
|
||||
* Bounce ease-in/out.
|
||||
*
|
||||
* @method Easing.Bounce#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
/**
|
||||
* Bounce ease-in/out.
|
||||
*
|
||||
* @method Easing.Bounce#InOut
|
||||
* @param {number} k - The value to be tweened.
|
||||
* @returns {number} The tweened value.
|
||||
*/
|
||||
InOut: Function;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Between {
|
||||
declare class Between {
|
||||
/**
|
||||
* Creates a new Between instance
|
||||
* @param from start
|
||||
|
@ -421,4 +423,6 @@ declare module "between.js" {
|
|||
*/
|
||||
isPaused: boolean;
|
||||
}
|
||||
|
||||
export = Between;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import * as Between from "between.js";
|
||||
import {
|
||||
createSlice,
|
||||
PayloadAction,
|
||||
Store,
|
||||
Dispatch,
|
||||
Action,
|
||||
Middleware
|
||||
} from "@reduxjs/toolkit";
|
||||
import Between from "between.js";
|
||||
import { PlanItem } from "../showplanner/state";
|
||||
import Keys from "keymaster";
|
||||
import { Track, MYRADIO_NON_API_BASE } from "../api";
|
||||
import { AppThunk } from "../store";
|
||||
import { RootState } from "../rootReducer";
|
||||
|
||||
console.log(Between);
|
||||
|
||||
const audioContext = new AudioContext();
|
||||
const playerSources: MediaElementAudioSourceNode[] = [];
|
||||
const playerGains: GainNode[] = [];
|
||||
const playerGainTweens: Between.Between[] = [];
|
||||
const playerGainTweens: Array<{
|
||||
target: VolumePresetEnum;
|
||||
tweens: Between[];
|
||||
}> = [];
|
||||
// TODO
|
||||
// const destination = audioContext.createWebcastSource(4096, 2);
|
||||
const destination = audioContext.createDynamicsCompressor();
|
||||
|
@ -23,6 +35,7 @@ interface PlayerState {
|
|||
loading: boolean;
|
||||
state: PlayerStateEnum;
|
||||
volume: number;
|
||||
gain: number;
|
||||
}
|
||||
|
||||
interface MixerState {
|
||||
|
@ -37,19 +50,22 @@ const mixerState = createSlice({
|
|||
loadedItem: null,
|
||||
loading: false,
|
||||
state: "stopped",
|
||||
volume: 1
|
||||
volume: 1,
|
||||
gain: 1
|
||||
},
|
||||
{
|
||||
loadedItem: null,
|
||||
loading: false,
|
||||
state: "stopped",
|
||||
volume: 1
|
||||
volume: 1,
|
||||
gain: 1
|
||||
},
|
||||
{
|
||||
loadedItem: null,
|
||||
loading: false,
|
||||
state: "stopped",
|
||||
volume: 1
|
||||
volume: 1,
|
||||
gain: 1
|
||||
}
|
||||
]
|
||||
} as MixerState,
|
||||
|
@ -73,9 +89,21 @@ const mixerState = createSlice({
|
|||
},
|
||||
setPlayerVolume(
|
||||
state,
|
||||
action: PayloadAction<{ player: number; volume: number }>
|
||||
action: PayloadAction<{
|
||||
player: number;
|
||||
volume: number;
|
||||
}>
|
||||
) {
|
||||
state.players[action.payload.player].volume = action.payload.volume;
|
||||
},
|
||||
setPlayerGain(
|
||||
state,
|
||||
action: PayloadAction<{
|
||||
player: number;
|
||||
gain: number;
|
||||
}>
|
||||
) {
|
||||
state.players[action.payload.player].gain = action.payload.gain;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -114,9 +142,14 @@ export const load = (player: number, item: PlanItem | Track): AppThunk => (
|
|||
);
|
||||
}
|
||||
el.oncanplay = () => {
|
||||
console.log("can play");
|
||||
};
|
||||
el.oncanplaythrough = () => {
|
||||
console.log("can play through");
|
||||
dispatch(mixerState.actions.itemLoadComplete({ player }));
|
||||
};
|
||||
el.load();
|
||||
console.log("loading");
|
||||
const sauce = audioContext.createMediaElementSource(el);
|
||||
const gain = audioContext.createGain();
|
||||
gain.gain.value = getState().mixer.players[player].volume;
|
||||
|
@ -179,29 +212,158 @@ export const stop = (player: number): AppThunk => dispatch => {
|
|||
}
|
||||
};
|
||||
|
||||
const FADE_TIME_SECONDS = 1;
|
||||
export const setVolume = (
|
||||
player: number,
|
||||
level: VolumePresetEnum
|
||||
): AppThunk => (dispatch, getState) => {
|
||||
let volume: number;
|
||||
let uiLevel: number;
|
||||
switch (level) {
|
||||
case "off":
|
||||
volume = 0;
|
||||
uiLevel = 0;
|
||||
break;
|
||||
case "bed":
|
||||
volume = 0.25;
|
||||
uiLevel = 0.5;
|
||||
break;
|
||||
case "full":
|
||||
volume = 1;
|
||||
volume = uiLevel = 1;
|
||||
break;
|
||||
}
|
||||
const currentLevel = getState().mixer.players[player].volume;
|
||||
playerGainTweens[player] = new (Between as any)(currentLevel, volume)
|
||||
.on("update", (value: number) => {
|
||||
dispatch(mixerState.actions.setPlayerVolume({ player, volume }));
|
||||
if (playerGains[player]) {
|
||||
playerGains[player].gain.value = value;
|
||||
}
|
||||
|
||||
// Right, okay, big fun is happen.
|
||||
// To make the fade sound natural, we need to ramp it exponentially.
|
||||
// To make the UI look sensible, we need to ramp it linearly.
|
||||
// Time for cheating!
|
||||
|
||||
if (typeof playerGainTweens[player] !== "undefined") {
|
||||
// We've interrupted a previous fade.
|
||||
// If we've just hit the button/key to go to the same value as that fade,
|
||||
// stop it and immediately cut to the target value.
|
||||
// Otherwise, stop id and start a new fade.
|
||||
playerGainTweens[player].tweens.forEach(tween => tween.pause());
|
||||
if (playerGainTweens[player].target === level) {
|
||||
delete playerGainTweens[player];
|
||||
dispatch(
|
||||
mixerState.actions.setPlayerVolume({ player, volume: uiLevel })
|
||||
);
|
||||
dispatch(
|
||||
mixerState.actions.setPlayerGain({ player, gain: volume })
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const state = getState().mixer.players[player];
|
||||
|
||||
const currentLevel = state.volume;
|
||||
const currentGain = state.gain;
|
||||
const volumeTween = new Between(currentLevel, uiLevel)
|
||||
.time(FADE_TIME_SECONDS * 1000)
|
||||
.on("update", (val: number) => {
|
||||
console.log(val);
|
||||
dispatch(
|
||||
mixerState.actions.setPlayerVolume({ player, volume: val })
|
||||
);
|
||||
});
|
||||
const gainTween = new Between(currentGain, volume)
|
||||
.time(FADE_TIME_SECONDS * 1000)
|
||||
.easing((Between as any).Easing.Quadratic.InOut)
|
||||
.on("update", (val: number) => {
|
||||
console.log(val);
|
||||
dispatch(mixerState.actions.setPlayerGain({ player, gain: val }));
|
||||
})
|
||||
.time(1000);
|
||||
.on("complete", () => {
|
||||
// clean up when done
|
||||
delete playerGainTweens[player];
|
||||
});
|
||||
|
||||
playerGainTweens[player] = {
|
||||
target: level,
|
||||
tweens: [volumeTween, gainTween]
|
||||
};
|
||||
};
|
||||
|
||||
export const mixerMiddleware: Middleware<
|
||||
{},
|
||||
RootState,
|
||||
Dispatch<any>
|
||||
> = store => next => action => {
|
||||
const oldState = store.getState().mixer;
|
||||
const result = next(action);
|
||||
const newState = store.getState().mixer;
|
||||
newState.players.forEach((state, index) => {
|
||||
if (typeof playerGains[index] !== "undefined") {
|
||||
if (oldState.players[index].gain !== newState.players[index].gain) {
|
||||
playerGains[index].gain.value = state.gain;
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
export const mixerKeyboardShortcutsMiddleware: Middleware<
|
||||
{},
|
||||
RootState,
|
||||
Dispatch<any>
|
||||
> = store => {
|
||||
Keys("q", () => {
|
||||
store.dispatch(play(0));
|
||||
});
|
||||
Keys("w", () => {
|
||||
store.dispatch(pause(0));
|
||||
});
|
||||
Keys("e", () => {
|
||||
store.dispatch(stop(0));
|
||||
});
|
||||
Keys("r", () => {
|
||||
store.dispatch(play(1));
|
||||
});
|
||||
Keys("t", () => {
|
||||
store.dispatch(pause(1));
|
||||
});
|
||||
Keys("y", () => {
|
||||
store.dispatch(stop(1));
|
||||
});
|
||||
Keys("u", () => {
|
||||
store.dispatch(play(2));
|
||||
});
|
||||
Keys("i", () => {
|
||||
store.dispatch(pause(2));
|
||||
});
|
||||
Keys("o", () => {
|
||||
store.dispatch(stop(2));
|
||||
});
|
||||
|
||||
Keys("a", () => {
|
||||
store.dispatch(setVolume(0, "off"));
|
||||
});
|
||||
Keys("s", () => {
|
||||
store.dispatch(setVolume(0, "bed"));
|
||||
});
|
||||
Keys("d", () => {
|
||||
store.dispatch(setVolume(0, "full"));
|
||||
});
|
||||
Keys("f", () => {
|
||||
store.dispatch(setVolume(1, "off"));
|
||||
});
|
||||
Keys("g", () => {
|
||||
store.dispatch(setVolume(1, "bed"));
|
||||
});
|
||||
Keys("h", () => {
|
||||
store.dispatch(setVolume(1, "full"));
|
||||
});
|
||||
Keys("j", () => {
|
||||
store.dispatch(setVolume(2, "off"));
|
||||
});
|
||||
Keys("k", () => {
|
||||
store.dispatch(setVolume(2, "bed"));
|
||||
});
|
||||
Keys("l", () => {
|
||||
store.dispatch(setVolume(2, "full"));
|
||||
});
|
||||
|
||||
return next => action => next(action);
|
||||
};
|
||||
|
|
|
@ -72,7 +72,7 @@ function Item({
|
|||
ref={provided.innerRef}
|
||||
key={id}
|
||||
className={`sp-track ${
|
||||
column > 0 &&
|
||||
column >= 0 &&
|
||||
playerState.loadedItem !== null &&
|
||||
itemId(playerState.loadedItem) === id
|
||||
? "sp-track-active"
|
||||
|
@ -98,6 +98,8 @@ function Item({
|
|||
);
|
||||
}
|
||||
|
||||
const USE_REAL_GAIN_VALUE = false;
|
||||
|
||||
function Player({ id }: { id: number }) {
|
||||
const playerState = useSelector(
|
||||
(state: RootState) => state.mixer.players[id]
|
||||
|
@ -108,7 +110,7 @@ function Player({ id }: { id: number }) {
|
|||
<div className="player">
|
||||
{playerState.loadedItem == null && <div>No Media Selected</div>}
|
||||
{playerState.loadedItem !== null && playerState.loading == false && (
|
||||
<div>{playerState.loadedItem.title}</div>
|
||||
<div style={{ height: "1.5em", overflowY: "hidden" }}>{playerState.loadedItem.title}</div>
|
||||
)}
|
||||
{playerState.loading && <b>LOADING</b>}
|
||||
<div className="mediaButtons">
|
||||
|
@ -134,7 +136,7 @@ function Player({ id }: { id: number }) {
|
|||
<div className="sp-mixer-buttons">
|
||||
<div
|
||||
className="sp-mixer-buttons-backdrop"
|
||||
style={{ width: playerState.volume * 100 + "%" }}
|
||||
style={{ width: (USE_REAL_GAIN_VALUE ? playerState.gain : playerState.volume) * 100 + "%" }}
|
||||
></div>
|
||||
<button onClick={() => dispatch(PlayerState.setVolume(id, "off"))}>
|
||||
Off
|
||||
|
@ -268,7 +270,10 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
|||
}, [timeslotId]);
|
||||
|
||||
async function onDragEnd(result: DropResult, provider: ResponderProvided) {
|
||||
if (result.destination!.droppableId[0] === "$") {
|
||||
if (!result.destination) {
|
||||
return;
|
||||
}
|
||||
if (result.destination.droppableId[0] === "$") {
|
||||
// pseudo-channel
|
||||
return;
|
||||
}
|
||||
|
@ -278,8 +283,8 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
|||
const newItem: TimeslotItem = {
|
||||
type: "central",
|
||||
timeslotitemid: "CHANGEME" + Math.random(),
|
||||
channel: parseInt(result.destination!.droppableId, 10),
|
||||
weight: result.destination!.index,
|
||||
channel: parseInt(result.destination.droppableId, 10),
|
||||
weight: result.destination.index,
|
||||
...data
|
||||
};
|
||||
dispatch(addItem(timeslotId, newItem));
|
||||
|
@ -287,8 +292,8 @@ const Showplanner: React.FC<{ timeslotId: number }> = function({ timeslotId }) {
|
|||
// this is a normal move (ghosts aren't draggable)
|
||||
dispatch(
|
||||
moveItem(timeslotId, result.draggableId, [
|
||||
parseInt(result.destination!.droppableId, 10),
|
||||
result.destination!.index
|
||||
parseInt(result.destination.droppableId, 10),
|
||||
result.destination.index
|
||||
])
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import rootReducer, { RootState } from "./rootReducer";
|
||||
import { configureStore, Action } from "@reduxjs/toolkit";
|
||||
import { configureStore, Action, getDefaultMiddleware } from "@reduxjs/toolkit";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
import { mixerMiddleware, mixerKeyboardShortcutsMiddleware } from "./mixer/state";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: rootReducer
|
||||
reducer: rootReducer,
|
||||
middleware: [...getDefaultMiddleware(), mixerMiddleware, mixerKeyboardShortcutsMiddleware]
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV === "development" && module.hot) {
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -1320,6 +1320,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636"
|
||||
integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==
|
||||
|
||||
"@types/keymaster@^1.6.28":
|
||||
version "1.6.28"
|
||||
resolved "https://registry.yarnpkg.com/@types/keymaster/-/keymaster-1.6.28.tgz#093fc6fe49deff4ee17d36935a49230edb1c935f"
|
||||
integrity sha1-CT/G/kne/07hfTaTWkkjDtsck18=
|
||||
|
||||
"@types/lodash@^4.14.149":
|
||||
version "4.14.149"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
|
||||
|
@ -5938,6 +5943,11 @@ jsx-ast-utils@^2.1.0, jsx-ast-utils@^2.2.1:
|
|||
array-includes "^3.0.3"
|
||||
object.assign "^4.1.0"
|
||||
|
||||
keymaster@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/keymaster/-/keymaster-1.6.2.tgz#e1ae54d0ea9488f9f60b66b668f02e9a1946c6eb"
|
||||
integrity sha1-4a5U0OqUiPn2C2a2aPAumhlGxus=
|
||||
|
||||
killable@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
|
||||
|
|
Loading…
Reference in a new issue