Skip to content

Commit

Permalink
feat: multi-channel vu meter
Browse files Browse the repository at this point in the history
feat: disable vu meter client-side
  • Loading branch information
mint-dewit committed Nov 10, 2020
1 parent 9caa210 commit 5447042
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 129 deletions.
7 changes: 4 additions & 3 deletions client/assets/css/Channel.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
);
margin: 4px;
border-radius: 7px;
width: 86px;
height: 950px;
position: relative;
touch-action: none;
display: flex;
flex-direction: column;
align-items: center;
}

.channel-body > .channel-props,
.channel-body > .out-control,
.channel-body > .channel-control {
Expand All @@ -25,12 +24,14 @@
.channel-body > .fader {
flex-grow: 1;
display: flex;
flex-direction: row-reverse;
flex-direction: row;
justify-content: center;
align-items: center;
}
.channel-body > .out-control {
padding-bottom: 5px;
display: flex;
flex-direction: column;
}
.channel-body > .channel-control {
height: 160px;
Expand Down
11 changes: 9 additions & 2 deletions client/components/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -347,9 +347,16 @@ class Channel extends React.Component<
{this.amixButton()}
</div>
<div className="fader">
{!window.location.search.includes('vu=0') &&
window.mixerProtocol.channelTypes[0].fromMixer.CHANNEL_VU?.map(
(_, i) => (
<VuMeter
faderIndex={this.faderIndex}
channel={i}
/>
)
)}
{this.fader()}
{window.mixerProtocol.channelTypes[0].fromMixer
.CHANNEL_VU && <VuMeter faderIndex={this.faderIndex} />}
</div>
<div className="out-control">
{this.pgmButton()}
Expand Down
41 changes: 26 additions & 15 deletions client/components/VuMeter.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as React from 'react'
import { connect } from 'react-redux'
import { vuMeters } from '../utils/SocketClientHandlers'

//assets:
import '../assets/css/VuMeter.css'
//Utils:

export interface IVuMeterInjectedProps {
showSnaps: boolean
vuVal: number
faderIndex: number
channel: number
}

interface IVuMeterProps {
Expand All @@ -27,6 +29,8 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
WINDOW: number = 2000

private _painting = false
private _previousVal = -1
private _value = 0

constructor(props: any) {
super(props)
Expand All @@ -48,33 +52,33 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
}

getTotalPeak = () => {
if (this.props.vuVal > this.totalPeak) {
this.totalPeak = this.props.vuVal
if (this._value > this.totalPeak) {
this.totalPeak = this._value
}
return this.totalHeight() * this.totalPeak
}

getWindowPeak = () => {
if (
this.props.vuVal > this.windowPeak ||
this._value > this.windowPeak ||
Date.now() - this.windowLast > this.WINDOW
) {
this.windowPeak = this.props.vuVal
this.windowPeak = this._value
this.windowLast = Date.now()
}
return this.totalHeight() * this.windowPeak
}

calcLower = () => {
let val = this.props.vuVal
let val = this._value
if (val >= this.meterTest) {
val = this.meterTest
}
return this.totalHeight() * val
}

calcMiddle = () => {
let val = this.props.vuVal
let val = this._value
if (val < this.meterTest) {
val = this.meterTest
} else if (val >= this.meterZero) {
Expand All @@ -84,7 +88,7 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
}

calcUpper = () => {
let val = this.props.vuVal
let val = this._value
if (val < this.meterZero) {
val = this.meterZero
}
Expand All @@ -108,6 +112,15 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
}
this._painting = true

this._value = vuMeters[this.props.faderIndex]?.[this.props.channel] || 0

if (this._value === this._previousVal) {
this._painting = false
window.requestAnimationFrame(this.paintVuMeter)
return
}
this._previousVal = this._value

const context = this.canvas.getContext('2d', {
antialias: false,
stencil: false,
Expand All @@ -116,8 +129,7 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {

if (!context) return

const range =
this.meterMax - this.meterMin
const range = this.meterMax - this.meterMin
context.clearRect(
0,
0,
Expand All @@ -138,8 +150,7 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
context.fillStyle = 'rgb(53, 167, 0)'
context.fillRect(
0,
this.totalHeight() * (range - this.meterTest) -
this.calcMiddle(),
this.totalHeight() * (range - this.meterTest) - this.calcMiddle(),
this.canvas.clientWidth,
this.calcMiddle()
)
Expand All @@ -148,8 +159,7 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {
context.fillStyle = 'rgb(206, 0, 0)'
context.fillRect(
0,
this.totalHeight() * (range - this.meterZero) -
this.calcUpper(),
this.totalHeight() * (range - this.meterZero) - this.calcUpper(),
this.canvas.clientWidth,
this.calcUpper()
)
Expand Down Expand Up @@ -210,7 +220,8 @@ export class VuMeter extends React.PureComponent<IVuMeterInjectedProps> {

const mapStateToProps = (state: any, props: any): IVuMeterInjectedProps => {
return {
vuVal: state.faders[0].vuMeters[props.faderIndex].vuVal,
faderIndex: props.faderIndex,
channel: props.channel,
showSnaps: state.settings[0].showSnaps,
}
}
Expand Down
21 changes: 20 additions & 1 deletion client/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import { socketClientHandlers } from './utils/SocketClientHandlers'
import { socketClientHandlers, vuMeters } from './utils/SocketClientHandlers'
import io from 'socket.io-client'

//Redux:
Expand All @@ -27,6 +27,7 @@ declare global {
mixerProtocolPresets: any
mixerProtocolList: any
socketIoClient: any
socketIoVuClient: any
snapshotFileList: string[]
ccgFileList: string[]
mixerPresetList: string[]
Expand All @@ -50,6 +51,24 @@ window.socketIoClient.emit('get-store', 'update local store')
window.socketIoClient.emit('get-settings', 'update local settings')
window.socketIoClient.emit('get-mixerprotocol', 'get selected mixerprotocol')

if (!window.location.search.includes('vu=0')) {
window.socketIoVuClient = io(
document.location.protocol + '//' + document.location.hostname + ':1178'
)
window.socketIoVuClient.on('connect', () => console.log('connection!'))
window.socketIoVuClient.on(
'channel',
(faderIndex: number, channelIndex: number, level: number) => {
// console.log('got vu!', ...payload)
if (!vuMeters[faderIndex]) vuMeters[faderIndex] = []
vuMeters[faderIndex][channelIndex] = level
}
)
// window.socketIoVuClient.on('reduction', (...payload: any[]) =>
// console.log('got reduction!', ...payload)
// )
}

ReactDom.render(
<ReduxProvider store={storeRedux}>
<I18nextProvider i18n={i18n}>
Expand Down
32 changes: 2 additions & 30 deletions client/utils/SocketClientHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ import {
storeUpdateSettings,
} from '../../server/reducers/settingsActions'
import {
SOCKET_SET_VU,
SOCKET_RETURN_SNAPSHOT_LIST,
SOCKET_SET_FULL_STORE,
SOCKET_SET_STORE_FADER,
SOCKET_SET_STORE_CHANNEL,
SOCKET_RETURN_CCG_LIST,
SOCKET_SET_VU_REDUCTION,
SOCKET_SET_MIXER_ONLINE,
SOCKET_SET_ALL_VU,
SOCKET_RETURN_MIXER_PRESET_LIST,
SOCKET_RETURN_PAGES_LIST,
} from '../../server/constants/SOCKET_IO_DISPATCHERS'
Expand All @@ -32,6 +30,8 @@ import {
InumberOfChannels,
} from '../../server/reducers/channelsReducer'

export const vuMeters: number[][] = []

export const socketClientHandlers = () => {
let vuUpdateSpeed = Date.now()
let vuReductionUpdateSpeed = Date.now()
Expand Down Expand Up @@ -99,34 +99,6 @@ export const socketClientHandlers = () => {
storeSetSingleChState(payload.channelIndex, payload.state)
)
})
.on(SOCKET_SET_ALL_VU, (payload: any) => {
if (Date.now() - vuUpdateSpeed > 100) {
vuUpdateSpeed = Date.now()
payload.vuMeters.forEach(
(meterLevel: number, index: number) => {
window.storeRedux.dispatch(
storeVuLevel(index, meterLevel)
)
}
)
payload.vuReductionMeters.forEach(
(meterLevel: number, index: number) => {
window.storeRedux.dispatch(
storeVuReductionLevel(index, meterLevel)
)
}
)
}
})
.on(SOCKET_SET_VU, (payload: any) => {
if (Date.now() - vuUpdateSpeed > 100) {
vuUpdateSpeed = Date.now()

window.storeRedux.dispatch(
storeVuLevel(payload.faderIndex, payload.level)
)
}
})
.on(SOCKET_SET_VU_REDUCTION, (payload: any) => {
if (Date.now() - vuReductionUpdateSpeed > 100) {
vuReductionUpdateSpeed = Date.now()
Expand Down
2 changes: 0 additions & 2 deletions server/constants/SOCKET_IO_DISPATCHERS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ export const SOCKET_CLEAR_PST = 'clearPst'
// Div:
export const SOCKET_SAVE_SETTINGS = 'saveSettings'
export const SOCKET_RESTART_SERVER = 'restartServer'
export const SOCKET_SET_VU = 'setVu'
export const SOCKET_SET_ALL_VU = 'setAllVu'
export const SOCKET_SET_VU_REDUCTION = 'setVuReduction'
export const SOCKET_GET_SNAPSHOT_LIST = 'getSnapshotList'
export const SOCKET_RETURN_SNAPSHOT_LIST = 'returnSnapshotList'
Expand Down
6 changes: 5 additions & 1 deletion server/constants/mixerProtocols/casparCGMaster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,11 @@ let CasparCGMasterObject: ICasparCGMixerGeometry = {
CHANNEL_VU: [
{
mixerMessage:
'/stage/channel/{ch}/layer/{layer}/mixer/volume',
'/channel/{ch}/stage/layer/{layer}/audio/1/pFS',
},
{
mixerMessage:
'/channel/{ch}/stage/layer/{layer}/audio/2/pFS',
},
],
},
Expand Down
6 changes: 5 additions & 1 deletion server/expressHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ const path = require('path')
const app = express()
const server = require('http').Server(app)
const socketServer = require('socket.io')(server)
const vuServer = require('socket.io')({
perMessageDeflate: false, // disable for cpu performance
})
const SERVER_PORT = 1176

app.use('/', express.static(path.join(__dirname, '..')))
server.listen(SERVER_PORT)
vuServer.listen(SERVER_PORT + 2)
logger.info(`Server started at http://localhost:${SERVER_PORT}`)

server.on('connection', () => {
Expand All @@ -26,4 +30,4 @@ export const expressInit = () => {
logger.info('Initialising WebServer')
}

export { socketServer }
export { socketServer, vuServer }
9 changes: 0 additions & 9 deletions server/reducers/faderActions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { fxParamsList } from '../constants/MixerProtocolInterface'
import { IFader, IFaders } from './fadersReducer'

export const SET_VU_LEVEL = 'SET_VU_LEVEL'
export const SET_VU_REDUCTION_LEVEL = 'SET_REDUCTION_LEVEL'
export const SET_COMPLETE_FADER_STATE = 'SET_COMPLETE_FADER_STATE'
export const SET_SINGLE_FADER_STATE = 'SET_SINGLE_FADER_STATE'
Expand Down Expand Up @@ -37,14 +36,6 @@ export const SET_AMIX = 'SET_AMIX'
export const SET_CAPABILITY = 'SET_CAPABILITY'
export const TOGGLE_ALL_MANUAL = 'TOGGLE_ALL_MANUAL'

export const storeVuLevel = (channel: number, level: number) => {
return {
type: SET_VU_LEVEL,
channel: channel,
level: level,
}
}

export const storeVuReductionLevel = (channel: number, level: number) => {
return {
type: SET_VU_REDUCTION_LEVEL,
Expand Down
10 changes: 0 additions & 10 deletions server/reducers/fadersReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
SET_PST,
SET_PST_VO,
SET_VO,
SET_VU_LEVEL,
SET_VU_REDUCTION_LEVEL,
SHOW_CHANNEL,
IGNORE_AUTOMATION,
Expand Down Expand Up @@ -73,7 +72,6 @@ export interface IFader {
}

export interface IVuMeters {
vuVal: number
reductionVal: number
}

Expand Down Expand Up @@ -106,7 +104,6 @@ const defaultFadersReducerState = (numberOfFaders: number): IFaders[] => {
disabled: false,
}
defaultObj[0].vuMeters.push({
vuVal: 0.0,
reductionVal: 0.0,
})
for (let y = 0; y < DEFAULTS.NUMBER_OF_SNAPS; y++) {
Expand All @@ -131,13 +128,6 @@ export const faders = (
}

switch (action.type) {
case SET_VU_LEVEL:
if (typeof nextState[0].vuMeters[action.channel] !== 'undefined') {
nextState[0].vuMeters[action.channel].vuVal = parseFloat(
action.level
)
}
return nextState
case SET_VU_REDUCTION_LEVEL:
if (typeof nextState[0].vuMeters[action.channel] !== 'undefined') {
nextState[0].vuMeters[action.channel].reductionVal = parseFloat(
Expand Down
Loading

0 comments on commit 5447042

Please sign in to comment.