mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
142 lines
5.0 KiB
TypeScript
142 lines
5.0 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import { OlStateButton } from "../../components/olstatebutton";
|
|
import { faPause, faPlay, faRepeat, faStop } from "@fortawesome/free-solid-svg-icons";
|
|
import { getApp } from "../../../olympusapp";
|
|
import { AudioSource } from "../../../audio/audiosource";
|
|
import { FaArrowRight, FaTrash, FaVolumeHigh } from "react-icons/fa6";
|
|
import { OlRangeSlider } from "../../components/olrangeslider";
|
|
import { FaUnlink } from "react-icons/fa";
|
|
import { OlDropdown, OlDropdownItem } from "../../components/oldropdown";
|
|
import { FileSource } from "../../../audio/filesource";
|
|
import { MicrophoneSource } from "../../../audio/microphonesource";
|
|
|
|
export function AudioSourcePanel(props: { source: AudioSource }) {
|
|
const [meterLevel, setMeterLevel] = useState(0);
|
|
|
|
useEffect(() => {
|
|
setInterval(() => {
|
|
setMeterLevel(props.source.getMeter().getPeaks().current[0]);
|
|
}, 50);
|
|
}, []);
|
|
|
|
let availabileSinks = getApp()
|
|
.getAudioManager()
|
|
.getSinks()
|
|
.filter((sink) => !props.source.getConnectedTo().includes(sink));
|
|
|
|
return (
|
|
<div
|
|
className={`
|
|
flex flex-col content-center justify-between gap-2 rounded-md
|
|
bg-olympus-200/30 py-3 pl-4 pr-5
|
|
`}
|
|
>
|
|
<div className="flex justify-between gap-2">
|
|
<span className="break-all">{props.source.getName()}</span>
|
|
{!(props.source instanceof MicrophoneSource) && (
|
|
<div
|
|
className={`
|
|
mb-auto aspect-square cursor-pointer rounded-md bg-red-800 p-2
|
|
`}
|
|
onClick={() => {
|
|
getApp().getAudioManager().removeSource(props.source);
|
|
}}
|
|
>
|
|
<FaTrash className={`text-gray-50`}></FaTrash>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-2 rounded-md bg-olympus-400 p-2">
|
|
{props.source instanceof FileSource && (
|
|
<div className="flex gap-4">
|
|
<OlStateButton
|
|
checked={false}
|
|
icon={props.source.getPlaying() ? faPause : faPlay}
|
|
onClick={() => {
|
|
if (props.source instanceof FileSource) props.source.getPlaying() ? props.source.stop() : props.source.play();
|
|
}}
|
|
tooltip="Play file"
|
|
></OlStateButton>
|
|
<OlRangeSlider
|
|
value={props.source.getDuration() > 0 ? (props.source.getCurrentPosition() / props.source.getDuration()) * 100 : 0}
|
|
onChange={(ev) => {
|
|
if (props.source instanceof FileSource) props.source.setCurrentPosition(parseFloat(ev.currentTarget.value));
|
|
}}
|
|
className="my-auto"
|
|
/>
|
|
<OlStateButton
|
|
checked={props.source.getLooping()}
|
|
icon={faRepeat}
|
|
onClick={() => {
|
|
if (props.source instanceof FileSource) props.source.setLooping(!props.source.getLooping());
|
|
}}
|
|
tooltip="Loop"
|
|
></OlStateButton>
|
|
</div>
|
|
)}
|
|
<div className="flex gap-4">
|
|
<div className="h-[40px] min-w-[40px] p-2">
|
|
<FaVolumeHigh className="h-full w-full" />
|
|
</div>
|
|
<div className="relative flex w-full flex-col gap-3">
|
|
<div
|
|
className={`
|
|
absolute top-[18px] flex h-2 min-w-full translate-y-[-5px]
|
|
flex-row border-gray-500
|
|
`}
|
|
>
|
|
<div style={{ minWidth: `${meterLevel * 100}%` }} className={`
|
|
rounded-full bg-gray-200
|
|
`}></div>
|
|
</div>
|
|
<OlRangeSlider
|
|
value={props.source.getVolume() * 100}
|
|
onChange={(ev) => {
|
|
props.source.setVolume(parseFloat(ev.currentTarget.value) / 100);
|
|
}}
|
|
className="absolute top-[18px]"
|
|
/>
|
|
</div>
|
|
<div className="h-[40px] min-w-[40px] p-2">
|
|
<span>{Math.round(props.source.getVolume() * 100)}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<span className="text-sm">Connected to:</span>
|
|
<div className="flex flex-col gap-1">
|
|
{props.source.getConnectedTo().map((sink) => {
|
|
return (
|
|
<div
|
|
className={`
|
|
flex justify-start gap-2 rounded-full bg-olympus-400 px-4 py-1
|
|
text-sm
|
|
`}
|
|
>
|
|
<FaArrowRight className="my-auto"></FaArrowRight>
|
|
{sink.getName()}
|
|
<FaUnlink className="my-auto ml-auto cursor-pointer text-red-400" onClick={() => props.source.disconnect(sink)}></FaUnlink>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
{availabileSinks.length > 0 && (
|
|
<OlDropdown label="Connect to:">
|
|
{availabileSinks.map((sink) => {
|
|
return (
|
|
<OlDropdownItem
|
|
onClick={() => {
|
|
props.source.connect(sink);
|
|
}}
|
|
>
|
|
{sink.getName()}
|
|
</OlDropdownItem>
|
|
);
|
|
})}
|
|
</OlDropdown>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|