Voicemeeter-remote-frontend/src/app/component/Bus.tsx

241 lines
6.6 KiB
TypeScript
Raw Normal View History

2024-07-22 01:41:17 +02:00
"use client";
import {
Button,
ButtonGroup,
Grid,
Input,
Slider,
Stack,
styled,
TextField,
Typography,
} from "@mui/material";
2024-07-22 01:41:17 +02:00
import React from "react";
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
import { EventCounter } from "@/utils/EventCounter";
import { getComponentState } from "@/utils/GetComponentState";
import { stopPropagation } from "@/utils/StopPropagation";
2024-07-22 01:41:17 +02:00
export interface BusProps {
values?: Partial<Omit<BusState, StateDefaultValueException>>;
width: number;
name: string;
onChange: (event: BusEvent) => any;
2024-07-22 01:41:17 +02:00
}
type StateDefaultValueException = "";
export interface BusState {
2024-07-22 01:41:17 +02:00
muted: boolean;
selected: boolean;
gain: number;
2024-07-22 01:41:17 +02:00
}
export type BusEvent = BusMuted | BusGainChanged | BusSelectToggle;
2024-07-22 01:41:17 +02:00
export interface BusGainChanged {
type: "BusGainChanged";
2024-07-22 01:41:17 +02:00
gain: number;
}
export interface BusMuted {
type: "BusMuted";
2024-07-22 01:41:17 +02:00
muted: boolean;
}
export interface BusSelectToggle {
type: "BusSelectToggle";
selected: boolean;
}
2024-07-22 01:41:17 +02:00
export class Bus extends React.Component<BusProps, BusState> {
private defaultValues: Omit<BusState, StateDefaultValueException> = {
selected: false,
muted: false,
gain: 0,
};
private eventCounter = new EventCounter<"onSliderResetDefaults">();
constructor(props: BusProps) {
2024-07-22 01:41:17 +02:00
super(props);
let { values: initialValues } = props;
this.state = getComponentState<BusState, "">(
props.values,
this.defaultValues
);
this.eventCounter.on({
callback: this.onResetDefaults.bind(this),
count: 2,
name: "onSliderResetDefaults",
});
2024-07-22 01:41:17 +02:00
}
onKeyDown(event: React.KeyboardEvent) {
console.log(event);
2024-07-22 01:41:17 +02:00
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
event.preventDefault();
}
}
_setGain(gain: number) {
this.setState({
gain,
});
this.props.onChange({
type: "BusGainChanged",
gain,
});
}
onResetDefaults() {
this._setGain(this.defaultValues.gain);
}
onGainSliderChange(event: Event) {
stopPropagation(event);
const multiplier = (event as unknown as React.KeyboardEvent).shiftKey
? 2
: 1;
const changedGain =
parseFloat((event.target as HTMLInputElement).value) * multiplier;
this._setGain(changedGain);
}
onMuteToggle(event: React.MouseEvent) {
stopPropagation(event);
2024-07-22 01:41:17 +02:00
this.setState(
(state) => ({ muted: !state.muted }),
() => {
this.props.onChange({ type: "BusMuted", muted: this.state.muted });
2024-07-22 01:41:17 +02:00
}
);
}
onSliderClick(event: React.MouseEvent) {
stopPropagation(event);
this.eventCounter.emit("onSliderResetDefaults");
}
onSelectToggle(event: React.MouseEvent) {
stopPropagation(event);
this.setState(
(state) => ({ selected: !state.selected }),
() => {
this.props.onChange({
type: "BusSelectToggle",
selected: this.state.selected,
});
}
);
}
2024-07-22 01:41:17 +02:00
render() {
return (
<>
<Stack
alignItems={"center"}
direction={"row"}
spacing={0}
sx={{ width: "inherit" }}
>
{/* {this.props.width > 600 ? (
// <TextField
// inputProps={{
// "aria-labelledby": "input-slider",
// itemType: "number",
// style:{padding: 0}
// }}
// value={Bus.percentToGain(this.state.gainPercent).toFixed(1)}
// onWheel={(e) => this.onStripWheel(e)}
// onClick={(e) => this.stopPropagation(e)}
// onChange={(e) => {
// e.target.value = Bus.gainToPercent(
// parseInt(e.target.value)
// ).toFixed(0);
// this.onGainSliderChange(e as unknown as Event);
// }}
// size="small"
// label={this.props.name}
// type="number"
// variant="outlined"
// sx={{
// minWidth: "100px",
// maxWidth: "100px",
// height: "",
// marginBlockEnd: "8px",
// }}
// />
) : (
<Typography variant="caption">{this.props.name}</Typography>
)} */}
{/* {this.props.width <= 600 && (
<Typography
position={"absolute"}
paddingInlineStart={"10rem"}
paddingBlockEnd={"2rem"}
fontSize={"0.6rem"}
width={"fit-content"}
variant="caption"
>
{this.state.gain}dB
</Typography>
)} */}
<Slider
valueLabelDisplay={this.props.width > 600 ? "off" : "auto"}
value={this.state.gain}
color={
this.state.gain > 0 && this.state.gain < 12
? "warning"
: this.state.gain <= 0
? "primary"
: "error"
}
min={-60}
max={12}
step={0.1}
slotProps={{
root: {
onClick: (e) => this.onSliderClick(e),
},
}}
onChange={(e) => this.onGainSliderChange(e)}
/>
2024-07-22 01:41:17 +02:00
<ButtonGroup>
<Button
onClick={(e) => this.onMuteToggle(e)}
variant={this.state.muted ? "contained" : "outlined"}
color={"error"}
>
Mute
</Button>
<Button
onClick={(e) => this.onSelectToggle(e)}
sx={{}}
variant={this.state.selected ? "contained" : "outlined"}
color={"warning"}
>
S
</Button>
</ButtonGroup>
</Stack>
{/* <Stack>
2024-07-22 01:41:17 +02:00
<ButtonGroup orientation="vertical">
{[
...Array(this.props.physicalBuses + this.props.virtualBuses),
].map((_v, i) => (
<StripBusOutput
key={`${i < this.props.physicalBuses ? "a" : "b"}${
i < this.props.physicalBuses
? i
: i - this.props.physicalBuses
}`}
id={
i < this.props.physicalBuses
? i
: i - this.props.physicalBuses
}
isVirtual={i < this.props.physicalBuses ? false : true}
onChange={(ev) => this.onBusChange(ev)}
default={{ enabled: this.state.buses[i] }}
/>
))}
</ButtonGroup>
</Stack> */}
2024-07-22 01:41:17 +02:00
</>
);
}
}