implementing UI for bottom controls

This commit is contained in:
2026-01-13 21:33:25 +11:00
parent f8f41212f3
commit 30835a506e
4 changed files with 62 additions and 3 deletions

View File

@@ -1,4 +1,5 @@
pymp3
textual
textual-slider
textual-plot
numpy

View File

@@ -3,6 +3,7 @@ from textual.widgets import Footer
from ui.widgets.sidebar import Sidebar
from ui.widgets.timeline import Timeline
from ui.widgets.project_settings import ProjectSettings
class AppUI(App):
@@ -13,4 +14,5 @@ class AppUI(App):
def compose(self) -> ComposeResult:
yield Sidebar()
yield Timeline()
yield ProjectSettings()
yield Footer()

View File

@@ -1,9 +1,11 @@
import librosa
import pyloudnorm as pyln
import math
import random
from textual.containers import Vertical
from textual.widgets import Sparkline
from textual_plot import HiResMode, PlotWidget
from ui.widgets.chunk_types.chunk import Chunk
@@ -12,7 +14,7 @@ from ui.widgets.chunk_types.chunk import Chunk
class AudioChunk(Chunk):
DEFAULT_CSS = """
AudioChunk {
align: left middle;
Sparkline {
margin: 1;
}
@@ -41,6 +43,11 @@ class AudioChunk(Chunk):
self.styles.width = (self.num_samples / self.sample_rate) / self.app.zoom_level
def on_mount(self):
for plot in self.query(PlotWidget):
plot.margin_top = 0
plot.margin_left = 0
plot.margin_bottom = 0
def compose(self) -> ComposeResult:
@@ -56,6 +63,8 @@ class AudioChunk(Chunk):
samples.append(self.audio[channel, sample])
yield Sparkline(data=samples)
else:
# just display the one channel
samples = []
@@ -64,4 +73,3 @@ class AudioChunk(Chunk):
samples.append(self.audio[sample])
yield Sparkline(data=samples)

View File

@@ -0,0 +1,48 @@
from textual.containers import Horizontal
from textual.app import ComposeResult
from textual.widgets import Button, Input, Static
class ProjectSettings(Horizontal):
DEFAULT_CSS = """
ProjectSettings {
height: 6;
margin-bottom: 1;
dock: bottom;
background: $surface-darken-1;
border-top: tall $surface-lighten-1;
align-vertical: middle;
padding: 0 1;
Button {
max-width: 5;
}
#song-bpm {
max-width: 12;
}
#song-time-sig {
max-width: 16;
}
Static {
height: 3;
content-align: left middle;
width: auto;
}
}
"""
def __init__(self):
super().__init__()
self.border_title = "Project"
def compose(self) -> ComposeResult:
yield Button("", tooltip="Play song", flat=True, id="play-button", variant="success") # icon becomes "⏸" when song is playing
yield Static(" BPM: ")
yield Input("120", placeholder="120", valid_empty=False, type="integer", max_length=3, id="song-bpm")
yield Static(" Time Signature: ")
yield Input("4/4", placeholder="4/4", valid_empty=False, id="song-time-sig")