diff --git a/client/assets/css/ChanStripFull.css b/client/assets/css/ChanStripFull.css
new file mode 100644
index 00000000..3956a272
--- /dev/null
+++ b/client/assets/css/ChanStripFull.css
@@ -0,0 +1,257 @@
+.chan-strip-full-body {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 1200px;
+ overflow: auto;
+ max-height: 90vh;
+ background-color: rgb(31, 31, 31);
+ border-color: rgb(124, 124, 124);
+ border-style: solid;
+ border-width: 4px;
+ text-align: left;
+ z-index: 2;
+
+ color: #fff;
+}
+
+.chan-strip-full-body > .header {
+ margin-left: 40px;
+ margin-top: 10px;
+ margin-right: 80px;
+ /* width: 420px; */
+ font-size: 240%;
+ color: #fff;
+ white-space: nowrap;
+}
+
+.chan-strip-full-body > .parameters {
+ top: 5px;
+ left: 2px;
+ height: 900px;
+ overflow: auto;
+ text-align: center;
+ color: #fff;
+}
+
+.chan-strip-full-body .parameters .horizontal {
+ display: flex;
+ justify-content: space-evenly;
+}
+.chan-strip-full-body .parameters .horizontal .item {
+}
+.chan-strip-full-body .parameters .horizontal .item .content {
+ display: flex;
+}
+
+.parameters > .inp-comp-del-group {
+ display: flex;
+ top: 5px;
+ left: 2px;
+ margin-left: 5px;
+ overflow: auto;
+ text-align: center;
+ color: #fff;
+}
+
+.inp-comp-del-group > .horizontal-space {
+ width: 40px;
+ height: 50px;
+}
+
+.parameters > .eq-group,
+.content > .eq-group {
+ display: flex;
+ top: 5px;
+ left: 2px;
+ margin-left: 90px;
+ overflow: auto;
+ text-align: center;
+ font-size: 14px;
+ color: #fff;
+}
+.content > .eq-group {
+ margin-left: 0;
+}
+
+.eq-group > .horizontal-space {
+ width: 150px;
+ height: 50px;
+}
+
+.eq > .group-text {
+ text-align: center;
+ line-height: 20px;
+ font-size: 110%;
+}
+
+.zero-eq {
+ width: 63px;
+ height: 2px;
+ margin-left: -68px;
+ margin-right: 30px;
+ margin-top: 111px;
+}
+
+.zero-comp {
+ width: 63px;
+ height: 2px;
+ margin-left: -68px;
+ margin-right: 30px;
+ margin-top: 81px;
+}
+
+.zero-monitor {
+ width: 2px;
+ height: 20px;
+ margin-left: 10px;
+ margin-top: -150px;
+}
+
+.parameters > .parameter-text,
+.content > .parameter-text {
+ list-style-type: none;
+ text-align: center;
+ margin-top: 15px;
+ line-height: 10px;
+ font-size: 14px;
+}
+
+.parameter-text > .parameter-mini-text,
+.content > .parameter-mini-text {
+ list-style-type: none;
+ text-align: center;
+ margin-top: 5px;
+ line-height: 10px;
+ font-size: 80%;
+}
+
+.inp-comp-del-group > .delayButtons {
+ width: 30px;
+ margin-top: 24px;
+ margin-left: 50px;
+}
+.content > .delayButtons {
+ width: 30px;
+ margin-top: 24px;
+ margin-left: 50px;
+}
+
+.delayButtons > .delayTime {
+ outline: none;
+ -moz-outline: none;
+ color: white;
+ height: 45px;
+ width: 70px;
+ border-color: rgb(71, 71, 71);
+ background-color: rgb(53, 53, 53);
+ margin-left: -50px;
+ margin-top: 5px;
+ border-radius: 7px;
+}
+
+.inp-comp-del-group > .input-buttons {
+ width: 30px;
+ margin-top: 24px;
+ margin-left: 50px;
+}
+.inp-comp-del-group .input-buttons.disabled {
+ visibility: hidden;
+}
+.content > .input-buttons {
+ width: 30px;
+ margin-top: 24px;
+ margin-left: 50px;
+}
+.content > .input-buttons.disabled {
+ visibility: hidden;
+}
+
+.input-buttons > .input-select {
+ outline: none;
+ -moz-outline: none;
+ color: white;
+ height: 62px;
+ width: 70px;
+ border-color: rgb(71, 71, 71);
+ background-color: rgb(53, 53, 53);
+ margin-left: -50px;
+ margin-top: 5px;
+ border-radius: 7px;
+}
+.input-buttons > .input-select.active {
+ background-color: #2f475b;
+}
+
+.parameters > .monitor-sends,
+.content > .monitor-sends {
+ list-style-type: none;
+ display: flex;
+ text-align: center;
+ margin-top: 15px;
+ margin-left: 1px;
+ padding: 0px;
+ line-height: 10px;
+ font-size: 95%;
+}
+
+.header > .close {
+ position: absolute;
+ outline: none;
+ border-color: rgb(99, 99, 99);
+ background-color: rgb(27, 27, 27);
+ border-radius: 20px;
+ color: #fff;
+ width: 50px;
+ height: 50px;
+ font-size: 30px;
+ /* margin-top: 5px; */
+ right: 10px;
+}
+
+.header > .button {
+ outline: none;
+ border-color: rgb(99, 99, 99);
+ background-color: rgb(27, 27, 27);
+ border-radius: 7px;
+ margin-left: 10px;
+ width: 80px;
+ height: 50px;
+ font-size: 12px;
+ line-height: 30px;
+ color: #fff;
+}
+
+.chan-strip-fader {
+ width: 10px;
+ height: 190px;
+ margin-left: 35px;
+ margin-right: 30px;
+ margin-top: 10px;
+ border-width: 0px;
+ border-style: solid;
+ border-radius: 8px;
+ background-color: rgb(17, 17, 17);
+}
+
+.chan-strip-thumb {
+ margin-left: -20px;
+ color: #3a3a3a;
+ font-size: 90%;
+ line-height: 50px;
+ width: 45px;
+ height: 49px;
+ border: 1px solid #c5c2c2;
+ border-radius: 8px;
+ background: linear-gradient(
+ to top,
+ #3a3a3a 0%,
+ #c2c2c2 20%,
+ hsl(0, 0%, 57%) 50%,
+ #00a 1px,
+ #919191 52%,
+ #c2c2c2 80%,
+ #3a3a3a 100%
+ );
+}
diff --git a/client/components/ChanStrip.tsx b/client/components/ChanStrip.tsx
index 12e203c9..2e901085 100644
--- a/client/components/ChanStrip.tsx
+++ b/client/components/ChanStrip.tsx
@@ -620,31 +620,11 @@ class ChanStrip extends React.PureComponent<
>
X
- {window.location.search.includes(
- 'settings=0'
- ) ? null : (
-
- )}
- {window.location.search.includes(
- 'settings=0'
- ) ? null : (
-
- )}
diff --git a/client/components/ChanStripFull.tsx b/client/components/ChanStripFull.tsx
new file mode 100644
index 00000000..99d16103
--- /dev/null
+++ b/client/components/ChanStripFull.tsx
@@ -0,0 +1,718 @@
+import React from 'react'
+import ReactSlider from 'react-slider'
+
+import '../assets/css/ChanStripFull.css'
+import { Store } from 'redux'
+import { connect } from 'react-redux'
+import {
+ storeShowOptions,
+ storeShowMonitorOptions,
+ storeShowChanStripFull,
+} from '../../server/reducers/settingsActions'
+import { IFader } from '../../server/reducers/fadersReducer'
+import {
+ SOCKET_SET_THRESHOLD,
+ SOCKET_SET_RATIO,
+ SOCKET_SET_DELAY_TIME,
+ SOCKET_SET_FX,
+ SOCKET_SET_AUX_LEVEL,
+ SOCKET_SET_INPUT_GAIN,
+ SOCKET_SET_INPUT_SELECTOR,
+} from '../../server/constants/SOCKET_IO_DISPATCHERS'
+import CcgChannelInputSettings from './CcgChannelSettings'
+import ReductionMeter from './ReductionMeter'
+import ClassNames from 'classnames'
+import { fxParamsList } from '../../server/constants/MixerProtocolInterface'
+
+interface IChanStripFullInjectProps {
+ label: string
+ selectedProtocol: string
+ numberOfChannelsInType: Array
+ channel: Array
+ fader: Array
+ auxSendIndex: number
+ offtubeMode: boolean
+}
+
+interface IChanStripFullProps {
+ faderIndex: number
+}
+
+class ChanStripFull extends React.PureComponent<
+ IChanStripFullProps & IChanStripFullInjectProps & Store
+> {
+ constructor(props: any) {
+ super(props)
+ }
+
+ shouldComponentUpdate(
+ nextProps: IChanStripFullInjectProps & IChanStripFullProps
+ ) {
+ if (nextProps.faderIndex > -1) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+ handleShowRoutingOptions() {
+ this.props.dispatch(storeShowOptions(this.props.faderIndex))
+ this.props.dispatch(storeShowChanStripFull(-1))
+ }
+
+ handleShowMonitorOptions() {
+ this.props.dispatch(storeShowMonitorOptions(this.props.faderIndex))
+ this.props.dispatch(storeShowChanStripFull(-1))
+ }
+
+ handleClose = () => {
+ this.props.dispatch(storeShowChanStripFull(-1))
+ }
+ handleInputSelect(selected: number) {
+ window.socketIoClient.emit(SOCKET_SET_INPUT_SELECTOR, {
+ faderIndex: this.props.faderIndex,
+ selected: selected,
+ })
+ }
+ handleInputGain(event: any) {
+ window.socketIoClient.emit(SOCKET_SET_INPUT_GAIN, {
+ faderIndex: this.props.faderIndex,
+ level: parseFloat(event),
+ })
+ }
+ handleThreshold(event: any) {
+ window.socketIoClient.emit(SOCKET_SET_THRESHOLD, {
+ channel: this.props.faderIndex,
+ level: parseFloat(event),
+ })
+ }
+ handleRatio(event: any) {
+ window.socketIoClient.emit(SOCKET_SET_RATIO, {
+ channel: this.props.faderIndex,
+ level: parseFloat(event),
+ })
+ }
+
+ handleDelay(event: any) {
+ window.socketIoClient.emit(SOCKET_SET_DELAY_TIME, {
+ channel: this.props.faderIndex,
+ delayTime: parseFloat(event),
+ })
+ }
+
+ changeDelay(currentValue: number, addValue: number) {
+ window.socketIoClient.emit(SOCKET_SET_DELAY_TIME, {
+ channel: this.props.faderIndex,
+ delayTime: currentValue + addValue,
+ })
+ }
+
+ handleFx(fxParam: fxParamsList, event: any) {
+ window.socketIoClient.emit(SOCKET_SET_FX, {
+ fxParam: fxParam,
+ channel: this.props.faderIndex,
+ level: parseFloat(event),
+ })
+ }
+
+ handleMonitorLevel(event: any, channelIndex: number) {
+ window.socketIoClient.emit(SOCKET_SET_AUX_LEVEL, {
+ channel: channelIndex,
+ auxIndex: this.props.auxSendIndex,
+ level: parseFloat(event),
+ })
+ }
+
+ inputSelectorButton(index: number) {
+ const isActive =
+ this.props.fader[this.props.faderIndex].inputSelector === index + 1
+ return (
+
+ )
+ }
+
+ inputSelector() {
+ return (
+
+ {window.mixerProtocol.channelTypes[0].toMixer
+ .CHANNEL_INPUT_SELECTOR ? (
+
+ {window.mixerProtocol.channelTypes[0].toMixer.CHANNEL_INPUT_SELECTOR.map(
+ (none: any, index: number) => {
+ return this.inputSelectorButton(index)
+ }
+ )}
+
+ ) : null}
+
+ )
+ }
+
+ inputGain() {
+ let maxLabel: number =
+ window.mixerProtocol.channelTypes[0].fromMixer
+ .CHANNEL_INPUT_GAIN?.[0].maxLabel ?? 1
+ let minLabel =
+ window.mixerProtocol.channelTypes[0].fromMixer
+ .CHANNEL_INPUT_GAIN?.[0].minLabel ?? 0
+ return (
+
+ Gain
+
{maxLabel + ' dB'}
+ {window.mixerProtocol.channelTypes[0].toMixer
+ .CHANNEL_INPUT_GAIN ? (
+
+ {
+ this.handleInputGain(event)
+ }}
+ />
+
+ ) : null}
+
{minLabel + ' dB'}
+
+ )
+ }
+
+ threshold() {
+ let maxLabel: number =
+ window.mixerProtocol.channelTypes[0].fromMixer.THRESHOLD?.[0]
+ .maxLabel ?? 1
+ let minLabel =
+ window.mixerProtocol.channelTypes[0].fromMixer.THRESHOLD?.[0]
+ .minLabel ?? 0
+ return (
+
+ Threshold
+
{maxLabel + ' dB'}
+
(
+
+ {Math.round(
+ (maxLabel - minLabel) *
+ parseFloat(state.valueNow) +
+ minLabel
+ )}
+ dB
+
+ )}
+ onChange={(event: any) => {
+ this.handleThreshold(event)
+ }}
+ />
+ {minLabel + ' dB'}
+
+ )
+ }
+
+ ratio() {
+ let maxLabel: number =
+ window.mixerProtocol.channelTypes[0].fromMixer.RATIO?.[0]
+ .maxLabel ?? 1
+ let minLabel =
+ window.mixerProtocol.channelTypes[0].fromMixer.RATIO?.[0]
+ .minLabel ?? 0
+ return (
+
+ Ratio
+
{maxLabel + ':1'}
+
(
+
+ {Math.round(
+ (maxLabel - minLabel) *
+ parseFloat(state.valueNow) +
+ minLabel
+ ) + ':1'}
+
+ )}
+ onChange={(event: any) => {
+ this.handleRatio(event)
+ }}
+ />
+ {minLabel + ':1'}
+
+ )
+ }
+
+ gainReduction() {
+ return (
+
+ Redution
+
+
+ )
+ }
+ delay() {
+ let maxLabel: number =
+ window.mixerProtocol.channelTypes[0].fromMixer.DELAY_TIME?.[0]
+ .maxLabel ?? 1
+ let minLabel =
+ window.mixerProtocol.channelTypes[0].fromMixer.DELAY_TIME?.[0]
+ .minLabel ?? 0
+ return (
+
+
+ Time
+
+ {maxLabel + ' ms'}
+
+
(
+
+ {Math.round(
+ (maxLabel - minLabel) *
+ parseFloat(state.valueNow) +
+ minLabel
+ )}
+ ms
+
+ )}
+ onChange={(event: any) => {
+ this.handleDelay(event)
+ }}
+ />
+
+ {minLabel + ' ms'}
+
+
+
+
+
+
+
+
+
+ )
+ }
+
+ eqGain(fxParam: fxParamsList) {
+ let maxLabel: number =
+ window.mixerProtocol.channelTypes[0].fromMixer.FX_PARAMS?.[fxParam]
+ .params[0].maxLabel ?? 1
+ let minLabel =
+ window.mixerProtocol.channelTypes[0].fromMixer.FX_PARAMS?.[fxParam]
+ .params[0].minLabel ?? 0
+ return (
+
+ {window.mixerProtocol.channelTypes[0].fromMixer.FX_PARAMS?.[
+ fxParam
+ ].params[0].label ?? 'ERR'}
+
{maxLabel + ' dB'}
+
(
+
+ {Math.round(
+ (maxLabel - minLabel) *
+ parseFloat(state.valueNow) +
+ minLabel
+ )}
+ dB
+
+ )}
+ onChange={(event: any) => {
+ this.handleFx(fxParam, event)
+ }}
+ />
+ {minLabel + ' dB'}
+
+ )
+ }
+
+ monitor(channelIndex: number) {
+ let faderIndex = this.props.channel[channelIndex].assignedFader
+ if (faderIndex === -1) return null
+ let monitorName = this.props.fader[faderIndex]
+ ? this.props.fader[faderIndex].label
+ : ''
+ if (monitorName === '') {
+ monitorName =
+ 'Fader ' +
+ String(this.props.channel[channelIndex].assignedFader + 1)
+ }
+ return (
+
+ {monitorName}
+ {
+ this.handleMonitorLevel(event, channelIndex)
+ }}
+ />
+ _______
+
+ )
+ }
+ parameters() {
+ if (this.props.offtubeMode) {
+ const hasInput =
+ window.mixerProtocol.channelTypes[0].toMixer
+ .CHANNEL_INPUT_GAIN ||
+ window.mixerProtocol.channelTypes[0].toMixer
+ .CHANNEL_INPUT_SELECTOR
+ const hasComp =
+ window.mixerProtocol.channelTypes[0].toMixer.THRESHOLD ||
+ window.mixerProtocol.channelTypes[0].toMixer.DELAY_TIME
+ const hasDelay =
+ window.mixerProtocol.channelTypes[0].toMixer.DELAY_TIME
+ const hasEq =
+ window.mixerProtocol.channelTypes[0].toMixer.FX_PARAMS?.[
+ fxParamsList.EqLowGain
+ ] ||
+ window.mixerProtocol.channelTypes[0].toMixer.FX_PARAMS?.[
+ fxParamsList.EqLowMidGain
+ ] ||
+ window.mixerProtocol.channelTypes[0].toMixer.FX_PARAMS?.[
+ fxParamsList.EqMidGain
+ ] ||
+ window.mixerProtocol.channelTypes[0].toMixer.FX_PARAMS?.[
+ fxParamsList.EqHighGain
+ ]
+ const hasMonitorSends = this.props.channel.find(
+ (ch: any) => ch.auxLevel[this.props.auxSendIndex] >= 0
+ )
+ return (
+
+
+ {hasInput && (
+
+
+
INPUT
+
+ {this.inputSelector()}
+ {this.inputGain()}
+
+
+
+ )}
+ {hasComp && (
+
+
+
COMPRESSOR
+
+ {this.threshold()}
+
______
+ {this.ratio()}
+
______
+ {this.gainReduction()}
+
+
+
+ )}
+ {hasDelay && (
+
+
+
DELAY
+
+ {this.delay()}
+
+
+
+ )}
+
+
+ {hasEq && (
+
+
+
+
+
EQUALIZER
+
+
+ {window.mixerProtocol
+ .channelTypes[0].toMixer
+ .FX_PARAMS?.[
+ fxParamsList.EqLowGain
+ ] ? (
+
+ {this.eqGain(
+ fxParamsList.EqLowGain
+ )}
+
+ _______
+
+
+ ) : null}
+ {window.mixerProtocol
+ .channelTypes[0].toMixer
+ .FX_PARAMS?.[
+ fxParamsList.EqLowMidGain
+ ] ? (
+
+ {this.eqGain(
+ fxParamsList.EqLowMidGain
+ )}
+
+ _______
+
+
+ ) : null}
+ {window.mixerProtocol
+ .channelTypes[0].toMixer
+ .FX_PARAMS?.[
+ fxParamsList.EqMidGain
+ ] ? (
+
+ {this.eqGain(
+ fxParamsList.EqMidGain
+ )}
+
+ _______
+
+
+ ) : null}
+ {window.mixerProtocol
+ .channelTypes[0].toMixer
+ .FX_PARAMS?.[
+ fxParamsList.EqHighGain
+ ] ? (
+
+ {this.eqGain(
+ fxParamsList.EqHighGain
+ )}
+
+ _______
+
+
+ ) : null}
+
+
+
+
+
+ )}
+
+ {hasMonitorSends && (
+
+
+
+ {this.props.label ||
+ 'FADER ' + (this.props.faderIndex + 1)}
+ {' - MONITOR MIX MINUS'}
+
+
+ {this.props.channel.map(
+ (ch: any, index: number) => {
+ if (
+ ch.auxLevel[
+ this.props.auxSendIndex
+ ] >= 0
+ ) {
+ return this.monitor(index)
+ }
+ }
+ )}
+
+
+ )}
+
+ )
+ } else {
+ return null
+ }
+ }
+
+ render() {
+ if (this.props.faderIndex >= 0) {
+ return (
+
+
+ {this.props.label ||
+ 'FADER ' + (this.props.faderIndex + 1)}
+
+ {window.location.search.includes(
+ 'settings=0'
+ ) ? null : (
+
+ )}
+ {window.location.search.includes(
+ 'settings=0'
+ ) ? null : (
+
+ )}
+
+
+ {this.props.selectedProtocol.includes('caspar') ? (
+
+ ) : (
+ this.parameters()
+ )}
+
+ )
+ } else {
+ return
+ }
+ }
+}
+
+const mapStateToProps = (state: any, props: any): IChanStripFullInjectProps => {
+ let inject: IChanStripFullInjectProps = {
+ label: '',
+ selectedProtocol: state.settings[0].mixers[0].mixerProtocol,
+ numberOfChannelsInType:
+ state.settings[0].mixers[0].numberOfChannelsInType,
+ channel: state.channels[0].chConnection[0].channel,
+ fader: state.faders[0].fader,
+ auxSendIndex: -1,
+ offtubeMode: state.settings[0].offtubeMode,
+ }
+ if (props.faderIndex >= 0) {
+ inject = {
+ label: state.faders[0].fader[props.faderIndex].label,
+ selectedProtocol: state.settings[0].mixers[0].mixerProtocol,
+ numberOfChannelsInType:
+ state.settings[0].mixers[0].numberOfChannelsInType,
+ channel: state.channels[0].chConnection[0].channel,
+ fader: state.faders[0].fader,
+ auxSendIndex: state.faders[0].fader[props.faderIndex].monitor - 1,
+ offtubeMode: state.settings[0].offtubeMode,
+ }
+ }
+ return inject
+}
+
+export default connect(mapStateToProps)(
+ ChanStripFull
+) as any