IMPROVE: bật tắt ARM, MIC trên track strip, double click lên nút balance, volume
This commit is contained in:
+47
-7
@@ -939,7 +939,7 @@ const MasterStripConsole = ({ masterVolume, setMasterVolume, showMasteringModal,
|
|||||||
handleFaderChange(Math.max(-60, Math.min(12, masterVolume + delta)));
|
handleFaderChange(Math.max(-60, Math.min(12, masterVolume + delta)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
React.createElement("div", { className: "w-0.5 flex-1 bg-slate-700 absolute" }),
|
React.createElement("div", { className: "w-0.5 h-full bg-slate-700 absolute left-1/2 -translate-x-1/2 top-0" }),
|
||||||
React.createElement("input", {
|
React.createElement("input", {
|
||||||
id: "masterFader",
|
id: "masterFader",
|
||||||
type: "range",
|
type: "range",
|
||||||
@@ -1035,8 +1035,9 @@ const TrackStripConsole = ({ track, index, onUpdateTrack, trackVuRefs }) => {
|
|||||||
var trackColor = track.color || '#06b6d4';
|
var trackColor = track.color || '#06b6d4';
|
||||||
var isMuted = track.muted;
|
var isMuted = track.muted;
|
||||||
var isSoloed = track.solo;
|
var isSoloed = track.solo;
|
||||||
var isArmed = track.armed;
|
var isArmed = track.isArmed;
|
||||||
var trackName = track.name || 'Track ' + (index + 1);
|
var trackName = track.name || 'Track ' + (index + 1);
|
||||||
|
var isMicActive = track.inputSource?.deviceType === 'MICROPHONE';
|
||||||
|
|
||||||
const [pan, setPan] = React.useState(0.0);
|
const [pan, setPan] = React.useState(0.0);
|
||||||
const [panLabel, setPanLabel] = React.useState('center');
|
const [panLabel, setPanLabel] = React.useState('center');
|
||||||
@@ -1088,7 +1089,19 @@ const TrackStripConsole = ({ track, index, onUpdateTrack, trackVuRefs }) => {
|
|||||||
React.createElement("div", {
|
React.createElement("div", {
|
||||||
className: "w-6 h-6 rounded-full bg-slate-800 border-2 border-slate-400 relative flex items-center justify-center cursor-pointer shadow-md",
|
className: "w-6 h-6 rounded-full bg-slate-800 border-2 border-slate-400 relative flex items-center justify-center cursor-pointer shadow-md",
|
||||||
title: "Kéo chuột lên/xuống để chỉnh Pan",
|
title: "Kéo chuột lên/xuống để chỉnh Pan",
|
||||||
onPointerDown: handlePanPointerDown
|
onPointerDown: handlePanPointerDown,
|
||||||
|
onDoubleClick: function() { setPan(0); setPanLabel('center'); if (panPointerRef.current) panPointerRef.current.style.transform = 'rotate(0deg)'; },
|
||||||
|
onWheel: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var step = e.deltaY > 0 ? -0.05 : 0.05;
|
||||||
|
var newPan = Math.max(-1, Math.min(1, pan + step));
|
||||||
|
newPan = Math.round(newPan * 100) / 100;
|
||||||
|
setPan(newPan);
|
||||||
|
if (panPointerRef.current) panPointerRef.current.style.transform = 'rotate(' + (newPan * 120) + 'deg)';
|
||||||
|
if (newPan === 0) setPanLabel('center');
|
||||||
|
else if (newPan < 0) setPanLabel('L' + Math.abs(Math.round(newPan * 100)));
|
||||||
|
else setPanLabel('R' + Math.round(newPan * 100));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
React.createElement("div", {
|
React.createElement("div", {
|
||||||
ref: panPointerRef,
|
ref: panPointerRef,
|
||||||
@@ -1123,6 +1136,15 @@ const TrackStripConsole = ({ track, index, onUpdateTrack, trackVuRefs }) => {
|
|||||||
onChange: function(e) {
|
onChange: function(e) {
|
||||||
var val = parseFloat(e.target.value);
|
var val = parseFloat(e.target.value);
|
||||||
if (onUpdateTrack) onUpdateTrack(track.id, { volumeDb: val });
|
if (onUpdateTrack) onUpdateTrack(track.id, { volumeDb: val });
|
||||||
|
},
|
||||||
|
onWheel: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var step = e.deltaY > 0 ? -0.5 : 0.5;
|
||||||
|
var newVol = Math.max(-60, Math.min(12, vol + step));
|
||||||
|
if (onUpdateTrack) onUpdateTrack(track.id, { volumeDb: newVol });
|
||||||
|
},
|
||||||
|
onDoubleClick: function() {
|
||||||
|
if (onUpdateTrack) onUpdateTrack(track.id, { volumeDb: 0 });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
@@ -1177,9 +1199,21 @@ const TrackStripConsole = ({ track, index, onUpdateTrack, trackVuRefs }) => {
|
|||||||
React.createElement("div", {
|
React.createElement("div", {
|
||||||
className: "h-[28px] shrink-0 flex items-center justify-between mx-1.5 px-1.5 bg-black/40 rounded border border-slate-800/60"
|
className: "h-[28px] shrink-0 flex items-center justify-between mx-1.5 px-1.5 bg-black/40 rounded border border-slate-800/60"
|
||||||
},
|
},
|
||||||
React.createElement("i", { className: "fa-solid fa-volume-high text-[9px] text-slate-400", title: "Input Monitoring" }),
|
|
||||||
React.createElement("button", {
|
React.createElement("button", {
|
||||||
onClick: function(e) { e.stopPropagation(); if (onUpdateTrack) onUpdateTrack(track.id, { armed: !track.armed }); },
|
onClick: function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (!onUpdateTrack) return;
|
||||||
|
if (track.inputSource?.deviceType === 'MICROPHONE') {
|
||||||
|
onUpdateTrack(track.id, { inputSource: { deviceType: 'NONE', deviceId: '' } });
|
||||||
|
} else {
|
||||||
|
onUpdateTrack(track.id, { inputSource: { deviceType: 'MICROPHONE', deviceId: 'default' } });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
className: "w-4 h-4 rounded flex items-center justify-center text-[7px] font-bold transition-all" + (isMicActive ? " bg-sky-600 text-white border border-sky-400 shadow-sm" : " bg-slate-800 text-slate-500 border border-slate-700"),
|
||||||
|
title: isMicActive ? "Mic Input ON" : "Mic Input OFF"
|
||||||
|
}, "MIC"),
|
||||||
|
React.createElement("button", {
|
||||||
|
onClick: function(e) { e.stopPropagation(); if (onUpdateTrack) onUpdateTrack(track.id, { isArmed: !track.isArmed }); },
|
||||||
className: "w-5 h-5 rounded-full flex items-center justify-center transition-all shadow-inner" + (isArmed ? " btn-arm-active border-red-400" : " bg-red-950 border-2 border-red-800 text-red-500"),
|
className: "w-5 h-5 rounded-full flex items-center justify-center transition-all shadow-inner" + (isArmed ? " btn-arm-active border-red-400" : " bg-red-950 border-2 border-red-800 text-red-500"),
|
||||||
title: "Arm for Recording"
|
title: "Arm for Recording"
|
||||||
}, React.createElement("i", { className: "fa-solid fa-circle text-[8px]" }))
|
}, React.createElement("i", { className: "fa-solid fa-circle text-[8px]" }))
|
||||||
@@ -5682,6 +5716,11 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
|
|||||||
setSelectedNoteIds([]);
|
setSelectedNoteIds([]);
|
||||||
showToast(`Đã xóa ${selectedNoteIds.length} nốt!`, 'info');
|
showToast(`Đã xóa ${selectedNoteIds.length} nốt!`, 'info');
|
||||||
}
|
}
|
||||||
|
} else if (e.key === 'F7') {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
var toggleMixer = window.__toggleMixerRef;
|
||||||
|
if (toggleMixer) toggleMixer();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
window.addEventListener('keydown', handler);
|
window.addEventListener('keydown', handler);
|
||||||
@@ -8965,6 +9004,7 @@ const App = () => {
|
|||||||
const [showMixer, setShowMixer] = useState(false);
|
const [showMixer, setShowMixer] = useState(false);
|
||||||
const setShowMixerRef = useRef(setShowMixer);
|
const setShowMixerRef = useRef(setShowMixer);
|
||||||
setShowMixerRef.current = setShowMixer;
|
setShowMixerRef.current = setShowMixer;
|
||||||
|
window.__toggleMixerRef = function() { setShowMixer(function(p) { return !p; }); };
|
||||||
const [mixerHeight, setMixerHeight] = useState(function() {
|
const [mixerHeight, setMixerHeight] = useState(function() {
|
||||||
var saved = localStorage.getItem('studio_mixer_height');
|
var saved = localStorage.getItem('studio_mixer_height');
|
||||||
return saved ? parseInt(saved) : 200;
|
return saved ? parseInt(saved) : 200;
|
||||||
@@ -17435,7 +17475,7 @@ const App = () => {
|
|||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
|
|
||||||
let audioPeak = 0;
|
let audioPeak = 0;
|
||||||
if (node && node.analyserNode && isPlaying) {
|
if (node && node.analyserNode) {
|
||||||
const analyser = node.analyserNode;
|
const analyser = node.analyserNode;
|
||||||
const data = new Uint8Array(128);
|
const data = new Uint8Array(128);
|
||||||
analyser.getByteTimeDomainData(data);
|
analyser.getByteTimeDomainData(data);
|
||||||
@@ -17445,7 +17485,7 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let midiPeak = midiVuActivityRef.current[trackId] || 0;
|
let midiPeak = isPlaying ? (midiVuActivityRef.current[trackId] || 0) : 0;
|
||||||
if (midiPeak > 0) {
|
if (midiPeak > 0) {
|
||||||
midiVuActivityRef.current[trackId] = midiPeak * 0.90;
|
midiVuActivityRef.current[trackId] = midiPeak * 0.90;
|
||||||
if (midiVuActivityRef.current[trackId] < 0.01) {
|
if (midiVuActivityRef.current[trackId] < 0.01) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user