modified: src/app/component/Bus.tsx
modified: src/app/component/BusesList.tsx modified: src/app/component/Strip.tsx modified: src/app/page.tsx modified: src/utils/DetectMobile.ts
This commit is contained in:
parent
7a65c76757
commit
42ccd675b8
|
@ -1,18 +1,31 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { Button, ButtonGroup, Grid, Input, Slider, Stack } from "@mui/material";
|
import {
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
Grid,
|
||||||
|
Input,
|
||||||
|
Slider,
|
||||||
|
Stack,
|
||||||
|
TextField,
|
||||||
|
} from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
||||||
import { EventCounter } from "@/utils/EventCounter";
|
import { EventCounter } from "@/utils/EventCounter";
|
||||||
|
|
||||||
export interface BusProps {
|
export interface BusProps {
|
||||||
values?: Partial<BusState>;
|
values?: Partial<Omit<BusState, StateDefaultValueException>>;
|
||||||
|
showInputdB?: boolean;
|
||||||
|
name: string;
|
||||||
onChange: (event: BusEvent) => any;
|
onChange: (event: BusEvent) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StateDefaultValueException = "showInputdB";
|
||||||
|
|
||||||
export interface BusState {
|
export interface BusState {
|
||||||
gain: number;
|
gain: number;
|
||||||
muted: boolean;
|
muted: boolean;
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
|
showInputdB: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BusEvent = BusMuted | BusGainChanged | BusSelectToggle;
|
export type BusEvent = BusMuted | BusGainChanged | BusSelectToggle;
|
||||||
|
@ -32,26 +45,29 @@ export interface BusSelectToggle {
|
||||||
|
|
||||||
export class Bus extends React.Component<BusProps, BusState> {
|
export class Bus extends React.Component<BusProps, BusState> {
|
||||||
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
||||||
private defaultValues: BusState = {
|
private defaultValues: Omit<BusState, StateDefaultValueException> = {
|
||||||
gain: 0,
|
gain: 0,
|
||||||
selected: false,
|
selected: false,
|
||||||
muted: false,
|
muted: false,
|
||||||
};
|
};
|
||||||
constructor(props: BusProps) {
|
constructor(props: BusProps) {
|
||||||
super(props);
|
super(props);
|
||||||
const { values: initialValues } = props;
|
let { values: initialValues } = props;
|
||||||
const getValue = (name: keyof typeof this.defaultValues) => {
|
const getValue = (name: keyof typeof this.defaultValues) => {
|
||||||
if (initialValues === undefined) return this.defaultValues[name];
|
if (initialValues === undefined) return this.defaultValues[name];
|
||||||
return initialValues[name] !== undefined
|
return initialValues[name] !== undefined
|
||||||
? this.defaultValues[name]
|
? this.defaultValues[name]
|
||||||
: initialValues[name];
|
: initialValues[name];
|
||||||
};
|
};
|
||||||
this.state = Object.fromEntries(
|
this.state = {
|
||||||
|
...Object.fromEntries(
|
||||||
Object.entries(this.defaultValues).map(([name]) => [
|
Object.entries(this.defaultValues).map(([name]) => [
|
||||||
name,
|
name,
|
||||||
getValue(name as keyof typeof this.defaultValues) as any,
|
getValue(name as keyof typeof this.defaultValues) as any,
|
||||||
])
|
])
|
||||||
) as BusState;
|
),
|
||||||
|
showInputdB: props.showInputdB !== undefined ? props.showInputdB : true,
|
||||||
|
} as BusState;
|
||||||
this.eventCounter.on({
|
this.eventCounter.on({
|
||||||
callback: this.onResetDefaults.bind(this),
|
callback: this.onResetDefaults.bind(this),
|
||||||
count: 2,
|
count: 2,
|
||||||
|
@ -69,10 +85,8 @@ export class Bus extends React.Component<BusProps, BusState> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onGainChange(event: Event | React.ChangeEvent<HTMLInputElement>) {
|
onGainChange(event: Event | React.ChangeEvent<HTMLInputElement>) {
|
||||||
|
let changedGain = parseFloat((event.target as HTMLInputElement).value);
|
||||||
let changedGain =
|
if (changedGain > 12) changedGain = 12;
|
||||||
parseFloat((event.target as HTMLInputElement).value);
|
|
||||||
if(changedGain > 12) changedGain = 12
|
|
||||||
else if (changedGain < -60) changedGain = -60;
|
else if (changedGain < -60) changedGain = -60;
|
||||||
this.setState({
|
this.setState({
|
||||||
gain: changedGain,
|
gain: changedGain,
|
||||||
|
@ -117,20 +131,30 @@ export class Bus extends React.Component<BusProps, BusState> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack alignItems={"center"} direction={"row"} spacing={0}>
|
<Stack
|
||||||
<Input
|
alignItems={"center"}
|
||||||
inputProps={{
|
direction={"row"}
|
||||||
"aria-labelledby": "input-slider",
|
spacing={0}
|
||||||
itemType: "number",
|
sx={{ width: "inherit" }}
|
||||||
style:{padding: 0}
|
>
|
||||||
}}
|
{this.state.showInputdB && (
|
||||||
|
<TextField
|
||||||
|
// inputProps={{
|
||||||
|
// "aria-labelledby": "input-slider",
|
||||||
|
// itemType: "number",
|
||||||
|
// style:{padding: 0}
|
||||||
|
// }}
|
||||||
value={this.state.gain}
|
value={this.state.gain}
|
||||||
onWheel={(e) => this.onStripWheel(e)}
|
onWheel={(e) => this.onStripWheel(e)}
|
||||||
onClick={(e) => this.stopPropagation(e)}
|
onClick={(e) => this.stopPropagation(e)}
|
||||||
onChange={(e) => this.onGainChange(e as unknown as Event)}
|
onChange={(e) => this.onGainChange(e as unknown as Event)}
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ width: "50px" }}
|
label={this.props.name}
|
||||||
|
type="number"
|
||||||
|
variant="outlined"
|
||||||
|
sx={{ minWidth: "100px", maxWidth: "100px" }}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<Slider
|
<Slider
|
||||||
sx={{
|
sx={{
|
||||||
margin: "5px",
|
margin: "5px",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Stack, Theme, Typography, useTheme, withTheme } from "@mui/material";
|
import { Chip, Stack, Theme, Typography, useTheme, withTheme } from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Bus } from "./Bus";
|
import { Bus } from "./Bus";
|
||||||
import { range } from "@/utils/Range";
|
import { range } from "@/utils/Range";
|
||||||
|
@ -22,17 +22,16 @@ export class BusesList extends React.Component<BusesListProps, BusesListState> {
|
||||||
) {
|
) {
|
||||||
const [busId] = args;
|
const [busId] = args;
|
||||||
const isPhysical = busId < this.props.physical;
|
const isPhysical = busId < this.props.physical;
|
||||||
|
const name = `${isPhysical ? "A" : "B"}${
|
||||||
|
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
||||||
|
}`;
|
||||||
return (
|
return (
|
||||||
<React.Fragment
|
<Stack direction={"row"} sx={{width:"100%"}} alignItems={"center"}
|
||||||
key={`${isPhysical ? "A" : "B"}${
|
key={name}
|
||||||
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<Typography variant="caption">{`${isPhysical ? "A" : "B"}${
|
{/* <Chip variant="outlined" sx={{marginInlineEnd: "15px"}} label={name}/> */}
|
||||||
isPhysical ? busId + 1 : busId - this.props.physical + 1
|
<Bus name={name} onChange={console.log} />
|
||||||
}`}</Typography>
|
</Stack>
|
||||||
<Bus onChange={console.log} />
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
render(): React.ReactNode {
|
render(): React.ReactNode {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Input,
|
Input,
|
||||||
Slider,
|
Slider,
|
||||||
Stack,
|
Stack,
|
||||||
|
TextField,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
import { StripBusOutput, StripBusOutputEvent } from "./StripBusOutput";
|
||||||
|
@ -16,13 +17,17 @@ export interface StripProps {
|
||||||
physicalBuses: number;
|
physicalBuses: number;
|
||||||
virtualBuses: number;
|
virtualBuses: number;
|
||||||
values?: Partial<StripState>;
|
values?: Partial<StripState>;
|
||||||
|
showOutputdB?: boolean;
|
||||||
|
name: string;
|
||||||
onChange: (event: StripEvent) => any;
|
onChange: (event: StripEvent) => any;
|
||||||
}
|
}
|
||||||
|
type StateDefaultValueException = "showOutputdB";
|
||||||
|
|
||||||
export interface StripState {
|
export interface StripState {
|
||||||
gain: number;
|
gain: number;
|
||||||
outputBuses: boolean[];
|
outputBuses: boolean[];
|
||||||
muted: boolean;
|
muted: boolean;
|
||||||
|
showOutputdB: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StripEvent = StripBusOutputChanged | StripMuted | StripGainChanged;
|
export type StripEvent = StripBusOutputChanged | StripMuted | StripGainChanged;
|
||||||
|
@ -41,7 +46,7 @@ export interface StripMuted {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Strip extends React.Component<StripProps, StripState> {
|
export class Strip extends React.Component<StripProps, StripState> {
|
||||||
private defaultValues: StripState;
|
private defaultValues: Omit<StripState, StateDefaultValueException>;
|
||||||
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
private eventCounter = new EventCounter<"onSliderResetDefaults">();
|
||||||
constructor(props: StripProps) {
|
constructor(props: StripProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -59,12 +64,16 @@ export class Strip extends React.Component<StripProps, StripState> {
|
||||||
? this.defaultValues[name]
|
? this.defaultValues[name]
|
||||||
: initialValues[name];
|
: initialValues[name];
|
||||||
};
|
};
|
||||||
this.state = Object.fromEntries(
|
this.state = {
|
||||||
|
...(Object.fromEntries(
|
||||||
Object.entries(this.defaultValues).map(([name]) => [
|
Object.entries(this.defaultValues).map(([name]) => [
|
||||||
name,
|
name,
|
||||||
getValue(name as keyof typeof this.defaultValues) as any,
|
getValue(name as keyof typeof this.defaultValues) as any,
|
||||||
])
|
])
|
||||||
) as StripState;
|
) as Omit<StripState, StateDefaultValueException>),
|
||||||
|
showOutputdB:
|
||||||
|
props.showOutputdB !== undefined ? props.showOutputdB : true,
|
||||||
|
};
|
||||||
this.eventCounter.on({
|
this.eventCounter.on({
|
||||||
callback: this.onResetDefaults.bind(this),
|
callback: this.onResetDefaults.bind(this),
|
||||||
count: 2,
|
count: 2,
|
||||||
|
@ -135,18 +144,21 @@ export class Strip extends React.Component<StripProps, StripState> {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack direction={"row"}>
|
<Stack direction={"row"}>
|
||||||
<Stack alignItems={"center"} style={{ maxWidth: "min-content" }}>
|
<Stack alignItems={"center"} style={{ maxWidth: "70px" }}>
|
||||||
<Input
|
<TextField
|
||||||
inputProps={{
|
// inputProps={{
|
||||||
"aria-labelledby": "input-slider",
|
// "aria-labelledby": "input-slider",
|
||||||
itemType: "number",
|
// itemType: "number",
|
||||||
style: { padding: 0 },
|
// style: { padding: 0 },
|
||||||
}}
|
// }}
|
||||||
value={this.state.gain}
|
value={this.state.gain}
|
||||||
onWheel={(e) => this.onStripWheel(e)}
|
onWheel={(e) => this.onStripWheel(e)}
|
||||||
onClick={(e) => this.stopPropagation(e)}
|
onClick={(e) => this.stopPropagation(e)}
|
||||||
size="small"
|
size="small"
|
||||||
sx={{ marginInline: "5px" }}
|
type="number"
|
||||||
|
label={this.props.name}
|
||||||
|
// sx={{minWidth: "4em", maxWidth: "5em"}}
|
||||||
|
// fullWidth
|
||||||
/>
|
/>
|
||||||
<Slider
|
<Slider
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -171,7 +183,7 @@ export class Strip extends React.Component<StripProps, StripState> {
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack>
|
<Stack>
|
||||||
<ButtonGroup orientation="vertical" sx={{paddingInlineStart:"5px"}}>
|
<ButtonGroup orientation="vertical">
|
||||||
{[
|
{[
|
||||||
...Array(this.props.physicalBuses + this.props.virtualBuses),
|
...Array(this.props.physicalBuses + this.props.virtualBuses),
|
||||||
].map((_v, i) => (
|
].map((_v, i) => (
|
||||||
|
|
|
@ -26,7 +26,13 @@ function random(min: number, max: number, floor: boolean = true) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const theme = useMemo(() => createTheme({ palette: { mode: "dark",background:{default: "black"} } }), []);
|
const theme = useMemo(
|
||||||
|
() =>
|
||||||
|
createTheme({
|
||||||
|
palette: { mode: "dark", background: { default: "#000" } },
|
||||||
|
}),
|
||||||
|
[]
|
||||||
|
);
|
||||||
function onStripEvent(event: StripEvent) {
|
function onStripEvent(event: StripEvent) {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
}
|
}
|
||||||
|
@ -36,9 +42,7 @@ export default function Home() {
|
||||||
}, []);
|
}, []);
|
||||||
const [snackBarVisible, setSnackBarVisibility] = useState(false);
|
const [snackBarVisible, setSnackBarVisibility] = useState(false);
|
||||||
const breakPoints = useMemo(() => theme.breakpoints.values, []);
|
const breakPoints = useMemo(() => theme.breakpoints.values, []);
|
||||||
const [width, setWidth] = useState(
|
const [width, setWidth] = useState(1000);
|
||||||
1000
|
|
||||||
);
|
|
||||||
const eventCounter = useMemo(() => {
|
const eventCounter = useMemo(() => {
|
||||||
const eventCounter = new EventCounter<"emptySpaceClick">();
|
const eventCounter = new EventCounter<"emptySpaceClick">();
|
||||||
eventCounter.on({
|
eventCounter.on({
|
||||||
|
@ -93,6 +97,7 @@ export default function Home() {
|
||||||
const buses = { virtual: 3, physical: 5 };
|
const buses = { virtual: 3, physical: 5 };
|
||||||
const amountOfStrips = strips.physical + strips.virtual;
|
const amountOfStrips = strips.physical + strips.virtual;
|
||||||
const amountOfBuses = buses.physical + buses.virtual;
|
const amountOfBuses = buses.physical + buses.virtual;
|
||||||
|
const virtualInputNames = useMemo(() => ["VAIO", "AUX", "VAIO3"], []);
|
||||||
if (typeof document !== "undefined") {
|
if (typeof document !== "undefined") {
|
||||||
document.onclick = () => eventCounter.emit("emptySpaceClick");
|
document.onclick = () => eventCounter.emit("emptySpaceClick");
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
|
@ -129,35 +134,44 @@ export default function Home() {
|
||||||
display={"flex"}
|
display={"flex"}
|
||||||
alignItems={"center"}
|
alignItems={"center"}
|
||||||
justifyContent={"space-evenly"}
|
justifyContent={"space-evenly"}
|
||||||
columns={{ xs: 8, sm: 12, md: 16, lg: 12 }}
|
columns={{ xs: 8, sm: 12, md: 16, lg: 14 }}
|
||||||
>
|
|
||||||
{[...Array(amountOfStrips)].map((_v, stripId) => (
|
|
||||||
<React.Fragment
|
|
||||||
key={`${stripId < amountOfStrips ? "a" : "b"}${
|
|
||||||
stripId < amountOfStrips
|
|
||||||
? stripId + 1
|
|
||||||
: stripId + 1 - amountOfStrips
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
|
{[...Array(amountOfStrips)].map((_v, stripId) => {
|
||||||
|
const isPhysical = stripId < strips.physical;
|
||||||
|
const name = `${isPhysical ? "A" : "B"}${
|
||||||
|
isPhysical ? stripId + 1 : stripId + 1 - strips.physical
|
||||||
|
}`;
|
||||||
|
return (
|
||||||
|
<React.Fragment key={name}>
|
||||||
<Grid
|
<Grid
|
||||||
lgOffset={stripId === strips.physical ? 2 : 0}
|
lgOffset={stripId === strips.physical ? 2 : 0}
|
||||||
mdOffset={stripId === strips.physical ? 0.5 : 0}
|
mdOffset={stripId === strips.physical ? 0.8 : 0}
|
||||||
sx={{ minWidth: "fit-content" }}
|
sx={{ minWidth: "fit-content" }}
|
||||||
>
|
>
|
||||||
<Typography variant="overline">{`Strip #${
|
{/* <Typography variant="overline">{`Strip #${
|
||||||
stripId + 1
|
stripId + 1
|
||||||
}`}</Typography>
|
}`}</Typography> */}
|
||||||
<Strip
|
<Strip
|
||||||
onChange={(ev) => onStripEvent(ev)}
|
onChange={(ev) => onStripEvent(ev)}
|
||||||
physicalBuses={buses.physical}
|
physicalBuses={buses.physical}
|
||||||
virtualBuses={buses.virtual}
|
virtualBuses={buses.virtual}
|
||||||
|
name={
|
||||||
|
isPhysical
|
||||||
|
? `#${stripId + 1}`
|
||||||
|
: virtualInputNames[stripId - strips.physical]
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Typography variant="h5">Outputs</Typography>
|
<Typography variant="h5">Outputs</Typography>
|
||||||
<BusesList width={width} physical={buses.physical} virtual={buses.virtual} />
|
<BusesList
|
||||||
|
width={width}
|
||||||
|
physical={buses.physical}
|
||||||
|
virtual={buses.virtual}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
<Snackbar
|
<Snackbar
|
||||||
|
@ -172,7 +186,8 @@ export default function Home() {
|
||||||
<Typography variant={"button"} fontWeight={500}>
|
<Typography variant={"button"} fontWeight={500}>
|
||||||
Double {isItMobileDevice ? "tap" : "click"}
|
Double {isItMobileDevice ? "tap" : "click"}
|
||||||
</Typography>{" "}
|
</Typography>{" "}
|
||||||
on any gain slider to reset it's value to 0 dB<br/>
|
on any gain slider to reset it's value to 0 dB
|
||||||
|
<br />
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography component={"span"}>
|
<Typography component={"span"}>
|
||||||
<Typography variant={"button"} fontWeight={500}>
|
<Typography variant={"button"} fontWeight={500}>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export function isItMobile(userAgent: string) {
|
export function isItMobile(userAgent: string) {
|
||||||
return (
|
return (
|
||||||
|
userAgent.includes("Android") ||
|
||||||
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
||||||
userAgent
|
userAgent
|
||||||
) ||
|
) ||
|
||||||
|
|
Loading…
Reference in New Issue
Block a user