1
0
Fork 0
forked from Simnation/Main
Main/resources/[tools]/nordi_dj/html/script.js

321 lines
9.3 KiB
JavaScript
Raw Normal View History

2025-08-03 17:46:16 +02:00
// DJ System - Professional Interface
let djInterface = {
decks: {
A: {
track: null,
isPlaying: false,
volume: 75,
pitch: 0,
cuePoint: 0,
player: null,
youtubePlayer: null
},
B: {
track: null,
isPlaying: false,
volume: 75,
pitch: 0,
cuePoint: 0,
player: null,
youtubePlayer: null
}
},
mixer: {
crossfader: 50,
masterVolume: 80,
eq: {
A: { high: 0, mid: 0, low: 0 },
B: { high: 0, mid: 0, low: 0 }
}
},
effects: {
reverb: false,
delay: false,
filter: false,
flanger: false,
wetDry: 0
},
currentDeck: null,
isRecording: false,
youtubeAPIReady: false
};
2025-08-03 16:51:12 +02:00
2025-08-03 17:09:00 +02:00
// YouTube API laden
function loadYouTubeAPI() {
// YouTube IFrame API Script laden
const tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
// YouTube API Ready Callback
window.onYouTubeIframeAPIReady = function() {
console.log('DJ System: YouTube API ready');
2025-08-03 17:46:16 +02:00
djInterface.youtubeAPIReady = true;
2025-08-03 17:09:00 +02:00
};
2025-08-03 17:46:16 +02:00
// Hier ist die fehlende Funktion
function createYouTubePlayerForDeck(deck, videoId) {
if (!djInterface.youtubeAPIReady) {
console.error('DJ System: YouTube API not ready');
showNotification('YouTube API not ready', 'error');
return;
}
// Container für YouTube Player erstellen
const containerId = `youtube-player-${deck.toLowerCase()}`;
let container = document.getElementById(containerId);
if (!container) {
container = document.createElement('div');
container.id = containerId;
container.style.position = 'absolute';
container.style.top = '-9999px';
container.style.left = '-9999px';
container.style.width = '1px';
container.style.height = '1px';
container.style.opacity = '0';
document.body.appendChild(container);
}
// Bestehenden Player zerstören, falls vorhanden
if (djInterface.decks[deck].youtubePlayer) {
try {
djInterface.decks[deck].youtubePlayer.destroy();
} catch (e) {
console.error('DJ System: Error destroying YouTube player', e);
}
}
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
// Neuen Player erstellen
djInterface.decks[deck].youtubePlayer = new YT.Player(containerId, {
2025-08-03 17:09:00 +02:00
height: '1',
width: '1',
2025-08-03 17:46:16 +02:00
videoId: videoId,
2025-08-03 17:09:00 +02:00
playerVars: {
'autoplay': 0,
'controls': 0,
'disablekb': 1,
'fs': 0,
'modestbranding': 1,
'playsinline': 1,
'rel': 0,
'showinfo': 0,
'iv_load_policy': 3,
'cc_load_policy': 0,
'origin': window.location.origin
},
events: {
2025-08-03 17:46:16 +02:00
'onReady': function(event) {
console.log(`DJ System: YouTube player ready for Deck ${deck}`);
// Setze Lautstärke
event.target.setVolume(djInterface.decks[deck].volume);
// Generiere Waveform
generateWaveform(deck, videoId);
// Aktualisiere UI
const vinyl = document.getElementById(`vinyl-${deck.toLowerCase()}`);
if (vinyl) {
vinyl.classList.add('loaded');
}
},
'onStateChange': function(event) {
handleYouTubeStateChange(deck, event);
},
'onError': function(event) {
handleYouTubeError(deck, event);
}
2025-08-03 17:09:00 +02:00
}
2025-08-03 16:51:12 +02:00
});
2025-08-03 17:09:00 +02:00
}
2025-08-03 17:46:16 +02:00
// YouTube State Change Handler
function handleYouTubeStateChange(deck, event) {
const deckData = djInterface.decks[deck];
const playBtn = document.getElementById(`play-${deck.toLowerCase()}`);
const vinyl = document.getElementById(`vinyl-${deck.toLowerCase()}`);
2025-08-03 17:09:00 +02:00
switch(event.data) {
case YT.PlayerState.PLAYING:
2025-08-03 17:46:16 +02:00
console.log(`DJ System: YouTube playing on Deck ${deck}`);
deckData.isPlaying = true;
if (playBtn) {
playBtn.innerHTML = '<i class="fas fa-pause"></i>';
playBtn.classList.add('playing');
}
if (vinyl) {
vinyl.classList.add('spinning');
}
// Notify FiveM
notifyFiveM('deckStateChanged', {
deck: deck,
isPlaying: true,
track: deckData.track
});
2025-08-03 17:09:00 +02:00
break;
2025-08-03 17:46:16 +02:00
2025-08-03 17:09:00 +02:00
case YT.PlayerState.PAUSED:
2025-08-03 17:46:16 +02:00
console.log(`DJ System: YouTube paused on Deck ${deck}`);
deckData.isPlaying = false;
if (playBtn) {
playBtn.innerHTML = '<i class="fas fa-play"></i>';
playBtn.classList.remove('playing');
}
if (vinyl) {
vinyl.classList.remove('spinning');
}
// Notify FiveM
notifyFiveM('deckStateChanged', {
deck: deck,
isPlaying: false,
track: deckData.track
});
2025-08-03 17:09:00 +02:00
break;
2025-08-03 17:46:16 +02:00
2025-08-03 17:09:00 +02:00
case YT.PlayerState.ENDED:
2025-08-03 17:46:16 +02:00
console.log(`DJ System: YouTube ended on Deck ${deck}`);
deckData.isPlaying = false;
if (playBtn) {
playBtn.innerHTML = '<i class="fas fa-play"></i>';
playBtn.classList.remove('playing');
}
if (vinyl) {
vinyl.classList.remove('spinning');
}
// Notify FiveM
notifyFiveM('songEnded', {
deck: deck
});
2025-08-03 17:09:00 +02:00
break;
}
}
2025-08-03 17:46:16 +02:00
// YouTube Error Handler
function handleYouTubeError(deck, event) {
console.error(`DJ System: YouTube error on Deck ${deck}:`, event.data);
2025-08-03 17:09:00 +02:00
let errorMessage = 'YouTube Fehler';
switch(event.data) {
case 2:
errorMessage = 'Ungültige Video ID';
break;
case 5:
errorMessage = 'HTML5 Player Fehler';
break;
case 100:
errorMessage = 'Video nicht gefunden';
break;
case 101:
case 150:
errorMessage = 'Video nicht verfügbar (Einbettung deaktiviert)';
break;
}
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
showNotification(errorMessage, 'error');
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
// Notify FiveM
notifyFiveM('audioError', {
deck: deck,
error: errorMessage
2025-08-03 16:51:12 +02:00
});
}
2025-08-03 17:46:16 +02:00
// Füge den Rest deines bestehenden script.js-Codes hier ein
// ...
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
// Initialize DJ Interface
document.addEventListener('DOMContentLoaded', function() {
initializeDJSystem();
setupEventListeners();
startAnimations();
loadYouTubeAPI();
});
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
// Funktion zum Extrahieren der YouTube Video ID
function extractYouTubeVideoId(url) {
const patterns = [
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
/youtube\.com\/watch\?.*v=([^&\n?#]+)/
];
2025-08-03 17:09:00 +02:00
2025-08-03 17:46:16 +02:00
for (let pattern of patterns) {
const match = url.match(pattern);
if (match && match[1]) {
return match[1];
2025-08-03 17:09:00 +02:00
}
2025-08-03 16:51:12 +02:00
}
2025-08-03 17:46:16 +02:00
return null;
2025-08-03 16:51:12 +02:00
}
2025-08-03 17:46:16 +02:00
// Prüfe ob es eine YouTube URL ist
2025-08-03 17:09:00 +02:00
function isYouTubeUrl(url) {
const youtubePatterns = [
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
/youtube\.com\/watch\?.*v=([^&\n?#]+)/
];
2025-08-03 16:51:12 +02:00
2025-08-03 17:09:00 +02:00
return youtubePatterns.some(pattern => pattern.test(url));
2025-08-03 16:51:12 +02:00
}
2025-08-03 17:46:16 +02:00
// Benachrichtigungen anzeigen
function showNotification(message, type = 'info') {
console.log(`DJ System [${type.toUpperCase()}]: ${message}`);
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
// Create notification element
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.textContent = message;
notification.style.cssText = `
position: fixed;
top: 80px;
right: 20px;
padding: 15px 20px;
border-radius: 10px;
color: white;
font-weight: 600;
z-index: 10000;
transform: translateX(100%);
transition: transform 0.3s ease;
background: ${type === 'error' ? '#ff6b6b' : type === 'success' ? '#4ecdc4' : type === 'warning' ? '#feca57' : '#45b7d1'};
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
`;
2025-08-03 16:51:12 +02:00
2025-08-03 17:46:16 +02:00
document.body.appendChild(notification);
// Animate in
setTimeout(() => {
notification.style.transform = 'translateX(0)';
}, 100);
// Remove after 3 seconds
setTimeout(() => {
notification.style.transform = 'translateX(100%)';
setTimeout(() => {
document.body.removeChild(notification);
}, 300);
}, 3000);
2025-08-03 16:51:12 +02:00
}
2025-08-03 17:09:00 +02:00
// FiveM benachrichtigen
function notifyFiveM(event, data) {
2025-08-03 17:36:16 +02:00
fetch(`https://${GetParentResourceName()}/${event}`, {
2025-08-03 16:51:12 +02:00
method: 'POST',
headers: {
2025-08-03 17:09:00 +02:00
'Content-Type': 'application/json'
2025-08-03 16:51:12 +02:00
},
2025-08-03 17:09:00 +02:00
body: JSON.stringify(data)
2025-08-03 16:51:12 +02:00
}).catch(err => {
2025-08-03 17:09:00 +02:00
console.error('DJ System: Failed to notify FiveM:', err);
2025-08-03 16:51:12 +02:00
});
}
function GetParentResourceName() {
return window.location.hostname;
}