diff --git a/server/package.json b/server/package.json index 10b3ba86..0eeb6739 100644 --- a/server/package.json +++ b/server/package.json @@ -22,7 +22,7 @@ "@tv2media/logger": "^2.0.1", "atem-connection": "^3.2.0", "casparcg-connection": "^5.1.0", - "emberplus-connection": "^0.1.2", + "emberplus-connection": "^0.2.1", "express": "^4.18.2", "node-emberplus": "^3.0.5", "node-vmix": "^1.6.1", @@ -36,4 +36,4 @@ "webmidi": "^2.5.1", "shared": "file:../shared" } -} +} \ No newline at end of file diff --git a/server/src/utils/mixerConnections/EmberMixerConnection.ts b/server/src/utils/mixerConnections/EmberMixerConnection.ts index 9c2c7ed4..aea87d8c 100644 --- a/server/src/utils/mixerConnections/EmberMixerConnection.ts +++ b/server/src/utils/mixerConnections/EmberMixerConnection.ts @@ -27,7 +27,11 @@ import { storeSetChLabel, } from '../../../../shared/src/actions/channelActions' import { storeSetMixerOnline } from '../../../../shared/src/actions/settingsActions' -import { IChannelReference, IFader } from '../../../../shared/src/reducers/fadersReducer' +import { + IChannelReference, + IFader, +} from '../../../../shared/src/reducers/fadersReducer' +import { EmberElement, NumberedTreeNode } from 'emberplus-connection/dist/model' export class EmberMixerConnection { mixerProtocol: IMixerProtocol @@ -49,9 +53,12 @@ export class EmberMixerConnection { } private getAssignedFaderIndex(channelIndex: number) { - return state.faders[0].fader.findIndex( - (fader: IFader) => fader.assignedChannels?.some((assigned: IChannelReference) => { - return (assigned.mixerIndex === this.mixerIndex && assigned.channelIndex === channelIndex) + return state.faders[0].fader.findIndex((fader: IFader) => + fader.assignedChannels?.some((assigned: IChannelReference) => { + return ( + assigned.mixerIndex === this.mixerIndex && + assigned.channelIndex === channelIndex + ) }) ) } @@ -212,17 +219,13 @@ export class EmberMixerConnection { channelTypeIndex ) } - store.dispatch( - storeShowChannel(assignedFaderIndex, true) - ) + store.dispatch(storeShowChannel(assignedFaderIndex, true)) global.mainThreadHandler.updatePartialStore( assignedFaderIndex ) } else { logger.info(`Channel ${ch} offline`) - store.dispatch( - storeShowChannel(assignedFaderIndex, false) - ) + store.dispatch(storeShowChannel(assignedFaderIndex, false)) global.mainThreadHandler.updatePartialStore( assignedFaderIndex ) @@ -249,7 +252,10 @@ export class EmberMixerConnection { ) if (!node) return - await this.emberConnection.subscribe(node, cb) + await this.emberConnection.subscribe( + node as NumberedTreeNode<EmberElement>, + cb + ) cb(node) } catch (e) { @@ -285,9 +291,7 @@ export class EmberMixerConnection { ) if (!channel.fadeActive && level >= 0 && level <= 1) { - store.dispatch( - storeFaderLevel(assignedFaderIndex, level) - ) + store.dispatch(storeFaderLevel(assignedFaderIndex, level)) store.dispatch({ type: SET_OUTPUT_LEVEL, channel: assignedFaderIndex, @@ -297,9 +301,7 @@ export class EmberMixerConnection { // toggle pgm based on level logger.trace(`Set Channel ${ch} pgmOn ${level > 0}`) - store.dispatch( - storeSetPgm(assignedFaderIndex, level > 0) - ) + store.dispatch(storeSetPgm(assignedFaderIndex, level > 0)) global.mainThreadHandler.updatePartialStore( assignedFaderIndex @@ -357,9 +359,7 @@ export class EmberMixerConnection { ) ) } - global.mainThreadHandler.updatePartialStore( - assignedFaderIndex - ) + global.mainThreadHandler.updatePartialStore(assignedFaderIndex) } ) } @@ -390,9 +390,7 @@ export class EmberMixerConnection { (node.contents as Model.Parameter).value as boolean ) ) - global.mainThreadHandler.updatePartialStore( - assignedFaderIndex - ) + global.mainThreadHandler.updatePartialStore(assignedFaderIndex) } ) } @@ -429,9 +427,7 @@ export class EmberMixerConnection { // assume it is in db now level = this._faderLevelToFloat(Number(level), 0) store.dispatch(storeInputGain(assignedFaderIndex, level)) - global.mainThreadHandler.updatePartialStore( - assignedFaderIndex - ) + global.mainThreadHandler.updatePartialStore(assignedFaderIndex) } ) } @@ -510,9 +506,7 @@ export class EmberMixerConnection { (node.contents as Model.Parameter).value as boolean ) ) - global.mainThreadHandler.updatePartialStore( - assignedFaderIndex - ) + global.mainThreadHandler.updatePartialStore(assignedFaderIndex) } ) // subscribe to input selectors @@ -623,9 +617,7 @@ export class EmberMixerConnection { (node.contents as Model.Parameter).value as boolean ) ) - global.mainThreadHandler.updatePartialStore( - assignedFaderIndex - ) + global.mainThreadHandler.updatePartialStore(assignedFaderIndex) } ) } diff --git a/server/src/utils/mixerConnections/LawoRubyConnection.ts b/server/src/utils/mixerConnections/LawoRubyConnection.ts index 71ab7c3c..33c5206a 100644 --- a/server/src/utils/mixerConnections/LawoRubyConnection.ts +++ b/server/src/utils/mixerConnections/LawoRubyConnection.ts @@ -15,10 +15,12 @@ import { storeSetAMix, storeCapability, storeShowChannel, + storeSetPgm, } from '../../../../shared/src/actions/faderActions' import { logger } from '../logger' import { storeSetMixerOnline } from '../../../../shared/src/actions/settingsActions' import { storeSetChLabel } from '../../../../shared/src/actions/channelActions' +import { EmberElement, NumberedTreeNode } from 'emberplus-connection/dist/model' // TODO - should these be util functions? export function floatToDB(f: number): number { @@ -122,7 +124,9 @@ export class LawoRubyMixerConnection { 'Ruby.Sources' ) // get the sources - const req = await this.emberConnection.getDirectory(sourceNode) + const req = await this.emberConnection.getDirectory( + sourceNode as NumberedTreeNode<EmberElement> + ) const sources = await req.response // map sourceNames to their fader number @@ -251,36 +255,37 @@ export class LawoRubyMixerConnection { if (node.contents.type !== Model.ElementType.Parameter) return logger.debug(`Subscription of channel level: ${command}`) - this.emberConnection.subscribe(node, () => { - logger.trace(`Receiving Level from Ch ${ch}`) - if ( - !state.channels[0].chMixerConnection[this.mixerIndex] - .channel[ch - 1].fadeActive && - (node.contents as Model.Parameter).value as number > - this.mixerProtocol.channelTypes[typeIndex].fromMixer - .CHANNEL_OUT_GAIN[0].min - ) { - store.dispatch( - storeFaderLevel( - ch - 1, - dbToFloat( - (node.contents as Model.Parameter) - .value as number - ) - ) - ) - global.mainThreadHandler.updatePartialStore(ch - 1) - if (remoteConnections) { - remoteConnections.updateRemoteFaderState( - ch - 1, - dbToFloat( - (node.contents as Model.Parameter) - .value as number + this.emberConnection.subscribe( + node as NumberedTreeNode<EmberElement>, + () => { + const levelDB = (node.contents as Model.Parameter) + .value as number + logger.debug(`Receiving Level from Ch ${ch}: ${levelDB}`) + if ( + !state.channels[0].chMixerConnection[this.mixerIndex] + .channel[ch - 1].fadeActive && + levelDB >= + this.mixerProtocol.channelTypes[typeIndex].fromMixer + .CHANNEL_OUT_GAIN[0].min + ) { + // update the fader + const level = dbToFloat(levelDB) + store.dispatch(storeFaderLevel(ch - 1, level)) + + // toggle pgm based on level + logger.trace(`Set Channel ${ch} pgmOn ${level > 0}`) + store.dispatch(storeSetPgm(ch - 1, level > 0)) + + global.mainThreadHandler.updatePartialStore(ch - 1) + if (remoteConnections) { + remoteConnections.updateRemoteFaderState( + ch - 1, + level ) - ) + } } } - }) + ) } catch (e) { logger.data(e).debug('error when subscribing to fader level') } @@ -303,15 +308,22 @@ export class LawoRubyMixerConnection { if (node.contents.type !== Model.ElementType.Parameter) return logger.debug(`Subscription of channel gain: ${command}`) - this.emberConnection.subscribe(node, () => { - logger.trace(`Receiving Gain from Ch ${ch}`) - const value = (node.contents as Model.Parameter).value as number - const level = (value - proto.min) / (proto.max - proto.min) - if ((node.contents as Model.Parameter).value as number > proto.min) { - store.dispatch(storeInputGain(ch - 1, level)) - global.mainThreadHandler.updatePartialStore(ch - 1) + this.emberConnection.subscribe( + node as NumberedTreeNode<EmberElement>, + () => { + logger.trace(`Receiving Gain from Ch ${ch}`) + const value = (node.contents as Model.Parameter) + .value as number + const level = (value - proto.min) / (proto.max - proto.min) + if ( + ((node.contents as Model.Parameter).value as number) > + proto.min + ) { + store.dispatch(storeInputGain(ch - 1, level)) + global.mainThreadHandler.updatePartialStore(ch - 1) + } } - }) + ) } catch (e) { logger.data(e).debug('Error when subscribing to gain level') } @@ -340,24 +352,31 @@ export class LawoRubyMixerConnection { } logger.debug(`Subscription of channel input selector: ${command}`) - this.emberConnection.subscribe(node, () => { - logger.trace(`Receiving InpSelector from Ch ${ch}`) - this.mixerProtocol.channelTypes[ - typeIndex - ].fromMixer.CHANNEL_INPUT_SELECTOR.forEach((selector, i) => { - if ( - selector.value === - (node.contents as Model.Parameter).value - ) { - store.dispatch({ - type: SET_INPUT_SELECTOR, - channel: ch - 1, - selected: i + 1, - }) - global.mainThreadHandler.updatePartialStore(ch - 1) - } - }) - }) + this.emberConnection.subscribe( + node as NumberedTreeNode<EmberElement>, + () => { + logger.trace(`Receiving InpSelector from Ch ${ch}`) + this.mixerProtocol.channelTypes[ + typeIndex + ].fromMixer.CHANNEL_INPUT_SELECTOR.forEach( + (selector, i) => { + if ( + selector.value === + (node.contents as Model.Parameter).value + ) { + store.dispatch({ + type: SET_INPUT_SELECTOR, + channel: ch - 1, + selected: i + 1, + }) + global.mainThreadHandler.updatePartialStore( + ch - 1 + ) + } + } + ) + } + ) } catch (e) { if (e.message.match(/could not find node/i)) { logger.debug(`set_cap ${ch} hasInputSel false`) @@ -392,16 +411,19 @@ export class LawoRubyMixerConnection { } logger.debug(`Subscription of AMix state: ${command}`) - this.emberConnection.subscribe(node, () => { - logger.trace(`Receiving AMix state from Ch ${ch}`) - store.dispatch( - storeSetAMix( - ch - 1, - (node.contents as Model.Parameter).value === 1 + this.emberConnection.subscribe( + node as NumberedTreeNode<EmberElement>, + () => { + logger.trace(`Receiving AMix state from Ch ${ch}`) + store.dispatch( + storeSetAMix( + ch - 1, + (node.contents as Model.Parameter).value === 1 + ) ) - ) - global.mainThreadHandler.updatePartialStore(ch - 1) - }) + global.mainThreadHandler.updatePartialStore(ch - 1) + } + ) } catch (e) { if (e.message.match(/could not find node/i)) { logger.debug(`set_cap ${ch - 1} hasAMix false`) diff --git a/yarn.lock b/yarn.lock index 79e1f762..ba78aa27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3068,17 +3068,17 @@ electron@16.2.6: "@types/node" "^14.6.2" extract-zip "^1.0.3" -emberplus-connection@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/emberplus-connection/-/emberplus-connection-0.1.2.tgz#001bb1db4ac28d340af59e6fbe8b4d2574dc1373" - integrity sha512-oTxY2wyUbWTD2hSaQOvhrQnrgqpXrc39UPQUqPUwbdPpH3UX9mChLtHUrp1GU2zl+/UsCMaPcG+okf1Td268QQ== +emberplus-connection@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/emberplus-connection/-/emberplus-connection-0.2.1.tgz#3166b29e228a1a2b561e346112c45d711f3238ea" + integrity sha512-M5/8fNk0u84xC8M3e4QZoKonaxfei92FynWfSqww1IoP4eAt9/A5xxmFaRTW/ivLgP58hXlYC6mhemSQzoL4bg== dependencies: asn1 evs-broadcast/node-asn1 - debug "^4.3.3" - enum "^2.4.0" + debug "^4.3.4" + eventemitter3 "^4.0.7" long "^3.2.0" smart-buffer "^3.0.3" - tslib "^2.3.1" + tslib "^2.6.2" emittery@^0.13.1: version "0.13.1" @@ -3157,13 +3157,6 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -enum@^2.4.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/enum/-/enum-2.5.0.tgz#f205b8c65a335a8ace8081105df971b18568b984" - integrity sha512-IN9mE0yf+9DoUvGpNQfvJNJ9HyS9VGeo7llLkPdRBtMU2LHLXiQ/JcOI03u8lig0lefGCewv9x82vK8LI8rNPg== - dependencies: - is-buffer "^1.1.0" - env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -4070,11 +4063,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-buffer@^1.1.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -6105,7 +6093,7 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -redux@^4.1.2, redux@^4.2.1: +redux@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== @@ -7105,6 +7093,11 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.5.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + tsscmp@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"