feature/share-libs
tsx 216 lines 6.19 KB
Raw
1 "use client";
2
3 import {
4 TAURI_PLAYER_PAUSED,
5 TAURI_PLAYER_PLAY,
6 TAURI_PLAYER_RECORD,
7 TAURI_PLAYER_RECORD_STOP,
8 TAURI_PLAYER_RECORDING_LENGTH,
9 TAURI_PLAYER_RESUMED,
10 TAURI_PLAYER_SET_VOLUME,
11 TAURI_PLAYER_STOP,
12 } from "@/lib/tauri-handler";
13 import { invoke } from "@tauri-apps/api/tauri";
14 import { useState } from "react";
15 import { ControlButtons } from "./control-button";
16 import { AudioInfo } from "./audio-info";
17 import { AudioInfoMiddle } from "./audio-info-middle";
18 import { useLogger } from "@/lib/logger";
19 import { ModeDemucs } from "@/models/mode";
20
21 enum PlayerState {
22 STOPPED,
23 PLAYING,
24 PAUSED,
25 RECORDING
26 }
27
28 export interface PlayerVolume {
29 mode: ModeDemucs,
30 volume: string
31 }
32
33
34 export default function Player({
35 audioId,
36 userId,
37 }: {
38 audioId: string;
39 userId: number;
40 }) {
41 // Logger
42 const log = useLogger("Player");
43
44 // State and constants
45 const COUNTING_DOWN_NUMBER = 3;
46 const [isCountingCountdown, setIsCountingCountdown] = useState(false);
47 const [recordingLength, setRecordingLength] = useState<number>(0);
48 const [hideVolumeSliders, setHideVolumeSliders] = useState(false);
49 const [playerState, setPlayerState] = useState<PlayerState>(
50 PlayerState.STOPPED
51 );
52
53 // Player states
54 const [vocalsVolume, setVocalsVolume] = useState<string>("100");
55 const [drumsVolume, setDrumsVolume] = useState<string>("100");
56 const [bassVolume, setBassVolume] = useState<string>("100");
57 const [otherVolume, setOtherVolume] = useState<string>("100");
58
59 // Player functions
60 const onVolumeChange = (mode: ModeDemucs, value: string) => {
61 log.debug("onVolumeChange", mode, value);
62 switch (mode) {
63 case ModeDemucs.Vocals:
64 setVocalsVolume(value);
65 break;
66 case ModeDemucs.Drums:
67 setDrumsVolume(value);
68 break;
69 case ModeDemucs.Bass:
70 setBassVolume(value);
71 break;
72 case ModeDemucs.Other:
73 setOtherVolume(value);
74 break;
75 }
76 invoke(TAURI_PLAYER_SET_VOLUME, { mode: mode, volume: value });
77 };
78
79 const onFinishedRecording = () => {
80 log.debug("Recording finished");
81 //_toggleRecording()
82 };
83
84 const toggleRecording = async () => {
85 try {
86 // If we are playing playbacks, stop it before recording.
87 if (playerState === PlayerState.PLAYING) {
88 setPlayerState(PlayerState.STOPPED);
89 const result = await invoke(TAURI_PLAYER_STOP, {
90 audioId,
91 userId,
92 });
93 log.debug(TAURI_PLAYER_STOP, result);
94 }
95
96 // If we're already recording, we want to stop it and return.
97 if (playerState === PlayerState.RECORDING) {
98 stopRecording();
99 return;
100 }
101
102 // Otherwise, we're good to go.
103 // Get the length of the audio file.
104
105 let length: number = await invoke(TAURI_PLAYER_RECORDING_LENGTH, {
106 audioId,
107 userId,
108 });
109 log.debug(TAURI_PLAYER_RECORDING_LENGTH, length);
110 setRecordingLength(length);
111 setIsCountingCountdown(true);
112
113 setTimeout(async () => {
114 log.debug(TAURI_PLAYER_RECORD, "Start recording");
115 setPlayerState(PlayerState.RECORDING);
116 setIsCountingCountdown(false);
117 const result = await invoke(TAURI_PLAYER_RECORD, {
118 audioId,
119 userId,
120 playerVolumes: currentPlayerVolumes(),
121 });
122 log.debug(TAURI_PLAYER_RECORD, result);
123 }, COUNTING_DOWN_NUMBER * 1000);
124 } catch (error) {
125 log.error(error);
126 }
127 };
128
129 const stopRecording = async () => {
130 setRecordingLength(0);
131 setPlayerState(PlayerState.STOPPED);
132 const stop_recording_result = await invoke(TAURI_PLAYER_RECORD_STOP, {
133 audioId,
134 userId,
135 });
136 const result = await invoke(TAURI_PLAYER_STOP, {
137 audioId,
138 userId,
139 });
140 log.debug(TAURI_PLAYER_STOP, result);
141 log.debug(TAURI_PLAYER_RECORD_STOP, stop_recording_result);
142 };
143
144 const _stopPlayer = async () => {
145 try {
146 setPlayerState(PlayerState.STOPPED);
147 setRecordingLength(0);
148 const result = await invoke(TAURI_PLAYER_STOP, {
149 audioId,
150 userId,
151 });
152 log.debug(TAURI_PLAYER_STOP, result);
153 } catch (error) {
154 log.error(error);
155 }
156 };
157 const currentPlayerVolumes = (): PlayerVolume[] => {
158 return [
159 { mode: ModeDemucs.Vocals, volume: vocalsVolume },
160 { mode: ModeDemucs.Drums, volume: drumsVolume },
161 { mode: ModeDemucs.Bass, volume: bassVolume },
162 { mode: ModeDemucs.Other, volume: otherVolume },
163 ];
164 };
165
166 const togglePlayAudio = async () => {
167 // Should disabled when recording
168 if (playerState === PlayerState.RECORDING) {
169 return;
170 }
171 try {
172 switch (playerState) {
173 case PlayerState.STOPPED:
174 log.debug(TAURI_PLAYER_PLAY, "Start playing");
175 setIsCountingCountdown(true);
176 setTimeout(async () => {
177 setIsCountingCountdown(false);
178 setPlayerState(PlayerState.PLAYING);
179 await invoke(TAURI_PLAYER_PLAY, {
180 playerVolumes: currentPlayerVolumes(),
181 });
182 }, COUNTING_DOWN_NUMBER * 1000);
183 break;
184 case PlayerState.PLAYING:
185 log.debug(TAURI_PLAYER_PAUSED, "Paused");
186 setPlayerState(PlayerState.PAUSED);
187 await invoke(TAURI_PLAYER_PAUSED);
188 break;
189 case PlayerState.PAUSED:
190 log.debug(TAURI_PLAYER_RESUMED, "Resumed");
191 setPlayerState(PlayerState.PLAYING);
192 await invoke(TAURI_PLAYER_PLAY, { playerVolumes: currentPlayerVolumes() });
193 }
194 } catch (error) {
195 log.error(error);
196 }
197 };
198
199 return (
200 <>
201 <div className="bg-black border-slate-100 dark:bg-slate-800 dark:border-slate-500 border-b rounded-t-xl p-4 pb-6 sm:p-10 sm:pb-8 lg:p-6 xl:p-10 xl:pb-8 space-y-6 sm:space-y-8 lg:space-y-6 xl:space-y-8 items-center">
202 <AudioInfo />
203 <AudioInfoMiddle counterDownTimer={COUNTING_DOWN_NUMBER} />
204 <ControlButtons
205 isPlaying={playerState === PlayerState.PLAYING}
206 isRecording={playerState === PlayerState.RECORDING}
207 onClick={togglePlayAudio}
208 onStop={_stopPlayer}
209 onRecord={toggleRecording}
210 onResume={function (): void {
211 throw new Error("Function not implemented.");
212 } } />
213 </div>
214 </>
215 );
216 }