forked from Simnation/Main
379 lines
10 KiB
JavaScript
379 lines
10 KiB
JavaScript
let audioPlayer = null;
|
|
let currentVolume = 50;
|
|
let isPlaying = false;
|
|
let currentSong = null;
|
|
let fadeInterval = null;
|
|
|
|
// YouTube Player API laden
|
|
let youtubeAPIReady = false;
|
|
let youtubePlayer = null;
|
|
|
|
// Initialize when page loads
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
loadYouTubeAPI();
|
|
setupAudioPlayer();
|
|
});
|
|
|
|
// 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');
|
|
youtubeAPIReady = true;
|
|
|
|
// Erstelle versteckten YouTube Player
|
|
createYouTubePlayer();
|
|
};
|
|
|
|
// YouTube Player erstellen
|
|
function createYouTubePlayer() {
|
|
// Container für YouTube Player
|
|
const playerContainer = document.createElement('div');
|
|
playerContainer.id = 'youtube-player-container';
|
|
playerContainer.style.position = 'absolute';
|
|
playerContainer.style.top = '-9999px';
|
|
playerContainer.style.left = '-9999px';
|
|
playerContainer.style.width = '1px';
|
|
playerContainer.style.height = '1px';
|
|
playerContainer.style.opacity = '0';
|
|
document.body.appendChild(playerContainer);
|
|
|
|
youtubePlayer = new YT.Player('youtube-player-container', {
|
|
height: '1',
|
|
width: '1',
|
|
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,
|
|
'start': 0,
|
|
'origin': window.location.origin
|
|
},
|
|
events: {
|
|
'onReady': onYouTubePlayerReady,
|
|
'onStateChange': onYouTubePlayerStateChange,
|
|
'onError': onYouTubePlayerError
|
|
}
|
|
});
|
|
}
|
|
|
|
function onYouTubePlayerReady(event) {
|
|
console.log('DJ System: YouTube Player ready');
|
|
}
|
|
|
|
function onYouTubePlayerStateChange(event) {
|
|
switch(event.data) {
|
|
case YT.PlayerState.PLAYING:
|
|
console.log('DJ System: YouTube playing');
|
|
isPlaying = true;
|
|
break;
|
|
case YT.PlayerState.PAUSED:
|
|
console.log('DJ System: YouTube paused');
|
|
isPlaying = false;
|
|
break;
|
|
case YT.PlayerState.ENDED:
|
|
console.log('DJ System: YouTube ended');
|
|
isPlaying = false;
|
|
notifyFiveM('songEnded', {});
|
|
break;
|
|
case YT.PlayerState.BUFFERING:
|
|
console.log('DJ System: YouTube buffering');
|
|
break;
|
|
}
|
|
}
|
|
|
|
function onYouTubePlayerError(event) {
|
|
console.error('DJ System: YouTube error:', event.data);
|
|
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;
|
|
}
|
|
|
|
notifyFiveM('audioError', { error: errorMessage });
|
|
}
|
|
|
|
// Setup normaler Audio Player für direkte URLs
|
|
function setupAudioPlayer() {
|
|
audioPlayer = document.getElementById('audio-player');
|
|
if (!audioPlayer) {
|
|
audioPlayer = document.createElement('audio');
|
|
audioPlayer.id = 'audio-player';
|
|
audioPlayer.style.display = 'none';
|
|
document.body.appendChild(audioPlayer);
|
|
}
|
|
|
|
audioPlayer.addEventListener('play', () => {
|
|
isPlaying = true;
|
|
console.log('DJ System: Audio playing');
|
|
});
|
|
|
|
audioPlayer.addEventListener('pause', () => {
|
|
isPlaying = false;
|
|
console.log('DJ System: Audio paused');
|
|
});
|
|
|
|
audioPlayer.addEventListener('ended', () => {
|
|
isPlaying = false;
|
|
notifyFiveM('songEnded', {});
|
|
});
|
|
|
|
audioPlayer.addEventListener('error', (e) => {
|
|
console.error('DJ System: Audio error', e);
|
|
notifyFiveM('audioError', { error: 'Audio playback error' });
|
|
});
|
|
}
|
|
|
|
// Main message handler
|
|
window.addEventListener('message', function(event) {
|
|
const data = event.data;
|
|
|
|
switch(data.type) {
|
|
case 'playMusic':
|
|
playMusic(data.url, data.volume, data.title);
|
|
break;
|
|
case 'stopMusic':
|
|
stopMusic();
|
|
break;
|
|
case 'setVolume':
|
|
setVolume(data.volume);
|
|
break;
|
|
case 'pauseMusic':
|
|
pauseMusic();
|
|
break;
|
|
case 'resumeMusic':
|
|
resumeMusic();
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Musik abspielen - YouTube oder direkte URL
|
|
async function playMusic(url, volume, title = 'Unknown') {
|
|
try {
|
|
console.log('DJ System: Playing:', title, url);
|
|
|
|
// Stoppe aktuelle Musik
|
|
stopMusic();
|
|
|
|
// Setze Lautstärke
|
|
currentVolume = volume || 50;
|
|
|
|
// Prüfe ob YouTube URL
|
|
if (isYouTubeUrl(url)) {
|
|
await playYouTubeMusic(url, volume, title);
|
|
} else {
|
|
await playDirectMusic(url, volume, title);
|
|
}
|
|
|
|
// Speichere aktuelle Song Info
|
|
currentSong = {
|
|
title: title,
|
|
url: url,
|
|
volume: volume
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('DJ System: Error playing music:', error);
|
|
notifyFiveM('audioError', { error: error.message });
|
|
}
|
|
}
|
|
|
|
// YouTube Musik abspielen
|
|
async function playYouTubeMusic(url, volume, title) {
|
|
if (!youtubeAPIReady || !youtubePlayer) {
|
|
throw new Error('YouTube Player nicht bereit');
|
|
}
|
|
|
|
const videoId = extractYouTubeVideoId(url);
|
|
if (!videoId) {
|
|
throw new Error('Ungültige YouTube URL');
|
|
}
|
|
|
|
console.log('DJ System: Playing YouTube video:', videoId);
|
|
|
|
// Lade und spiele YouTube Video
|
|
youtubePlayer.loadVideoById({
|
|
videoId: videoId,
|
|
startSeconds: 0
|
|
});
|
|
|
|
// Setze Lautstärke
|
|
youtubePlayer.setVolume(volume || 50);
|
|
|
|
// Warte kurz und starte
|
|
setTimeout(() => {
|
|
youtubePlayer.playVideo();
|
|
}, 1000);
|
|
}
|
|
|
|
// Direkte Audio URL abspielen
|
|
async function playDirectMusic(url, volume, title) {
|
|
if (!audioPlayer) {
|
|
throw new Error('Audio Player nicht verfügbar');
|
|
}
|
|
|
|
console.log('DJ System: Playing direct audio:', url);
|
|
|
|
audioPlayer.src = url;
|
|
audioPlayer.volume = (volume || 50) / 100;
|
|
audioPlayer.load();
|
|
|
|
const playPromise = audioPlayer.play();
|
|
if (playPromise !== undefined) {
|
|
await playPromise;
|
|
}
|
|
}
|
|
|
|
// Musik stoppen
|
|
function stopMusic() {
|
|
try {
|
|
// Stoppe YouTube Player
|
|
if (youtubePlayer && youtubeAPIReady) {
|
|
youtubePlayer.stopVideo();
|
|
}
|
|
|
|
// Stoppe Audio Player
|
|
if (audioPlayer) {
|
|
audioPlayer.pause();
|
|
audioPlayer.currentTime = 0;
|
|
audioPlayer.src = '';
|
|
}
|
|
|
|
isPlaying = false;
|
|
currentSong = null;
|
|
|
|
console.log('DJ System: Music stopped');
|
|
|
|
} catch (error) {
|
|
console.error('DJ System: Error stopping music:', error);
|
|
}
|
|
}
|
|
|
|
// Musik pausieren
|
|
function pauseMusic() {
|
|
try {
|
|
if (currentSong && isYouTubeUrl(currentSong.url)) {
|
|
if (youtubePlayer && youtubeAPIReady) {
|
|
youtubePlayer.pauseVideo();
|
|
}
|
|
} else if (audioPlayer) {
|
|
audioPlayer.pause();
|
|
}
|
|
} catch (error) {
|
|
console.error('DJ System: Error pausing music:', error);
|
|
}
|
|
}
|
|
|
|
// Musik fortsetzen
|
|
function resumeMusic() {
|
|
try {
|
|
if (currentSong && isYouTubeUrl(currentSong.url)) {
|
|
if (youtubePlayer && youtubeAPIReady) {
|
|
youtubePlayer.playVideo();
|
|
}
|
|
} else if (audioPlayer) {
|
|
audioPlayer.play();
|
|
}
|
|
} catch (error) {
|
|
console.error('DJ System: Error resuming music:', error);
|
|
}
|
|
}
|
|
|
|
// Lautstärke setzen
|
|
function setVolume(volume) {
|
|
try {
|
|
currentVolume = Math.max(0, Math.min(100, volume));
|
|
|
|
if (currentSong && isYouTubeUrl(currentSong.url)) {
|
|
if (youtubePlayer && youtubeAPIReady) {
|
|
youtubePlayer.setVolume(currentVolume);
|
|
}
|
|
} else if (audioPlayer) {
|
|
audioPlayer.volume = currentVolume / 100;
|
|
}
|
|
|
|
console.log('DJ System: Volume set to', currentVolume + '%');
|
|
} catch (error) {
|
|
console.error('DJ System: Error setting volume:', error);
|
|
}
|
|
}
|
|
|
|
// YouTube URL prüfen
|
|
function isYouTubeUrl(url) {
|
|
const youtubePatterns = [
|
|
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
|
|
/youtube\.com\/watch\?.*v=([^&\n?#]+)/
|
|
];
|
|
|
|
return youtubePatterns.some(pattern => pattern.test(url));
|
|
}
|
|
|
|
// YouTube Video ID extrahieren
|
|
function extractYouTubeVideoId(url) {
|
|
const patterns = [
|
|
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
|
|
/youtube\.com\/watch\?.*v=([^&\n?#]+)/
|
|
];
|
|
|
|
for (let pattern of patterns) {
|
|
const match = url.match(pattern);
|
|
if (match && match[1]) {
|
|
return match[1];
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// FiveM benachrichtigen
|
|
function notifyFiveM(event, data) {
|
|
fetch(`https://${GetParentResourceName()}/` + event, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(data)
|
|
}).catch(err => {
|
|
console.error('DJ System: Failed to notify FiveM:', err);
|
|
});
|
|
}
|
|
|
|
function GetParentResourceName() {
|
|
return window.location.hostname;
|
|
}
|
|
|
|
// Debug
|
|
window.djDebug = {
|
|
getCurrentSong: () => currentSong,
|
|
getVolume: () => currentVolume,
|
|
isPlaying: () => isPlaying,
|
|
youtubeReady: () => youtubeAPIReady,
|
|
testYouTube: (videoId) => playYouTubeMusic('https://www.youtube.com/watch?v=' + videoId, 50, 'Test')
|
|
};
|
|
|
|
console.log('DJ System: YouTube streaming system loaded');
|