({
start: 0.0,
loopEnable: false,
loopStart: 0.0,
loopEnd: 0.0
});
const [size] = useWindowSize();
const width = size.width;
const height = size.height;
const HORIZONTAL_CONTROL_SCROLL_HEIGHT_BREAK = 500;
const useHorizontalLayout = height < HORIZONTAL_CONTROL_SCROLL_HEIGHT_BREAK && width > 573 && width > height;
//const useVerticalScroll = width < 573;
const noBorders = width < 420 || height < 720;
let useQuadMixPanel = width < 720;
if (noBorders) {
useQuadMixPanel = width < 370;
}
function SelectFile() {
setShowFileDialog(true);
}
function onAudioFileChanged(path: string) {
setAudioFile(path);
if (path === "") {
setTitle("");
setAlbum("");
setArtist("");
setAlbumArtist("");
setCoverArt(defaultCoverArt);
return;
}
model.getAudioFileMetadata(path)
.then((metadata) => {
let strTrack: string = "";
if (metadata.track > 0) {
let disc = (metadata.track / 1000);
if (disc >= 1) {
strTrack = (metadata.track % 1000).toString() + '/' + Math.floor(disc).toString();
} else {
strTrack = metadata.track.toString();
}
strTrack += ". ";
}
let coverArtUri = getAlbumArtUri(model, metadata, path);
setCoverArt(coverArtUri);
setTitle(strTrack + metadata.title);
setAlbum(metadata.album);
setArtist(metadata.artist);
setAlbumArtist(metadata.albumArtist);
})
.catch((e) => {
setTitle("#error" + e.message);
setAlbum("");
});
}
function ControlCluster() {
return (
({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
mt: -1,
'& svg': {
color: '#000',
...theme.applyStyles('dark', {
color: '#fff',
}),
},
})}
>
{
if (position > start + 3.0) {
model.sendPedalboardControlTrigger(
props.instanceId,
"stop",
1
);
} else {
onPreviousTrack();
}
}}
>
{
if (pluginState != PluginState.Idle) {
if (paused) {
model.sendPedalboardControlTrigger(
props.instanceId,
"play",
1
);
} else {
model.sendPedalboardControlTrigger(
props.instanceId,
"pause",
1
);
}
}
}}
>
{paused ? (
) : (
)}
{ onNextTrack(); }}
>
);
}
function FilePanel() {
return (
{ SelectFile() }}
>
{
e.preventDefault();
}}
alt="Cover Art"
src={
coverArt
}
/>
{pluginState === PluginState.Idle ? (
Tap to select
) : (
{titleLine}
{albumLine}
)}
);
}
function loopButtonText() {
if (start === 0 && !loopEnable) {
return "Set loop";
} else if (loopEnable) {
return `${formatTimeCompact(timebase, sampleRate, start)} [${formatTimeCompact(timebase, sampleRate, loopStart)} - ${formatTimeCompact(timebase, sampleRate, loopEnd)}]`;
} else {
return `Start: ${formatTimeCompact(timebase, sampleRate, start)}`;
}
}
function getUiFileProperty(uri: string): UiFileProperty {
let pedalboardItem = model.pedalboard.get().getItem(props.instanceId);
let uiPlugin = model.getUiPlugin(pedalboardItem.uri);
if (!uiPlugin) {
throw "uiPlugin not found.";
}
for (let property of uiPlugin.fileProperties) {
if (property.patchProperty === uri) {
return property;
}
}
throw "FileProperty not found.";
}
function onLoopPropertyChanged(loopSettingsJson: string) {
try {
let atomObject = JSON.parse(loopSettingsJson);
let loopParameters: LoopParameters = atomObject.loopParameters as LoopParameters;
let newTimebase: Timebase | undefined = atomObject.timebase as (Timebase | undefined);;
if (newTimebase !== undefined) {
if (!timebaseEqual(timebase, newTimebase)) {
setTimebase(newTimebase);
}
setLoopParameters(loopParameters);
setLoopEnable(loopParameters.loopEnable);
setStart(loopParameters.start);
setLoopStart(loopParameters.loopStart);
setLoopEnd(loopParameters.loopEnd);
} else {
throw new Error("Invalid loop settings.");
}
} catch (e) {
console.warn("Unable to parse loop settings.");
setTimebase(
{
units: TimebaseUnits.Seconds,
tempo: 120.0,
timeSignature: { numerator: 4, denominator: 4 }
})
setLoopEnable(false);
setStart(0.0);
setLoopStart(0.0);
setLoopEnd(0.0);
}
}
function onNextTrack() {
model.getNextAudioFile(audioFile)
.then((file) => {
let json = JsonAtom.Path(file);
model.setPatchProperty(
props.instanceId,
AUDIO_FILE_PROPERTY_URI,
json);
})
.catch(() => {
});
}
function onPreviousTrack() {
model.getPreviousAudioFile(audioFile)
.then((file) => {
let json = JsonAtom.Path(file);
model.setPatchProperty(
props.instanceId,
AUDIO_FILE_PROPERTY_URI,
json);
})
.catch(() => {
});
}
function OnSeek(value: number) {
model.setPatchProperty(props.instanceId, Player__seek, value)
.then(() => {
}).catch((e) => {
console.warn("Seek error. " + e.toString());
});
}
function onStateChanged(value: State) {
setServerConnected(value === State.Ready);
}
useEffect(() => {
model.state.addOnChangedHandler(onStateChanged);
if (model.state.get() !== State.Ready) {
// wait for it.
return () => {
model.state.removeOnChangedHandler(onStateChanged);
}
}
let durationHandle = model.monitorPort(props.instanceId, "duration", 1.0 / 15,
(value) => {
setDuration(value);
}
);
let positionHandle = model.monitorPort(props.instanceId, "position", 1.0,
(value) => {
setPosition(value);
}
);
let pluginStateHandle = model.monitorPort(props.instanceId, "state", 1.0 / 1000.0,
(value) => {
setPluginState(value);
}
);
let filePropertyHandle = model.monitorPatchProperty(
props.instanceId,
AUDIO_FILE_PROPERTY_URI,
(instanceId: number, propertyUri: string, atomObject: any) => {
if (typeof (atomObject) === "object") {
let path = atomObject.value;
onAudioFileChanged(path);
} else if (typeof (atomObject) === "string") {
onAudioFileChanged(atomObject as string);
}
}
);
let loopPropertyHandle = model.monitorPatchProperty(
props.instanceId,
LOOP_PROPERTY_URI,
(instanceId: number, propertyUri: string, atomObject: any) => {
if (typeof (atomObject) === "string") {
onLoopPropertyChanged(atomObject as string);
}
}
);
model.getPatchProperty(props.instanceId, AUDIO_FILE_PROPERTY_URI)
.then((o) => {
let path = o.value;
onAudioFileChanged(path);
});
model.getPatchProperty(props.instanceId, LOOP_PROPERTY_URI)
.then((o) => {
onLoopPropertyChanged(o as string);
})
return () => {
model.state.removeOnChangedHandler(onStateChanged);
model.unmonitorPort(durationHandle);
model.unmonitorPort(pluginStateHandle);
model.unmonitorPort(positionHandle);
// model.unmonitorPort(loopEnableHandle);
// model.unmonitorPort(startHandle);
// model.unmonitorPort(loopStartHandle);
// model.unmonitorPort(loopEndHandle);
model.cancelMonitorPatchProperty(filePropertyHandle);
model.cancelMonitorPatchProperty(loopPropertyHandle);
};
},
[serverConnected]
);
const titleLine = title !== "" ? title : pathFileNameOnly(audioFile);
const albumLine = getAlbumLine(album, artist, albumArtist);
const paused = (pluginState === PluginState.Idle
|| pluginState === PluginState.CuePlayingThenPause
|| pluginState === PluginState.Paused
|| pluginState === PluginState.Error);
function handlePreview() {
if (paused) {
model.sendPedalboardControlTrigger(
props.instanceId,
"play",
1
);
} else {
model.sendPedalboardControlTrigger(
props.instanceId,
"stop",
1
);
}
}
function handleCancelPlaying() {
if (!paused) {
model.sendPedalboardControlTrigger(
props.instanceId,
"stop",
1
);
}
}
function LinearMixPanel() {
return (
{props.extraControls}
);
}
function QuadMixPanel() {
return (
{props.extraControls[0]}
{props.extraControls[1]}
{props.extraControls[2]}
{props.extraControls[3]}
);
}
function SliderCluster() {
return (
{
}}
onValueChanged={(value) => {
OnSeek(value);
}}
/>
{/**
*
sx={{
'& .MuiTouchRipple-root': {
},
'& .MuiTouchRipple-ripple': {
transform: 'scale(1.9) !important',
}
}}
*/}
)}
onClick={() => {
setShowLoopDialog(true);
}}
>
{loopButtonText()
}
);
}
function VerticalWidget() {
return (
{
FilePanel()
}
{SliderCluster()}
{
ControlCluster()
}
{useQuadMixPanel ? QuadMixPanel()
:
LinearMixPanel()
}
);
}
function HorizontalWidget() {
return (
{
ControlCluster()
}
{LinearMixPanel()}
);
}
return (
{useWallpaper && ()}
{
useHorizontalLayout ?
HorizontalWidget() : VerticalWidget()
}
{showLoopDialog && (
{ handlePreview(); }}
value={loopParameters}
onCancelPlaying= {()=> { handleCancelPlaying();}}
timebase={timebase}
onTimebaseChange={(newTimebase) => {
setTimebase(newTimebase);
// model.setPatchProperty(
// props.instanceId,
// "timebase",
// newTimebase
// );
}}
onClose={() => {
setShowLoopDialog(false);
}}
onSetLoop={(loop: LoopParameters) => {
let loopSettings = {
timebase: timebase,
loopParameters: loop
};
model.setPatchProperty(
props.instanceId,
LOOP_PROPERTY_URI,
JSON.stringify(loopSettings));
setStart(loop.start);
setLoopEnable(loop.loopEnable);
setLoopStart(loop.loopStart);
setLoopEnd(loop.loopEnd);
}}
duration={duration}
/>
)}
{showFileDialog && (
{
setShowFileDialog(false);
}}
onApply={(fileProperty, selectedFile) => {
model.setPatchProperty(
props.instanceId,
AUDIO_FILE_PROPERTY_URI,
JsonAtom.Path(selectedFile)
)
.then(() => {
})
.catch((error) => {
model.showAlert("Unable to complete the operation. " + error);
});
}}
onOk={(fileProperty, selectedFile) => {
model.setPatchProperty(
props.instanceId,
fileProperty.patchProperty,
JsonAtom.Path(selectedFile)
)
.then(() => {
})
.catch((error) => {
model.showAlert("Unable to complete the operation. " + error);
});
setShowFileDialog(false);
}
}
/>
)}
);
}