diff options
Diffstat (limited to 'web-project')
| -rw-r--r-- | web-project/src/solo_tool_web.py | 58 | 
1 files changed, 39 insertions, 19 deletions
| diff --git a/web-project/src/solo_tool_web.py b/web-project/src/solo_tool_web.py index a3143c5..8ae36b5 100644 --- a/web-project/src/solo_tool_web.py +++ b/web-project/src/solo_tool_web.py @@ -1,11 +1,11 @@  from glob import glob  from os.path import basename, splitext  from nicegui import ui +from starlette.formparsers import MultiPartParser  from solo_tool import SoloTool  from solo_tool.session_manager import loadSession, saveSession  from solo_tool import handlers -from solo_tool.midi_controller_launchpad_mini import MidiController  SESSION_DIR = "/home/eddy/music/sessions"  SONG_POOL = "/home/eddy/music" @@ -14,17 +14,25 @@ def fileName(path: str) -> str:      return basename(splitext(path)[0])  @ui.refreshable -def keyPointTables(st: SoloTool) -> None: -    for i, song in enumerate(st.songs): -        with ui.list().props('separator').bind_visibility_from(st, 'song', value=i): -            for kp in st._keyPoints[i]: -                ui.item(f"{kp:0.2}", on_click=handlers.setKeyPoint(st, kp)).props('clickable v-ripple').classes('text-lg') +def keyPointList(st: SoloTool) -> None: +    with ui.list().props('separator'): +        for kp in st.keyPoints: +            ui.item(f"{kp:0.2}", on_click=handlers.setKeyPoint(st, kp)).props('clickable v-ripple').classes('text-lg') + +@ui.refreshable +def songList(st: SoloTool, songDrawer) -> None: +    with ui.list().props('separator'): +        for i, path in enumerate(st.songs): +            ui.item(fileName(path), on_click=handlers.setSong(st, i, lambda: songDrawer.hide())).props('clickable v-ripple')  sessions = {}  for f in glob(f"{SESSION_DIR}/*.json"):      sessionName = fileName(f) -    sessions[sessionName] = loadSession(f, SONG_POOL) -    sessions[sessionName].registerKeyPointListCallback(lambda new: keyPointTables.refresh()) +    songTool = loadSession(f, SONG_POOL) +    songTool.registerKeyPointListCallback(lambda new: keyPointList.refresh()) +    songTool.registerSongSelectionCallback(lambda new: keyPointList.refresh()) +    songTool.registerSongListCallback(lambda new: songList.refresh()) +    sessions[sessionName] = songTool  @ui.page('/{sessionName}')  def sessionPage(sessionName: str): @@ -36,32 +44,44 @@ def sessionPage(sessionName: str):      ui.colors(secondary='#ffc107')      ui.page_title(sessionName) +    # Improved performance with large file uploads +    MultiPartParser.max_file_size = 1024 * 1024 * 100  # 100 MB +      st = sessions[sessionName] +    # Upload song dialog +    def handleFileUpload(e): +        from shutil import copyfileobj +        newSong = f"{SONG_POOL}/{e.name}" +        with open(newSong, "wb") as f: +            copyfileobj(e.content, f) +        st.addSong(newSong) + +    with ui.dialog() as uploadSongDialog: +        ui.upload(label="Upload songs", auto_upload=True, on_upload=handleFileUpload).classes('max-w-full') +      # Header      with ui.header().classes('items-center justify-between'):          with ui.row().classes('items-center justify-start'): -            ui.button(icon='menu', on_click=lambda: song_drawer.toggle()).props('flat round dense color=white') +            ui.button(icon='menu', on_click=lambda: songDrawer.toggle()).props('flat round color=white')              ui.label().bind_text_from(st, 'song', lambda index: fileName(st.songs[index]) if index is not None else "Select a song").classes('text-lg')          with ui.row().classes('items-center justify-start'): +            ui.button(icon='home', on_click=lambda: ui.navigate.to("/")).props('flat dense round color=white')              def save(): saveSession(st, f"{SESSION_DIR}/{sessionName}.json")              ui.button(icon='save', on_click=save).props('flat dense round color=white') -            ui.button(icon='fullscreen', on_click=fullscreen.toggle).props('flat dense round color=white') +            ui.button(icon='fullscreen', on_click=fullscreen.toggle).props('flat round color=white')      # Key points list      with ui.right_drawer(top_corner=True, bottom_corner=True).props('width=120 behavior=desktop'):          ui.label("Key Points").classes('text-lg') -        keyPointTables(st) - +        keyPointList(st)          def addKeyPoint() -> None: st.keyPoints += [st.keyPoint]          ui.button(icon='add', on_click=addKeyPoint).props('flat round dense color=white')      # Song list -    with ui.left_drawer(bottom_corner=True).props('overlay breakpoint=8000') as song_drawer: -        with ui.list().props('separator'): -            for i, path in enumerate(st.songs): -                ui.item(fileName(path), on_click=handlers.setSong(st, i, lambda: song_drawer.hide())).props('clickable v-ripple') -        ui.button(icon='add', on_click=lambda e: print(e)).props('flat round dense color=white') +    with ui.left_drawer(bottom_corner=True).props('overlay breakpoint=8000') as songDrawer: +        songList(st, songDrawer) +        ui.button(icon='add', on_click=uploadSongDialog.open).props('flat round dense color=white')      # Playback position      def setPosition(e) -> None: st.position = e.args @@ -78,7 +98,7 @@ def sessionPage(sessionName: str):          buttonSize = "20px"          ui.button(icon='skip_previous', on_click=handlers.restartOrPreviousSong(st, 0.01)).props(f"size={buttonSize}").style('flex: 1')          ui.button(color='positive', on_click=handlers.playPause(st)).bind_icon_from(st, "playing", lambda playing: "pause" if playing else "play_arrow").props(f"size={buttonSize}").style('flex: 1') -        ui.button(icon='vertical_align_bottom', on_click=handlers.positionToKeyPoint(st), color='amber-5').props(f"size={buttonSize}").style('flex: 2') +        ui.button(icon='vertical_align_bottom', on_click=handlers.positionToKeyPoint(st), color='negative').props(f"size={buttonSize}").style('flex: 2')          ui.button(icon='undo', on_click=st.jump, color='secondary').props(f"size={buttonSize}").style('flex: 2')          ui.button(icon='skip_next', on_click=handlers.changeSong(st, 1)).props(f"size={buttonSize}").style('flex: 1') @@ -102,6 +122,6 @@ def landingPage():          ui.label("Choose a session").classes('text-lg')      for name, soloTool in sessions.items(): -        ui.link(name, f"/{name}") +        ui.button(name, on_click=lambda: ui.navigate.to(f"/{name}"))  ui.run(binding_refresh_interval=0.2) | 
