from pathlib import Path from contextlib import contextmanager from asyncio import sleep from tempfile import TemporaryDirectory from datetime import date from nicegui import ui, run _recording = None @contextmanager def _disable(button: ui.button): button.disable() try: yield finally: button.enable() async def _stopRecording(recordButton, uploadButton, recorder, wavFile): with _disable(recordButton): global _recording _recording = recorder.stopRecording() await run.cpu_bound(_recording.writeWav, wavFile) uploadButton.enable() def _makeRecordCallback(playButton, recordButton, uploadButton, soloTool, recorder, wavFile): async def f(): if recorder.recording: await _stopRecording(recordButton, uploadButton, recorder, wavFile) else: if soloTool.playingAdHoc: soloTool.backToNormal() uploadButton.disable() recorder.startRecording() playButton.enable() return f def _makePlayCallback(playButton, recordButton, uploadButton, soloTool, recorder, wavFile): async def f(): with _disable(playButton): if recorder.recording: await _stopRecording(recordButton, uploadButton, recorder, wavFile) if soloTool.playingAdHoc: soloTool.backToNormal() else: soloTool.playAdHoc(wavFile) soloTool.play() return f def _makeUploadCallback(playButton, recordButton, uploadButton, tempDir, sessionManager): async def f(): with ui.dialog() as dialog, ui.card(): fileName = ui.input(label='File name', value="jam.mp3") with ui.row(): ui.button('Upload', color='positive', on_click=lambda: dialog.submit(fileName.value)) ui.button('Cancel', color='negative' ,on_click=lambda: dialog.submit(None)) fileName = await dialog if fileName is None: return playButton.disable() recordButton.disable() uploadButton.disable() def on_dismiss(): playButton.enable() recordButton.enable() uploadButton.enable() n = ui.notification(timeout=None, position='bottom-right', type='ongoing', spinner=True, on_dismiss=on_dismiss, icon='check') n.message = f'Converting to .mp3...' mp3File = Path(tempDir.name) / fileName await run.cpu_bound(_recording.writeMp3, mp3File) n.message = 'Uploading...' folderName = date.today().isoformat() try: await run.io_bound(sessionManager.saveRecording, mp3File, f"{folderName}/{fileName}") except: n.spinner = False n.icon = 'error' n.message = 'Upload failed!' n.close_button = 'Close' return n.spinner = False n.message = 'Done!' await sleep(2) n.dismiss() return f def recordingControls(soloTool, recorder, sessionManager): tempDir = TemporaryDirectory(prefix="solotool-") wavFile = Path(tempDir.name) / "st_recording.wav" with ui.button_group().classes('').style('height: 40px'): recordButton = ui.button(icon='fiber_manual_record', color='negative') \ .bind_icon_from(recorder, 'recording', lambda recording: 'radio_button_unchecked' if recording else 'fiber_manual_record') playButton = ui.button(icon='hearing') \ .bind_icon_from(soloTool, 'playingAdHoc', lambda adHoc: 'close' if adHoc else 'hearing') playButton.disable() uploadButton = ui.button(icon='cloud_upload') uploadButton.disable() recordButton.on_click(_makeRecordCallback(playButton, recordButton, uploadButton, soloTool, recorder, wavFile)) playButton.on_click(_makePlayCallback(playButton, recordButton, uploadButton, soloTool, recorder, wavFile)) uploadButton.on_click(_makeUploadCallback(playButton, recordButton, uploadButton, tempDir, sessionManager))