(null);
63 | const read = useRead();
64 |
65 | useRequestAnimationFrame(() => {
66 | const canvas = canvasRef.current;
67 | const rect = canvas?.getBoundingClientRect();
68 | const ctx = canvas?.getContext("2d");
69 | if (!ctx) return;
70 | canvas!.width = rect!.width;
71 | canvas!.height = rect!.height;
72 | const h = rect!.height;
73 | const hh = h * 0.5;
74 | drawValues(ctx, read("frequency"), "red", (val) => h - (val / 255) * h);
75 | drawValues(
76 | ctx,
77 | read("volume"),
78 | "lime",
79 | (val) => h - (hh + ((val - 127) / hh) * h),
80 | );
81 | });
82 |
83 | return (
84 |
85 |
86 |
87 | );
88 | }
89 |
90 | const Audio = () => {
91 | const {
92 | bpm: { count: bpm },
93 | server,
94 | } = useSelector((state: WebviewAppState) => state);
95 | const setBPM = useSetBPM();
96 |
97 | const [{ lastMeasure, measuresCount, seriesStart }, setState] =
98 | React.useState(defaultState);
99 | const serverURL = `http://${server.host}:${server.port}`;
100 |
101 | const newBPM = Math.round(
102 | 60000 / ((Date.now() - seriesStart) * (1 / measuresCount)),
103 | );
104 |
105 | const handleBPMClick = () => {
106 | const now = Date.now();
107 | if (now - lastMeasure > 2000) {
108 | setState({
109 | lastMeasure: now,
110 | measuresCount: 0,
111 | seriesStart: now,
112 | });
113 | return;
114 | }
115 |
116 | if (measuresCount > 2) {
117 | void setBPM(newBPM);
118 | }
119 |
120 | setState({
121 | lastMeasure: now,
122 | measuresCount: measuresCount + 1,
123 | seriesStart: seriesStart || now,
124 | });
125 | };
126 |
127 | return (
128 | <>
129 |
135 |
136 |
137 | {`BPM: ${bpm}`}
138 |
139 |
151 |
152 | >
153 | );
154 | };
155 |
156 | export default Audio;
157 |
--------------------------------------------------------------------------------
/src/webviews/components/ControlDisplay.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { useSelector } from "react-redux";
3 | import type { AppState } from "../../types";
4 |
5 | const ControlDisplay = () => {
6 | const info = useSelector((state: AppState) => ({
7 | ...state.server,
8 | ...state.stage,
9 | }));
10 | const src = `http://${info.host}:${info.port}/display/#control`;
11 | return (
12 |
18 | );
19 | };
20 |
21 | export default ControlDisplay;
22 |
--------------------------------------------------------------------------------
/src/webviews/components/Display.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import type { DisplayBase } from "../../types";
3 |
4 | export interface DisplayProps extends DisplayBase {}
5 |
6 | const Display = ({ id, width = 1, height = 1 }: DisplayProps) => (
7 |
11 | {id}
12 |
{`${width} x ${height}`}
13 |
14 | );
15 |
16 | export default Display;
17 |
--------------------------------------------------------------------------------
/src/webviews/components/DisplaysList.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { useSelector } from "react-redux";
3 | import type { WebviewAppState } from "../store";
4 |
5 | import Display from "./Display";
6 |
7 | const DisplaysList = () => {
8 | const {
9 | displays: items,
10 | host,
11 | port,
12 | } = useSelector(({ displays, server }: WebviewAppState) => ({
13 | displays,
14 | ...server,
15 | }));
16 |
17 | const displayURL = `http://${host}:${port}/display/`;
18 |
19 | return (
20 | <>
21 |
22 | {items.map((item) => (
23 |
24 | ))}
25 |
26 |
34 | >
35 | );
36 | };
37 |
38 | export default DisplaysList;
39 |
--------------------------------------------------------------------------------
/src/webviews/components/Providers.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import { Provider as StoreProvider } from "react-redux";
3 |
4 | import { type ComEventData, autoBind } from "../../utils/com";
5 | import store, { webviewStateToAppState, storeMessageHandlers } from "../store";
6 | import vscode from "../vscode";
7 |
8 | import { Provider as ComProvider } from "../contexts/ComContext";
9 | import { Provider as DataProvider } from "../contexts/DataContext";
10 |
11 | const Providers = ({
12 | children,
13 | name,
14 | withData = false,
15 | }: React.PropsWithChildren<{ name: string; withData?: boolean }>) => {
16 | const dataRef = React.useRef