Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 54 additions & 71 deletions Lux/lux_react/src/components/AudioControlPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ const AudioControlPanel = ({
return 'prompt';
};

const formatValue = (value) => Math.round((value || 0) * 100);

// Advanced mixer frequency bands
const frequencyBands = [
{ id: 'volume', name: 'Volume', range: 'Overall', color: '#666', value: audioFeatures?.volume || 0 },
{ id: 'bass', name: 'Bass', range: '60-250Hz', color: '#ff3366', value: audioFeatures?.bassLevel || 0 },
{ id: 'mid', name: 'Mid', range: '500-2kHz', color: '#ffaa33', value: audioFeatures?.midLevel || 0 },
{ id: 'high', name: 'High', range: '2k+Hz', color: '#66ff33', value: audioFeatures?.highLevel || 0 }
];

const linearToDb = (linear) => {
if (linear <= 0) return -60;
return 20 * Math.log10(linear);
};

return (
<div className="audio-control-panel enhanced">
Expand Down Expand Up @@ -52,85 +64,56 @@ const AudioControlPanel = ({

{isEnabled && (
<>
<div className="audio-meters-grid">
<div className="frequency-meter">
<div className="meter-header">
<span className="meter-label">Bass</span>
<span className="meter-value">{formatValue(audioFeatures?.bassLevel)}%</span>
</div>
<div className="meter-bar">
<div
className="meter-fill bass"
style={{ width: `${formatValue(audioFeatures?.bassLevel)}%` }}
/>
</div>
</div>

<div className="frequency-meter">
<div className="meter-header">
<span className="meter-label">Mid</span>
<span className="meter-value">{formatValue(audioFeatures?.midLevel)}%</span>
</div>
<div className="meter-bar">
<div
className="meter-fill mid"
style={{ width: `${formatValue(audioFeatures?.midLevel)}%` }}
/>
</div>
</div>

<div className="frequency-meter">
<div className="meter-header">
<span className="meter-label">High</span>
<span className="meter-value">{formatValue(audioFeatures?.highLevel)}%</span>
</div>
<div className="meter-bar">
<div
className="meter-fill high"
style={{ width: `${formatValue(audioFeatures?.highLevel)}%` }}
/>
</div>
</div>

<div className="frequency-meter">
<div className="meter-header">
<span className="meter-label">Volume</span>
<span className="meter-value">{formatValue(audioFeatures?.volume)}%</span>
</div>
<div className="meter-bar">
<div
className="meter-fill volume"
style={{ width: `${formatValue(audioFeatures?.volume)}%` }}
/>
</div>
</div>
</div>

<div className="audio-features-section">
<div className="beat-indicator-card">
{/* Vertical Mixer Strips - Primary Control */}
<div className="mixer-strips-container">
<div className="mixer-header">
<h3>🎛️ Audio Mixer</h3>
<div className="beat-indicator">
<div className={`beat-pulse ${audioFeatures?.beatDetected ? 'active' : ''}`} />
<span className="beat-text">Beat Detection</span>
</div>
<div className="beat-status">
{audioFeatures?.beatDetected ? '🎵 Beat!' : '⏸️ Waiting'}
<span className="beat-text">{audioFeatures?.beatDetected ? '🎵 Beat!' : '⏸️ Waiting'}</span>
</div>
</div>

<div className="activity-indicator-card">
<div className="audio-activity-indicator">
<div className={`activity-dot ${(audioFeatures?.volume || 0) > 0.01 ? 'active' : ''}`} />
<span className="activity-text">Audio Input</span>
</div>
<div className="activity-status">
{(audioFeatures?.volume || 0) > 0.01 ? '🔊 Detected' : '🔇 Silent'}
</div>

<div className="frequency-strips">
{frequencyBands.map(band => (
<div key={band.id} className="band-strip">
<div className="band-header">
<span className="band-name" style={{ color: band.color }}>
{band.name}
</span>
<span className="band-range">{band.range}</span>
</div>

<div className="band-meter">
<div
className="level-bar"
style={{
height: `${Math.max(0, Math.min(100, ((linearToDb(band.value) + 60) / 60 * 100)))}%`,
backgroundColor: band.color
}}
/>
<div className="meter-scale">
<span className="db-marker" style={{ bottom: '100%' }}>0</span>
<span className="db-marker" style={{ bottom: '75%' }}>-12</span>
<span className="db-marker" style={{ bottom: '50%' }}>-24</span>
<span className="db-marker" style={{ bottom: '25%' }}>-36</span>
<span className="db-marker" style={{ bottom: '0%' }}>-60</span>
</div>
</div>

<div className="level-display">
<div className="level-db" style={{ color: band.color }}>
{linearToDb(band.value).toFixed(1)}dB
</div>
</div>
</div>
))}
</div>
</div>

<div className="sensitivity-section-enhanced">
<div className="sensitivity-header">
<span className="sensitivity-title">🎛️ Sensitivity</span>
<span className="sensitivity-title">🎛️ Master Sensitivity</span>
<span className="sensitivity-value">{Math.round((sensitivity ?? 1.0) * 100)}%</span>
</div>
<div className="sensitivity-slider-container">
Expand Down
22 changes: 10 additions & 12 deletions Lux/lux_react/src/components/AudioMixer.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
color: #ffffff;
font-family: 'Inter', 'Arial', sans-serif;
width: 100%;
overflow: hidden;
max-height: 60vh;
overflow-y: auto;
overflow: visible;
max-height: none;
}

/* Header */
Expand Down Expand Up @@ -175,13 +174,10 @@
/* Frequency Bands */
.frequency-bands {
margin-bottom: 16px;
}

.frequency-bands h4 {
margin-bottom: 15px;
color: #fff;
font-size: 1.2rem;
text-align: center;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 12px;
padding: 16px;
}

.bands-grid {
Expand Down Expand Up @@ -491,7 +487,8 @@
.audio-mixer {
padding: 12px;
margin: 0;
max-height: 50vh;
max-height: none;
overflow: visible;
}

.mixer-header h3 {
Expand Down Expand Up @@ -552,7 +549,8 @@
@media (max-width: 480px) {
.audio-mixer {
padding: 8px;
max-height: 40vh;
max-height: none;
overflow: visible;
}

.bands-grid {
Expand Down
15 changes: 10 additions & 5 deletions Lux/lux_react/src/components/ControlPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ import { useJenModule } from '../hooks/useJenModule.js'; // Our simple, reliable
import MediaController from "./MediaController";
import TabNavigation from "./TabNavigation";
import HomePane from "./panes/HomePane";
import SourceImagePane from "./panes/SourceImagePane";
import TargetImagePane from "./panes/TargetImagePane";
import BrushPane from "./panes/BrushPane";
import AudioPane from "./panes/AudioPane";
import {SceneChooserPane} from "./panes/SceneChooserPane";
import {PaneContext} from "./panes/PaneContext.jsx";
import RealtimeCamera from "./RealtimeCamera.jsx";
import ImagePane from "./panes/ImagePane.jsx";

function ControlPanel({ dimensions, panelSize, activePane, onPaneChange }) {
const { sliderValues, onSliderChange } = React.useContext(ControlPanelContext);
Expand Down Expand Up @@ -244,14 +243,20 @@ function ControlPanel({ dimensions, panelSize, activePane, onPaneChange }) {
<SceneChooserPane />
</PaneContext.Provider>
);
case "source":
case "image":
return (
<PaneContext.Provider value={paneContextValue}>
<SourceImagePane {...commonProps}/>
<ImagePane {...commonProps}/>
</PaneContext.Provider>
);
case "source":
case "target":
return <TargetImagePane {...commonProps} />;
// Redirect old pane values to the new unified image pane
return (
<PaneContext.Provider value={paneContextValue}>
<ImagePane {...commonProps}/>
</PaneContext.Provider>
);
case "brush":
return <BrushPane {...commonProps} />;
case "audio":
Expand Down
1 change: 0 additions & 1 deletion Lux/lux_react/src/components/MediaController.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ function MediaController({ isOverlay = false }) {
const syncWithBackend = () => {
if (window.module && typeof window.module.get_animation_running === 'function') {
const backendRunning = window.module.get_animation_running();
console.log('[MediaController] Syncing with backend animation state:', backendRunning);
setIsRunning(backendRunning);
}
};
Expand Down
20 changes: 3 additions & 17 deletions Lux/lux_react/src/components/TabNavigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ function TabNavigation({ activePane, onPaneChange }) {

<Tab
icon={<BiImageAlt style={iconStyle} />}
value="source"
value="image"
sx={{
minHeight: '50px',
'&.Mui-selected': {
color: 'primary.main',
background: 'rgba(25, 118, 210, 0.08)'
}
}}
aria-label="Source Image"
title="Source Image"
aria-label="Image Controls"
title="Image Controls"
/>

<Tab
Expand Down Expand Up @@ -131,20 +131,6 @@ function TabNavigation({ activePane, onPaneChange }) {
title={isAudioEnabled ? "Audio (Active)" : "Audio"}
/>

<Tab
icon={<FaBullseye style={{...iconStyle, color: activePane === "target" ? "#e63946" : undefined}} />}
value="target"
sx={{
minHeight: '50px',
'&.Mui-selected': {
color: 'primary.main',
background: 'rgba(25, 118, 210, 0.08)'
}
}}
aria-label="Target Image"
title="Target Image"
/>

<Tab
icon={<BsBrush style={iconStyle} />}
value="brush"
Expand Down
Loading