forked from Simnation/Main
ed
This commit is contained in:
parent
0e29315dd1
commit
e0a3b21c61
7 changed files with 1463 additions and 0 deletions
401
resources/[tools]/nordi_dj/html/script.js
Normal file
401
resources/[tools]/nordi_dj/html/script.js
Normal file
|
@ -0,0 +1,401 @@
|
|||
let audioPlayer = null;
|
||||
let currentVolume = 50;
|
||||
let isPlaying = false;
|
||||
let currentSong = null;
|
||||
let fadeInterval = null;
|
||||
|
||||
// Initialize when page loads
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
audioPlayer = document.getElementById('audio-player');
|
||||
setupAudioPlayer();
|
||||
});
|
||||
|
||||
// Setup audio player with event listeners
|
||||
function setupAudioPlayer() {
|
||||
if (!audioPlayer) return;
|
||||
|
||||
// Audio Events
|
||||
audioPlayer.addEventListener('loadstart', function() {
|
||||
console.log('DJ System: Loading started');
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('canplay', function() {
|
||||
console.log('DJ System: Can start playing');
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('play', function() {
|
||||
console.log('DJ System: Playback started');
|
||||
isPlaying = true;
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('pause', function() {
|
||||
console.log('DJ System: Playback paused');
|
||||
isPlaying = false;
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('ended', function() {
|
||||
console.log('DJ System: Song ended');
|
||||
isPlaying = false;
|
||||
// Notify FiveM that song ended (for playlist functionality)
|
||||
fetch(`https://${GetParentResourceName()}/songEnded`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('error', function(e) {
|
||||
console.error('DJ System: Audio error', e);
|
||||
isPlaying = false;
|
||||
// Notify FiveM about the error
|
||||
fetch(`https://${GetParentResourceName()}/audioError`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
error: 'Audio playback error',
|
||||
code: audioPlayer.error ? audioPlayer.error.code : 'unknown'
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('loadedmetadata', function() {
|
||||
console.log('DJ System: Metadata loaded, duration:', audioPlayer.duration);
|
||||
});
|
||||
|
||||
audioPlayer.addEventListener('timeupdate', function() {
|
||||
// Optional: Send progress updates
|
||||
if (isPlaying && audioPlayer.duration) {
|
||||
const progress = (audioPlayer.currentTime / audioPlayer.duration) * 100;
|
||||
// You can use this for progress bars if needed
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Main message handler from FiveM
|
||||
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 'fadeOut':
|
||||
fadeOut();
|
||||
break;
|
||||
case 'fadeIn':
|
||||
fadeIn();
|
||||
break;
|
||||
case 'pauseMusic':
|
||||
pauseMusic();
|
||||
break;
|
||||
case 'resumeMusic':
|
||||
resumeMusic();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Play music function with YouTube support
|
||||
async function playMusic(url, volume, title = 'Unknown') {
|
||||
if (!audioPlayer) {
|
||||
console.error('DJ System: Audio player not initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Stop current music first
|
||||
stopMusic();
|
||||
|
||||
console.log('DJ System: Attempting to play:', title, url);
|
||||
|
||||
// Set volume
|
||||
currentVolume = volume || 50;
|
||||
audioPlayer.volume = currentVolume / 100;
|
||||
|
||||
// Handle different URL types
|
||||
let playableUrl = await processUrl(url);
|
||||
|
||||
if (!playableUrl) {
|
||||
console.error('DJ System: Could not process URL:', url);
|
||||
notifyError('Could not process audio URL');
|
||||
return;
|
||||
}
|
||||
|
||||
// Set source and play
|
||||
audioPlayer.src = playableUrl;
|
||||
audioPlayer.load();
|
||||
|
||||
// Store current song info
|
||||
currentSong = {
|
||||
title: title,
|
||||
url: url,
|
||||
playableUrl: playableUrl
|
||||
};
|
||||
|
||||
// Attempt to play
|
||||
const playPromise = audioPlayer.play();
|
||||
|
||||
if (playPromise !== undefined) {
|
||||
playPromise
|
||||
.then(() => {
|
||||
console.log('DJ System: Successfully started playing:', title);
|
||||
isPlaying = true;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('DJ System: Play failed:', error);
|
||||
notifyError('Playback failed: ' + error.message);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error in playMusic:', error);
|
||||
notifyError('Error playing music: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Process different URL types
|
||||
async function processUrl(url) {
|
||||
try {
|
||||
// Check if it's a YouTube URL
|
||||
if (isYouTubeUrl(url)) {
|
||||
console.log('DJ System: Processing YouTube URL');
|
||||
return await convertYouTubeUrl(url);
|
||||
}
|
||||
|
||||
// Check if it's a direct audio URL
|
||||
if (isDirectAudioUrl(url)) {
|
||||
console.log('DJ System: Direct audio URL detected');
|
||||
return url;
|
||||
}
|
||||
|
||||
// Try to use URL as-is (might be pre-converted)
|
||||
console.log('DJ System: Using URL as-is');
|
||||
return url;
|
||||
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error processing URL:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if URL is YouTube
|
||||
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));
|
||||
}
|
||||
|
||||
// Check if URL is direct audio
|
||||
function isDirectAudioUrl(url) {
|
||||
const audioExtensions = ['.mp3', '.wav', '.ogg', '.m4a', '.aac', '.flac'];
|
||||
const lowerUrl = url.toLowerCase();
|
||||
|
||||
return audioExtensions.some(ext => lowerUrl.includes(ext)) ||
|
||||
lowerUrl.includes('audio/') ||
|
||||
lowerUrl.includes('stream');
|
||||
}
|
||||
|
||||
// Convert YouTube URL (this would be handled server-side in real implementation)
|
||||
async function convertYouTubeUrl(url) {
|
||||
try {
|
||||
// Extract video ID
|
||||
const videoId = extractYouTubeVideoId(url);
|
||||
if (!videoId) {
|
||||
throw new Error('Could not extract YouTube video ID');
|
||||
}
|
||||
|
||||
console.log('DJ System: YouTube Video ID:', videoId);
|
||||
|
||||
// In a real implementation, this would call your server-side converter
|
||||
// For now, we'll return the original URL and let the server handle it
|
||||
return url;
|
||||
|
||||
} catch (error) {
|
||||
console.error('DJ System: YouTube conversion error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract YouTube video ID
|
||||
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;
|
||||
}
|
||||
|
||||
// Stop music
|
||||
function stopMusic() {
|
||||
if (!audioPlayer) return;
|
||||
|
||||
try {
|
||||
audioPlayer.pause();
|
||||
audioPlayer.currentTime = 0;
|
||||
audioPlayer.src = '';
|
||||
isPlaying = false;
|
||||
currentSong = null;
|
||||
|
||||
// Clear any fade effects
|
||||
if (fadeInterval) {
|
||||
clearInterval(fadeInterval);
|
||||
fadeInterval = null;
|
||||
}
|
||||
|
||||
console.log('DJ System: Music stopped');
|
||||
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error stopping music:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Pause music
|
||||
function pauseMusic() {
|
||||
if (!audioPlayer || !isPlaying) return;
|
||||
|
||||
try {
|
||||
audioPlayer.pause();
|
||||
isPlaying = false;
|
||||
console.log('DJ System: Music paused');
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error pausing music:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Resume music
|
||||
function resumeMusic() {
|
||||
if (!audioPlayer || isPlaying) return;
|
||||
|
||||
try {
|
||||
const playPromise = audioPlayer.play();
|
||||
if (playPromise !== undefined) {
|
||||
playPromise
|
||||
.then(() => {
|
||||
isPlaying = true;
|
||||
console.log('DJ System: Music resumed');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('DJ System: Resume failed:', error);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error resuming music:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Set volume
|
||||
function setVolume(volume) {
|
||||
if (!audioPlayer) return;
|
||||
|
||||
try {
|
||||
currentVolume = Math.max(0, Math.min(100, volume));
|
||||
audioPlayer.volume = currentVolume / 100;
|
||||
console.log('DJ System: Volume set to', currentVolume + '%');
|
||||
} catch (error) {
|
||||
console.error('DJ System: Error setting volume:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Fade out effect (when player moves away)
|
||||
function fadeOut() {
|
||||
if (!audioPlayer || !isPlaying) return;
|
||||
|
||||
if (fadeInterval) {
|
||||
clearInterval(fadeInterval);
|
||||
}
|
||||
|
||||
let currentVol = audioPlayer.volume;
|
||||
const targetVol = 0;
|
||||
const fadeStep = 0.05;
|
||||
|
||||
fadeInterval = setInterval(() => {
|
||||
currentVol -= fadeStep;
|
||||
if (currentVol <= targetVol) {
|
||||
currentVol = targetVol;
|
||||
audioPlayer.volume = currentVol;
|
||||
clearInterval(fadeInterval);
|
||||
fadeInterval = null;
|
||||
} else {
|
||||
audioPlayer.volume = currentVol;
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// Fade in effect (when player moves closer)
|
||||
function fadeIn() {
|
||||
if (!audioPlayer || !isPlaying) return;
|
||||
|
||||
if (fadeInterval) {
|
||||
clearInterval(fadeInterval);
|
||||
}
|
||||
|
||||
let currentVol = audioPlayer.volume;
|
||||
const targetVol = currentVolume / 100;
|
||||
const fadeStep = 0.05;
|
||||
|
||||
fadeInterval = setInterval(() => {
|
||||
currentVol += fadeStep;
|
||||
if (currentVol >= targetVol) {
|
||||
currentVol = targetVol;
|
||||
audioPlayer.volume = currentVol;
|
||||
clearInterval(fadeInterval);
|
||||
fadeInterval = null;
|
||||
} else {
|
||||
audioPlayer.volume = currentVol;
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
||||
// Notify FiveM about errors
|
||||
function notifyError(message) {
|
||||
fetch(`https://${GetParentResourceName()}/audioError`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
error: message
|
||||
})
|
||||
}).catch(err => {
|
||||
console.error('DJ System: Failed to notify error:', err);
|
||||
});
|
||||
}
|
||||
|
||||
// Get current resource name
|
||||
function GetParentResourceName() {
|
||||
return window.location.hostname;
|
||||
}
|
||||
|
||||
// Debug functions (can be called from browser console)
|
||||
window.djDebug = {
|
||||
getCurrentSong: () => currentSong,
|
||||
getVolume: () => currentVolume,
|
||||
isPlaying: () => isPlaying,
|
||||
getAudioPlayer: () => audioPlayer,
|
||||
testPlay: (url) => playMusic(url, 50, 'Test Song'),
|
||||
testStop: () => stopMusic(),
|
||||
testVolume: (vol) => setVolume(vol)
|
||||
};
|
||||
|
||||
// Log when script is loaded
|
||||
console.log('DJ System: Script loaded and ready');
|
Loading…
Add table
Add a link
Reference in a new issue