add midi tracks to webUI
This commit is contained in:
parent
9b7b651ef9
commit
e48f39375e
@ -18,7 +18,7 @@ import {
|
|||||||
} from '@fluentui/react-icons';
|
} from '@fluentui/react-icons';
|
||||||
import { Button, Card, DialogTrigger, Slider, Text, Tooltip } from '@fluentui/react-components';
|
import { Button, Card, DialogTrigger, Slider, Text, Tooltip } from '@fluentui/react-components';
|
||||||
import { useWindowSize } from 'usehooks-ts';
|
import { useWindowSize } from 'usehooks-ts';
|
||||||
import commonStore from '../../stores/commonStore';
|
import commonStore, { ModelStatus } from '../../stores/commonStore';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import {
|
import {
|
||||||
InstrumentType,
|
InstrumentType,
|
||||||
@ -420,6 +420,7 @@ const AudiotrackEditor: FC<{ setPrompt: (prompt: string) => void }> = observer((
|
|||||||
<div key={track.id} className="flex gap-2 pb-1 border-b">
|
<div key={track.id} className="flex gap-2 pb-1 border-b">
|
||||||
<div className="flex gap-1 border-r h-7">
|
<div className="flex gap-1 border-r h-7">
|
||||||
<ToolTipButton desc={commonStore.recordingTrackId === track.id ? t('Stop') : t('Record')}
|
<ToolTipButton desc={commonStore.recordingTrackId === track.id ? t('Stop') : t('Record')}
|
||||||
|
disabled={commonStore.platform === 'web'}
|
||||||
icon={commonStore.recordingTrackId === track.id ? <Stop16Filled /> : <Record16Regular />}
|
icon={commonStore.recordingTrackId === track.id ? <Stop16Filled /> : <Record16Regular />}
|
||||||
size="small" shape="circular" appearance="subtle"
|
size="small" shape="circular" appearance="subtle"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -481,6 +482,7 @@ const AudiotrackEditor: FC<{ setPrompt: (prompt: string) => void }> = observer((
|
|||||||
<div className="flex gap-1">
|
<div className="flex gap-1">
|
||||||
<Button icon={<Add16Regular />} size="small" shape="circular"
|
<Button icon={<Add16Regular />} size="small" shape="circular"
|
||||||
appearance="subtle"
|
appearance="subtle"
|
||||||
|
disabled={commonStore.platform === 'web'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
commonStore.setTracks([...commonStore.tracks, {
|
commonStore.setTracks([...commonStore.tracks, {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
@ -496,11 +498,20 @@ const AudiotrackEditor: FC<{ setPrompt: (prompt: string) => void }> = observer((
|
|||||||
<Button icon={<ArrowUpload16Regular />} size="small" shape="circular"
|
<Button icon={<ArrowUpload16Regular />} size="small" shape="circular"
|
||||||
appearance="subtle"
|
appearance="subtle"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (commonStore.status.status === ModelStatus.Offline && !commonStore.settings.apiUrl && commonStore.platform !== 'web') {
|
||||||
|
toast(t('Please click the button in the top right corner to start the model'), { type: 'warning' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OpenOpenFileDialog('*.mid').then(async filePath => {
|
OpenOpenFileDialog('*.mid').then(async filePath => {
|
||||||
if (!filePath)
|
if (!filePath)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const blob = await fetch(absPathAsset(filePath)).then(r => r.blob());
|
let blob: Blob;
|
||||||
|
if (commonStore.platform === 'web')
|
||||||
|
blob = (filePath as unknown as { blob: Blob }).blob;
|
||||||
|
else
|
||||||
|
blob = await fetch(absPathAsset(filePath)).then(r => r.blob());
|
||||||
const bodyForm = new FormData();
|
const bodyForm = new FormData();
|
||||||
bodyForm.append('file_data', blob);
|
bodyForm.append('file_data', blob);
|
||||||
fetch(getServerRoot(commonStore.getCurrentModelConfig().apiParameters.apiPort) + '/midi-to-text', {
|
fetch(getServerRoot(commonStore.getCurrentModelConfig().apiParameters.apiPort) + '/midi-to-text', {
|
||||||
|
@ -567,7 +567,7 @@ const ChatPanel: FC = observer(() => {
|
|||||||
const setUploading = () => commonStore.setAttachmentUploading(true);
|
const setUploading = () => commonStore.setAttachmentUploading(true);
|
||||||
// actually, status of web platform is always Offline
|
// actually, status of web platform is always Offline
|
||||||
if (commonStore.platform === 'web' || commonStore.status.status === ModelStatus.Offline || currentConfig.modelParameters.device === 'WebGPU') {
|
if (commonStore.platform === 'web' || commonStore.status.status === ModelStatus.Offline || currentConfig.modelParameters.device === 'WebGPU') {
|
||||||
webOpenOpenFileDialog({ filterPattern, fnStartLoading: setUploading }).then(webReturn => {
|
webOpenOpenFileDialog(filterPattern, setUploading).then(webReturn => {
|
||||||
if (webReturn.content)
|
if (webReturn.content)
|
||||||
commonStore.setCurrentTempAttachment(
|
commonStore.setCurrentTempAttachment(
|
||||||
{
|
{
|
||||||
|
@ -250,32 +250,36 @@ const CompositionPanel: FC = observer(() => {
|
|||||||
}} />
|
}} />
|
||||||
} />
|
} />
|
||||||
<div className="grow" />
|
<div className="grow" />
|
||||||
<Checkbox className="select-none"
|
{
|
||||||
size="large" label={t('Use Local Sound Font')} checked={params.useLocalSoundFont}
|
commonStore.platform !== 'web' &&
|
||||||
onChange={async (_, data) => {
|
<Checkbox className="select-none"
|
||||||
if (data.checked) {
|
size="large" label={t('Use Local Sound Font')} checked={params.useLocalSoundFont}
|
||||||
if (!await FileExists('assets/sound-font/accordion/instrument.json')) {
|
onChange={async (_, data) => {
|
||||||
toast(t('Failed to load local sound font, please check if the files exist - assets/sound-font'),
|
if (data.checked) {
|
||||||
{ type: 'warning' });
|
if (!await FileExists('assets/sound-font/accordion/instrument.json')) {
|
||||||
return;
|
toast(t('Failed to load local sound font, please check if the files exist - assets/sound-font'),
|
||||||
|
{ type: 'warning' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
setParams({
|
||||||
setParams({
|
useLocalSoundFont: data.checked as boolean
|
||||||
useLocalSoundFont: data.checked as boolean
|
});
|
||||||
});
|
setSoundFont();
|
||||||
setSoundFont();
|
}} />
|
||||||
}} />
|
}
|
||||||
<Checkbox className="select-none"
|
<Checkbox className="select-none"
|
||||||
size="large" label={t('Auto Play At The End')} checked={params.autoPlay} onChange={(_, data) => {
|
size="large" label={t('Auto Play At The End')} checked={params.autoPlay} onChange={(_, data) => {
|
||||||
setParams({
|
setParams({
|
||||||
autoPlay: data.checked as boolean
|
autoPlay: data.checked as boolean
|
||||||
});
|
});
|
||||||
}} />
|
}} />
|
||||||
{commonStore.platform !== 'web' &&
|
<Labeled flex breakline label={t('MIDI Input')}
|
||||||
<Labeled flex breakline label={t('MIDI Input')}
|
desc={t('Select the MIDI input device to be used.')}
|
||||||
desc={t('Select the MIDI input device to be used.')}
|
content={
|
||||||
content={
|
<div className="flex flex-col gap-1">
|
||||||
<div className="flex flex-col gap-1">
|
{
|
||||||
|
commonStore.platform !== 'web' &&
|
||||||
<Dropdown style={{ minWidth: 0 }}
|
<Dropdown style={{ minWidth: 0 }}
|
||||||
value={(commonStore.activeMidiDeviceIndex === -1 || !(commonStore.activeMidiDeviceIndex in commonStore.midiPorts))
|
value={(commonStore.activeMidiDeviceIndex === -1 || !(commonStore.activeMidiDeviceIndex in commonStore.midiPorts))
|
||||||
? t('None')!
|
? t('None')!
|
||||||
@ -299,10 +303,10 @@ const CompositionPanel: FC = observer(() => {
|
|||||||
<Option key={i} value={i.toString()}>{p.name}</Option>)
|
<Option key={i} value={i.toString()}>{p.name}</Option>)
|
||||||
}
|
}
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<AudiotrackButton setPrompt={setPrompt} />
|
}
|
||||||
</div>
|
<AudiotrackButton setPrompt={setPrompt} />
|
||||||
} />
|
</div>
|
||||||
}
|
} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between gap-2">
|
<div className="flex justify-between gap-2">
|
||||||
<ToolTipButton desc={t('Regenerate')} icon={<ArrowSync20Regular />} onClick={() => {
|
<ToolTipButton desc={t('Regenerate')} icon={<ArrowSync20Regular />} onClick={() => {
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { getDocument, GlobalWorkerOptions, PDFDocumentProxy } from 'pdfjs-dist';
|
import { getDocument, GlobalWorkerOptions, PDFDocumentProxy } from 'pdfjs-dist';
|
||||||
import { TextItem } from 'pdfjs-dist/types/src/display/api';
|
import { TextItem } from 'pdfjs-dist/types/src/display/api';
|
||||||
|
|
||||||
export function webOpenOpenFileDialog({ filterPattern, fnStartLoading }: { filterPattern: string, fnStartLoading: Function | null }): Promise<{ blob: Blob, content?: string }> {
|
export function webOpenOpenFileDialog(filterPattern: string, fnStartLoading: Function | undefined): Promise<{
|
||||||
|
blob: Blob,
|
||||||
|
content?: string
|
||||||
|
}> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.accept = filterPattern
|
input.accept = filterPattern
|
||||||
.replaceAll('*.txt', 'text/plain')
|
.replaceAll('*.txt', 'text/plain')
|
||||||
|
.replace('*.midi', 'audio/midi')
|
||||||
|
.replace('*.mid', 'audio/midi')
|
||||||
.replaceAll('*.', 'application/')
|
.replaceAll('*.', 'application/')
|
||||||
.replaceAll(';', ',');
|
.replaceAll(';', ',');
|
||||||
|
|
||||||
@ -15,7 +20,7 @@ export function webOpenOpenFileDialog({ filterPattern, fnStartLoading }: { filte
|
|||||||
const file: Blob = e.target?.files[0];
|
const file: Blob = e.target?.files[0];
|
||||||
if (fnStartLoading && typeof fnStartLoading === 'function')
|
if (fnStartLoading && typeof fnStartLoading === 'function')
|
||||||
fnStartLoading();
|
fnStartLoading();
|
||||||
if (!GlobalWorkerOptions.workerSrc)
|
if (!GlobalWorkerOptions.workerSrc && file.type === 'application/pdf')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
GlobalWorkerOptions.workerSrc = await import('pdfjs-dist/build/pdf.worker.min.mjs');
|
GlobalWorkerOptions.workerSrc = await import('pdfjs-dist/build/pdf.worker.min.mjs');
|
||||||
if (file.type === 'text/plain') {
|
if (file.type === 'text/plain') {
|
||||||
|
Loading…
Reference in New Issue
Block a user