From a761b81dd1382bb7abd241c76fdb7fcf3a1f2ada Mon Sep 17 00:00:00 2001 From: michalcourson Date: Sat, 21 Feb 2026 20:42:11 -0500 Subject: [PATCH] fully functional runtime stuff. Need settings then new features --- audio-service/metadata.json | 12 +-- .../audio_recorder.cpython-313.pyc | Bin 7136 -> 7319 bytes audio-service/src/audio_recorder.py | 5 +- .../__pycache__/recording.cpython-313.pyc | Bin 2821 -> 2821 bytes electron-ui/src/renderer/App.tsx | 24 +++-- .../src/renderer/components/AudioTrimer.tsx | 83 ++++++++++++++++-- .../renderer/components/playOverlapIcon.tsx | 29 ++++++ .../src/renderer/components/playStopIcon.tsx | 23 +++++ 8 files changed, 155 insertions(+), 21 deletions(-) create mode 100644 electron-ui/src/renderer/components/playOverlapIcon.tsx create mode 100644 electron-ui/src/renderer/components/playStopIcon.tsx diff --git a/audio-service/metadata.json b/audio-service/metadata.json index e83672c..0ac3d2c 100644 --- a/audio-service/metadata.json +++ b/audio-service/metadata.json @@ -18,16 +18,16 @@ "filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_193822.wav", "name": "Pee pee poo poo", "playbackType": "playStop", - "startTime": 27.756510985786615, - "volume": 1 + "startTime": 27.587412587412587, + "volume": 0.69 }, { - "endTime": 28.597210828548004, + "endTime": 27.516843118383072, "filename": "C:\\Users\\mickl\\Desktop\\cliptrim-ui\\ClipTrimApp\\audio-service\\recordings\\audio_capture_20260220_200442.wav", "name": "Clip 20260220_200442", - "playbackType": "playStop", - "startTime": 26.1853978671042, - "volume": 1 + "playbackType": "playOverlap", + "startTime": 25.120307988450435, + "volume": 0.41 } ] } diff --git a/audio-service/src/__pycache__/audio_recorder.cpython-313.pyc b/audio-service/src/__pycache__/audio_recorder.cpython-313.pyc index 3fd36bd9ba7cdf97c8a4b0fedfbd751e234ded57..61d41c879209cff7be8632298c04d97804889bfb 100644 GIT binary patch delta 620 zcmaE0KHZY{GcPX}0}v#5&&u4nk=KctF>G@HvkBwmSuA3VOq(~dSTXW4-Qp@v%q_@C zElMm&oy^3h$#sh(IU_MIFEyulvH@EUWAo&_Y$;Ap#3ZKYP0G6=E`42G{i3+~4N=MK zqM8>)H9xX4i*t3b^l}%80BuTU1lb1#96*{Gh(F6QF)&P>#3?aZPf~dDRQ9*3;xHw_ zOrZ=xJTM-D=3@wEp1hDlj0MPGnVi5UCcwvF%w`HTU4bE5V)6z)naT4xq#0!30YRQbT&=)$<~}!K~)-#r74;DL8;04MJcI83YmGCC7FpinN_JN z3gww4844+-K#ynU=h;^A7wafMf+8Li7PeKq9#uLDu&}T#k_I}@Pg7uWEvK@S9FSck z4jcfC2E&(P+ ztId0OoLLyQ(gC?kZZfBcJ7fOlKoLhq#){38 zMI#v*6(+wG^I&Y)Y$o2t$k@I4poAtPKDb;Z-`1xkDV9`q^^r6}&^ zMbbdEewzG~KXWRJ$^+R&3LpaH)FKrSp*q=sE1Plt2Zx`Im=)E~xNR^3Ee)2>SVHtE=fL3WT73qL%l%IS+#GSEVGl!@nBV*-e zFR@5Qpxc*-doVU`ek4|s( diff --git a/audio-service/src/audio_recorder.py b/audio-service/src/audio_recorder.py index 05d38e2..b4db2ef 100644 --- a/audio-service/src/audio_recorder.py +++ b/audio-service/src/audio_recorder.py @@ -28,9 +28,9 @@ class AudioRecorder: self.channels = 2 self.buffer = np.zeros((int(self.duration * self.sample_rate), self.channels), dtype=np.float32) self.recordings_dir = "recordings" + self.stream = sd.InputStream( samplerate=self.sample_rate, - channels=self.channels, callback=self.record_callback ) @@ -43,10 +43,9 @@ class AudioRecorder: self.stream.stop() self.buffer = np.zeros((int(self.duration * self.sample_rate), self.channels), dtype=np.float32) - + print(f"AudioRecorder initialized with duration={self.duration}s, sample_rate={self.sample_rate}Hz, channels={self.channels}") self.stream = sd.InputStream( samplerate=self.sample_rate, - channels=self.channels, callback=self.record_callback ) diff --git a/audio-service/src/routes/__pycache__/recording.cpython-313.pyc b/audio-service/src/routes/__pycache__/recording.cpython-313.pyc index 62062389ec9da64cd351f56724029fd627aadc29..d15b53715c0e5d001d37625253e4b603651a552d 100644 GIT binary patch delta 22 ccmZn_YZc@D%*)Hg00g49W@g^o$oqo}07LNx>Hq)$ delta 22 ccmZn_YZc@D%*)Hg00al`P08H6k@p7|07)YUY5)KL diff --git a/electron-ui/src/renderer/App.tsx b/electron-ui/src/renderer/App.tsx index aaaec0e..f9cfde0 100644 --- a/electron-ui/src/renderer/App.tsx +++ b/electron-ui/src/renderer/App.tsx @@ -2,6 +2,8 @@ import { MemoryRouter as Router, Routes, Route } from 'react-router-dom'; import { useEffect, useState } from 'react'; import { Provider } from 'react-redux'; import Dialog from '@mui/material/Dialog'; + +import { ThemeProvider, createTheme } from '@mui/material/styles'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; @@ -150,13 +152,25 @@ function MainPage() { } export default function App() { + const theme = createTheme({ + palette: { + primary: { + main: '#6e44ba', // plum + }, + secondary: { + main: '#4f3186', // plumDark + }, + }, + }); return ( - - - } /> - - + + + + } /> + + + ); } diff --git a/electron-ui/src/renderer/components/AudioTrimer.tsx b/electron-ui/src/renderer/components/AudioTrimer.tsx index 81487af..af5954b 100644 --- a/electron-ui/src/renderer/components/AudioTrimer.tsx +++ b/electron-ui/src/renderer/components/AudioTrimer.tsx @@ -9,6 +9,9 @@ import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; +import Slider from '@mui/material/Slider'; +import ToggleButton from '@mui/material/ToggleButton'; +import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; import { useWavesurfer } from '@wavesurfer/react'; import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.esm.js'; import ZoomPlugin from 'wavesurfer.js/dist/plugins/zoom.esm.js'; @@ -19,8 +22,10 @@ import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import DeleteIcon from '@mui/icons-material/Delete'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import { ClipMetadata } from '../../redux/types'; +import { ClipMetadata, PlaybackType } from '../../redux/types'; import { useAppSelector } from '../hooks'; +import PlayStopIcon from './playStopIcon'; +import PlayOverlapIcon from './playOverlapIcon'; export interface AudioTrimmerProps { metadata: ClipMetadata; @@ -43,6 +48,7 @@ export default function AudioTrimmer({ const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [dropdownOpen, setDropdownOpen] = useState(false); const [nameInput, setNameInput] = useState(metadata.name); + const [volumeInput, setVolumeInput] = useState(metadata.volume ?? 1); const collectionNames = useAppSelector((state) => state.collections.map((col) => col.name), ); @@ -223,6 +229,7 @@ export default function AudioTrimmer({ } else { const allRegions = (plugins[0] as RegionsPlugin).getRegions(); if (allRegions.length > 0) { + wavesurfer.setVolume(metadata.volume ?? 1); wavesurfer.play(allRegions[0].start, allRegions[0].end); } else { wavesurfer.play(); @@ -404,12 +411,74 @@ export default function AudioTrimmer({
-
-
- - Clip: {formatTime(metadata.startTime ?? 0)} -{' '} - {formatTime(metadata.endTime ?? 0)} - +
+ + Clip: {formatTime(metadata.startTime ?? 0)} -{' '} + {formatTime(metadata.endTime ?? 0)} + +
+ setVolumeInput(newValue as number)} + onChangeCommitted={(e, newValue) => { + const newVolume = newValue as number; + console.log('Volume change:', newVolume); + if (onSave) onSave({ ...metadata, volume: newVolume }); + }} + color="secondary" + className="p-0 m-0" + /> + {/* { + const newVolume = parseFloat(e.target.value); + setVolumeInput(newVolume); + }} + onDragEnd={(e) => { + console.log('Volume change:'); + // const newVolume = parseFloat(e.target.value); + // if (onSave) onSave({ ...metadata, volume: newVolume }); + }} + className="mx-2 w-full accent-plum" + aria-label="Volume slider" + /> */} +
+
+ + { + if (onSave) + onSave({ + ...metadata, + playbackType: PlaybackType.PlayStop, + }); + }} + > + + + { + if (onSave) + onSave({ + ...metadata, + playbackType: PlaybackType.PlayOverlap, + }); + }} + > + + +
diff --git a/electron-ui/src/renderer/components/playOverlapIcon.tsx b/electron-ui/src/renderer/components/playOverlapIcon.tsx new file mode 100644 index 0000000..3592bd4 --- /dev/null +++ b/electron-ui/src/renderer/components/playOverlapIcon.tsx @@ -0,0 +1,29 @@ +import React from 'react'; + +export default function PlayOverlapIcon({ + size = 24, + color = 'currentColor', +}: { + size?: number; + color?: string; +}) { + return ( + + {/* Filled play arrow */} + + {/* Outlined play arrow (underneath and to the right) */} + + + ); +} diff --git a/electron-ui/src/renderer/components/playStopIcon.tsx b/electron-ui/src/renderer/components/playStopIcon.tsx new file mode 100644 index 0000000..7d66388 --- /dev/null +++ b/electron-ui/src/renderer/components/playStopIcon.tsx @@ -0,0 +1,23 @@ +export default function PlayStopIcon({ + size = 24, + color = 'currentColor', +}: { + size?: number; + color?: string; +}) { + return ( + + {/* Play Arrow */} + + {/* Stop Square */} + + + ); +}