Skip to content
Merged
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
8 changes: 8 additions & 0 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
39 changes: 21 additions & 18 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,9 @@ <h1>🎧 DJ Toolkit Pro</h1>

<!-- Mixer -->
<div class="mixer">
<div class="slider-container">
<div class="effect-control">
<div id="masterVolumeKnob" class="effect-knob" onmousedown="startKnobTurn(event, 'master', 'volume')"></div>
<label>Master Volume</label>
<input type="range" class="slider" id="masterVolume" min="0" max="100" value="75" oninput="setMasterVolume(this.value)">
</div>

<div class="deck-volume-controls">
<div class="slider-container vertical">
<label>Volume A</label>
<input type="range" class="slider" id="volumeA" min="0" max="100" value="75" oninput="setVolume('A', this.value)">
</div>
<div class="slider-container vertical">
<label>Volume B</label>
<input type="range" class="slider" id="volumeB" min="0" max="100" value="75" oninput="setVolume('B', this.value)">
</div>
</div>

<div class="crossfader-container">
<label>Crossfader</label>
<input type="range" class="crossfader slider" id="crossfader" min="0" max="100" value="50" oninput="setCrossfader(this.value)">
</div>

<div class="spectrum">
Expand All @@ -129,6 +113,25 @@ <h1>🎧 DJ Toolkit Pro</h1>
</div>

<button class="control-btn" onclick="toggleAutomix()">🤖 Automix</button>

<div class="deck-volume-controls">
<label>Volume</label>
<div class="deck-volume-sliders">
<div class="slider-container vertical">
<input type="range" class="slider" id="volumeA" min="0" max="100" value="75" oninput="setVolume('A', this.value)">
<label>A</label>
</div>
<div class="slider-container vertical">
<input type="range" class="slider" id="volumeB" min="0" max="100" value="75" oninput="setVolume('B', this.value)">
<label>B</label>
</div>
</div>
</div>

<div class="crossfader-container">
<label>Crossfader</label>
<input type="range" class="crossfader slider" id="crossfader" min="0" max="100" value="50" oninput="setCrossfader(this.value)">
</div>
</div>

<!-- Deck B -->
Expand Down
65 changes: 42 additions & 23 deletions js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -774,33 +782,40 @@ class Deck {

// Knob turning logic
let activeKnob = {
type: null, // 'effect' or 'master'
deck: null,
effect: null,
element: null,
initialY: 0,
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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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 }))
};
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -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;

Expand Down