diff --git a/css/style.css b/css/style.css
index ba96f59..2e35103 100644
--- a/css/style.css
+++ b/css/style.css
@@ -253,6 +253,14 @@
}
.deck-volume-controls {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ align-items: center;
+ width: 100%;
+ }
+
+ .deck-volume-sliders {
display: flex;
gap: 40px;
justify-content: center;
diff --git a/index.html b/index.html
index cf4f80c..3bd1a3a 100644
--- a/index.html
+++ b/index.html
@@ -92,25 +92,9 @@
-
+
-
-
-
-
-
-
@@ -129,6 +113,25 @@
🎧 DJ Toolkit Pro
+
+
+
+
+
+
+
diff --git a/js/main.js b/js/main.js
index 8370048..76fb5c3 100644
--- a/js/main.js
+++ b/js/main.js
@@ -727,7 +727,15 @@ class Deck {
function setMasterVolume(value) {
masterGain.gain.value = value / 100;
- saveSettings();
+ updateMasterVolumeKnobUI(value / 100);
+ }
+
+ function updateMasterVolumeKnobUI(value) {
+ const knob = document.getElementById('masterVolumeKnob');
+ if (knob) {
+ const rotation = -135 + (value * 270); // -135 to 135 degrees
+ knob.style.transform = `rotate(${rotation}deg)`;
+ }
}
function setCrossfader(value) {
@@ -774,6 +782,7 @@ class Deck {
// Knob turning logic
let activeKnob = {
+ type: null, // 'effect' or 'master'
deck: null,
effect: null,
element: null,
@@ -781,26 +790,32 @@ class Deck {
initialValue: 0,
};
- function startKnobTurn(event, deckId, effect) {
+ function startKnobTurn(event, type, parameter) {
event.preventDefault();
- const deck = deckId === 'A' ? deckA : deckB;
-
- activeKnob.deck = deck;
- activeKnob.effect = effect;
activeKnob.element = event.target;
activeKnob.initialY = event.clientY;
- activeKnob.initialValue = deck.effects[effect].value;
-
- // Toggle active state on simple click without drag
- if (event.detail === 1) {
- const wasActive = deck.effects[effect].active;
- // A small timeout to differentiate from a drag
- setTimeout(() => {
- if (activeKnob.element && Math.abs(event.clientY - activeKnob.initialY) < 5) {
- deck.effects[effect].active = !wasActive;
- deck.toggleEffect(effect);
- }
- }, 200);
+
+ if (type === 'master') {
+ activeKnob.type = 'master';
+ activeKnob.initialValue = masterGain.gain.value;
+ } else {
+ const deck = type === 'A' ? deckA : deckB;
+ activeKnob.type = 'effect';
+ activeKnob.deck = deck;
+ activeKnob.effect = parameter;
+ activeKnob.initialValue = deck.effects[parameter].value;
+
+ // Toggle active state on simple click without drag
+ if (event.detail === 1) {
+ const wasActive = deck.effects[parameter].active;
+ // A small timeout to differentiate from a drag
+ setTimeout(() => {
+ if (activeKnob.element && Math.abs(event.clientY - activeKnob.initialY) < 5) {
+ deck.effects[parameter].active = !wasActive;
+ deck.toggleEffect(parameter);
+ }
+ }, 200);
+ }
}
window.addEventListener('mousemove', handleKnobTurn);
@@ -815,11 +830,17 @@ class Deck {
let value = activeKnob.initialValue + dy * sensitivity;
value = Math.max(0, Math.min(1, value)); // clamp between 0 and 1
- activeKnob.deck.toggleEffect(activeKnob.effect, value);
+ if (activeKnob.type === 'master') {
+ setMasterVolume(value * 100);
+ saveSettings();
+ } else {
+ activeKnob.deck.toggleEffect(activeKnob.effect, value);
+ }
}
function endKnobTurn(event) {
activeKnob.element = null;
+ activeKnob.type = null;
window.removeEventListener('mousemove', handleKnobTurn);
window.removeEventListener('mouseup', endKnobTurn);
}
@@ -1011,7 +1032,7 @@ class Deck {
keylock: deckB.keylock,
effects: deckB.effects
},
- masterVolume: document.getElementById('masterVolume').value,
+ masterVolume: masterGain.gain.value * 100,
crossfader: document.getElementById('crossfader').value,
playlist: playlist.map(item => ({ name: item.name }))
};
@@ -1038,7 +1059,6 @@ class Deck {
document.getElementById('volumeB').value = session.deckB.volume;
document.getElementById('tempoA').value = session.deckA.tempo;
document.getElementById('tempoB').value = session.deckB.tempo;
- document.getElementById('masterVolume').value = session.masterVolume;
document.getElementById('crossfader').value = session.crossfader;
setVolume('A', session.deckA.volume);
@@ -1095,7 +1115,7 @@ class Deck {
keylock: deckB.keylock,
effects: deckB.effects
},
- masterVolume: document.getElementById('masterVolume').value,
+ masterVolume: masterGain.gain.value * 100,
crossfader: document.getElementById('crossfader').value,
crossfaderCurve: document.getElementById('crossfaderCurve').value,
theme: document.getElementById('theme').value,
@@ -1111,7 +1131,6 @@ class Deck {
// Restore Mixer
setMasterVolume(settings.masterVolume);
- document.getElementById('masterVolume').value = settings.masterVolume;
setCrossfader(settings.crossfader);
document.getElementById('crossfader').value = settings.crossfader;