![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/.cursor-server/data/User/History/-109ca8d5/ |
<?php
// Global Music Player - Persistent Across AJAX Navigation
// This player will be included in the main layout and stay active during page navigation
// Prevent multiple includes
if (defined('GLOBAL_PLAYER_INCLUDED')) {
return;
}
define('GLOBAL_PLAYER_INCLUDED', true);
// Check if global player is enabled
require_once __DIR__ . '/site_settings_helper.php';
// Temporarily force enable the global player
// if (!isGlobalPlayerEnabled()) {
// return; // Don't show the player if disabled
// }
// Use external CDN tracks only - no database queries
$lastCommunitySong = null;
?>
<!-- Global Music Player -->
<div id="globalMusicPlayer" class="global-music-player">
<div class="player-container">
<!-- Track Info -->
<div class="track-info">
<div class="track-details">
<div class="track-title" id="globalTrackTitle">
Community Music Ready
</div>
<div class="track-artist" id="globalTrackArtist">
<span id="globalTrackArtistName">Loading community tracks...</span>
<span id="globalTrackCount" style="display: none; color: #48bb78; font-size: 0.8em;"></span>
<a href="#" id="globalTrackArtistLink" class="artist-link" style="display: none;">
<i class="fas fa-user"></i> View Profile
</a>
</div>
</div>
</div>
<!-- Controls -->
<div class="player-controls">
<button class="control-btn" id="globalPrevBtn">
<i class="fas fa-step-backward"></i>
</button>
<button class="control-btn play-btn" id="globalPlayBtn">
<i class="fas fa-play" id="globalPlayIcon"></i>
</button>
<button class="control-btn" id="globalStopBtn">
<i class="fas fa-stop"></i>
</button>
<button class="control-btn" id="globalNextBtn">
<i class="fas fa-step-forward"></i>
</button>
</div>
<!-- Progress Bar -->
<div class="progress-container">
<div class="progress-bar" id="globalProgressBar">
<div class="progress-fill" id="globalProgressFill"></div>
</div>
<div class="time-display">
<span id="globalCurrentTime">0:00</span>
<span id="globalTotalTime">0:00</span>
</div>
</div>
<!-- Volume Control -->
<div class="volume-control">
<i class="fas fa-volume-up" id="globalVolumeIcon"></i>
<input type="range" id="globalVolumeSlider" min="0" max="100" value="50" class="volume-slider">
</div>
<!-- Shuffle Toggle -->
<button class="shuffle-toggle" id="globalShuffleToggle" title="Toggle Shuffle">
<i class="fas fa-random"></i>
</button>
<!-- Playlist Toggle -->
<button class="playlist-toggle" id="globalPlaylistToggle">
<i class="fas fa-list"></i>
</button>
</div>
<!-- Playlist Panel -->
<div class="playlist-panel" id="globalPlaylistPanel">
<div class="playlist-header">
<h3>Community Playlist</h3>
<button class="close-playlist" id="globalClosePlaylist">
<i class="fas fa-times"></i>
</button>
</div>
<div class="playlist-tracks" id="globalPlaylistTracks">
<div class="playlist-loading" id="playlistLoading">
<i class="fas fa-spinner fa-spin"></i>
<span>Loading community tracks...</span>
</div>
</div>
</div>
</div>
<style>
/* Global Music Player Styles */
.global-music-player {
position: fixed !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
background: rgba(10, 10, 10, 0.95) !important;
backdrop-filter: blur(20px) !important;
border-top: 1px solid rgba(255, 255, 255, 0.1) !important;
z-index: 9999 !important;
padding: 1rem 2rem !important;
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
min-height: 80px !important;
transform: translateY(0) !important;
transition: transform 0.3s ease !important;
opacity: 1 !important;
visibility: visible !important;
display: flex !important;
max-height: none !important;
overflow: visible !important;
clip: auto !important;
clip-path: none !important;
}
.global-music-player.active {
transform: translateY(0);
opacity: 1;
visibility: visible;
}
.player-container {
display: flex;
align-items: center;
gap: 2rem;
flex: 1;
max-width: 1200px;
margin: 0 auto;
}
.track-info {
flex: 1;
min-width: 200px;
}
.track-details {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.track-title {
font-size: 1.4rem;
font-weight: 600;
color: white;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.track-artist {
font-size: 1.2rem;
color: #a0aec0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
align-items: center;
gap: 1rem;
}
.artist-link {
color: #667eea;
text-decoration: none;
font-size: 1rem;
padding: 0.3rem 0.8rem;
border-radius: 12px;
background: rgba(102, 126, 234, 0.1);
border: 1px solid rgba(102, 126, 234, 0.2);
transition: all 0.3s ease;
white-space: nowrap;
}
.artist-link:hover {
background: rgba(102, 126, 234, 0.2);
border-color: rgba(102, 126, 234, 0.4);
transform: translateY(-1px);
}
.player-controls {
display: flex;
align-items: center;
gap: 1rem;
}
.control-btn {
background: rgba(255, 255, 255, 0.1);
border: none;
color: white;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
.play-btn {
width: 50px;
height: 50px;
background: linear-gradient(135deg, #667eea, #764ba2);
}
.play-btn:hover {
background: linear-gradient(135deg, #5a67d8, #6b46c1);
}
.progress-container {
flex: 2;
display: flex;
flex-direction: column;
gap: 0.5rem;
min-width: 300px;
}
.progress-bar {
width: 100%;
height: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
cursor: pointer;
position: relative;
}
.progress-fill {
height: 100%;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 2px;
width: 0%;
transition: width 0.1s ease;
}
.time-display {
display: flex;
justify-content: space-between;
font-size: 1.2rem;
color: #a0aec0;
}
.volume-control {
display: flex;
align-items: center;
gap: 1rem;
min-width: 150px;
padding: 0.5rem;
border-radius: 8px;
transition: all 0.3s ease;
cursor: ns-resize;
}
.volume-control:hover {
background: rgba(255, 255, 255, 0.05);
transform: scale(1.02);
border: 1px solid rgba(102, 126, 234, 0.3);
}
.volume-control::after {
content: "🖱️ Scroll to adjust volume • Hold Shift for larger steps";
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.9);
color: white;
padding: 0.8rem 1.2rem;
border-radius: 8px;
font-size: 0.9rem;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.3s ease;
z-index: 10001;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.volume-control:hover::after {
opacity: 1;
}
.volume-control i {
color: #a0aec0;
font-size: 1.4rem;
}
.volume-slider {
flex: 1;
height: 4px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
outline: none;
cursor: pointer;
}
.volume-slider::-webkit-slider-thumb {
appearance: none;
width: 12px;
height: 12px;
background: #667eea;
border-radius: 50%;
cursor: pointer;
}
.playlist-toggle {
background: rgba(255, 255, 255, 0.1);
border: none;
color: white;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.playlist-toggle:hover {
background: rgba(255, 255, 255, 0.2);
}
.shuffle-toggle {
background: rgba(255, 255, 255, 0.1);
border: none;
color: white;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
}
.shuffle-toggle:hover {
background: rgba(255, 255, 255, 0.2);
}
.shuffle-toggle.active {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.playlist-panel {
position: fixed;
bottom: 80px;
right: 2rem;
width: 350px;
max-height: 400px;
background: rgba(10, 10, 10, 0.95);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
display: none;
flex-direction: column;
z-index: 10000;
}
.playlist-panel.active {
display: flex;
}
.playlist-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.playlist-header h3 {
color: white;
font-size: 1.6rem;
font-weight: 600;
}
.close-playlist {
background: none;
border: none;
color: #a0aec0;
cursor: pointer;
font-size: 1.4rem;
}
.playlist-tracks {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.playlist-track {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
margin-bottom: 0.5rem;
}
.playlist-track:hover {
background: rgba(255, 255, 255, 0.1);
}
.playlist-track.active {
background: rgba(102, 126, 234, 0.2);
border-left: 3px solid #667eea;
}
.playlist-track-info {
flex: 1;
min-width: 0;
}
.playlist-track-title {
font-size: 1.3rem;
color: white;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.playlist-track-artist {
font-size: 1.1rem;
color: #a0aec0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.playlist-loading {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
padding: 2rem;
color: #a0aec0;
font-size: 1.4rem;
}
.playlist-loading i {
font-size: 1.6rem;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.global-music-player {
padding: 0.8rem 1rem;
min-height: 60px;
}
.player-container {
gap: 0.8rem;
flex-wrap: wrap;
}
.track-info {
min-width: 100px;
flex: 1;
min-width: 0;
}
.track-title {
font-size: 1.2rem;
}
.track-artist {
font-size: 1rem;
}
.player-controls {
gap: 0.5rem;
flex-shrink: 0;
}
.control-btn {
width: 35px;
height: 35px;
font-size: 1rem;
}
.play-btn {
width: 40px;
height: 40px;
}
.progress-container {
min-width: 120px;
flex: 1;
min-width: 0;
}
.progress-bar {
height: 4px;
}
.time-display {
font-size: 1rem;
}
.volume-control {
min-width: 80px;
flex-shrink: 0;
}
.volume-slider {
width: 60px;
}
.playlist-toggle {
width: 35px;
height: 35px;
font-size: 1rem;
}
.playlist-panel {
width: calc(100vw - 2rem);
right: 1rem;
left: 1rem;
bottom: 80px;
max-height: 400px;
}
}
@media (max-width: 480px) {
.global-music-player {
padding: 0.6rem 0.8rem;
min-height: 55px;
}
.player-container {
gap: 0.5rem;
}
.track-title {
font-size: 1.1rem;
}
.track-artist {
font-size: 0.9rem;
}
.control-btn {
width: 30px;
height: 30px;
font-size: 0.9rem;
}
.play-btn {
width: 35px;
height: 35px;
}
.progress-container {
min-width: 100px;
}
.time-display {
font-size: 0.9rem;
}
.volume-control {
min-width: 60px;
}
.volume-slider {
width: 50px;
}
.playlist-toggle {
width: 30px;
height: 30px;
font-size: 0.9rem;
}
.playlist-panel {
width: calc(100vw - 1rem);
right: 0.5rem;
left: 0.5rem;
bottom: 70px;
}
}
</style>
<script>
console.log('🎵 SCRIPT STARTING - Global player script is loading...');
// Global Music Player JavaScript
const globalPlayer = {
audio: null,
playlist: [],
currentTrackIndex: -1,
isPlaying: false,
wasPlaying: false,
volume: localStorage.getItem('globalPlayerVolume') ? parseFloat(localStorage.getItem('globalPlayerVolume')) : 0.5,
shuffleMode: localStorage.getItem('globalPlayerShuffle') === 'true',
shuffleHistory: [],
initialized: false,
initializationPromise: null,
init() {
// Prevent multiple initializations
if (this.initialized) {
console.log('🎵 Global player already initialized');
return Promise.resolve();
}
if (this.initializationPromise) {
console.log('🎵 Global player initialization already in progress');
return this.initializationPromise;
}
this.initializationPromise = new Promise(async (resolve, reject) => {
console.log('🎵 Global player initializing...');
try {
this.setupEventListeners();
// Initialize user interaction flag
this.userInteracted = false;
// Show player immediately
this.showPlayer();
// Load community playlist
console.log('🎵 Loading community playlist...');
try {
await this.loadCommunityPlaylist();
console.log('🎵 Community playlist loaded successfully');
} catch (error) {
console.error('🎵 Failed to load community playlist:', error);
// Continue anyway - player can still play individual tracks
}
this.initialized = true;
console.log('🎵 Global player initialization complete');
resolve();
// Debug: Log initial state
console.log('🎵 Initial player state:', {
playlistLength: this.playlist.length,
currentTrackIndex: this.currentTrackIndex,
isPlaying: this.isPlaying
});
} catch (error) {
console.error('🎵 Error during global player initialization:', error);
reject(error);
}
});
return this.initializationPromise;
},
setupEventListeners() {
console.log('🎵 Setting up event listeners...');
// Play button
const playBtn = document.getElementById('globalPlayBtn');
if (playBtn) {
playBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Play button clicked!');
this.userInteracted = true;
this.togglePlayPause();
});
}
// Previous button
const prevBtn = document.getElementById('globalPrevBtn');
if (prevBtn) {
prevBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Previous button clicked');
this.previousTrack();
});
}
// Stop button
const stopBtn = document.getElementById('globalStopBtn');
if (stopBtn) {
stopBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Stop button clicked!');
this.stopTrack();
});
}
// Next button
const nextBtn = document.getElementById('globalNextBtn');
if (nextBtn) {
nextBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Next button clicked');
this.nextTrack();
});
}
// Volume slider
const volumeSlider = document.getElementById('globalVolumeSlider');
if (volumeSlider) {
volumeSlider.value = this.volume * 100;
volumeSlider.addEventListener('input', (e) => {
this.volume = e.target.value / 100;
console.log('🎵 Volume changed to:', this.volume);
if (this.audio) {
this.audio.volume = this.volume;
}
this.updateVolumeIcon();
localStorage.setItem('globalPlayerVolume', this.volume);
});
this.updateVolumeIcon();
}
// Volume control mouse wheel
const volumeControl = document.querySelector('.volume-control');
if (volumeControl) {
volumeControl.addEventListener('wheel', (e) => {
e.preventDefault();
e.stopPropagation();
// Determine scroll direction and amount
const delta = e.deltaY > 0 ? -1 : 1;
const step = e.shiftKey ? 10 : 5; // Larger steps with Shift key
// Calculate new volume
let newVolume = this.volume + (delta * step / 100);
newVolume = Math.max(0, Math.min(1, newVolume)); // Clamp between 0 and 1
// Update volume
this.volume = newVolume;
if (this.audio) {
this.audio.volume = this.volume;
}
// Update slider
if (volumeSlider) {
volumeSlider.value = this.volume * 100;
}
// Update icon and save
this.updateVolumeIcon();
localStorage.setItem('globalPlayerVolume', this.volume);
// Visual feedback
volumeControl.style.background = 'rgba(102, 126, 234, 0.2)';
setTimeout(() => {
volumeControl.style.background = '';
}, 200);
console.log('🎵 Volume changed via mouse wheel to:', this.volume);
});
}
// Shuffle toggle
const shuffleToggle = document.getElementById('globalShuffleToggle');
if (shuffleToggle) {
shuffleToggle.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Shuffle toggle clicked');
this.toggleShuffle();
});
this.updateShuffleButton();
}
// Playlist toggle
const playlistToggle = document.getElementById('globalPlaylistToggle');
if (playlistToggle) {
playlistToggle.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Playlist toggle clicked');
this.togglePlaylist();
});
}
// Close playlist
const closePlaylist = document.getElementById('globalClosePlaylist');
if (closePlaylist) {
closePlaylist.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('🎵 Close playlist clicked');
this.togglePlaylist();
});
}
// Progress bar
const progressBar = document.getElementById('globalProgressBar');
if (progressBar) {
progressBar.addEventListener('click', (e) => {
if (this.audio && this.audio.duration && !isNaN(this.audio.duration)) {
const rect = e.target.getBoundingClientRect();
const percent = (e.clientX - rect.left) / rect.width;
const newTime = percent * this.audio.duration;
this.audio.currentTime = newTime;
console.log('🎵 Progress bar clicked:', {
percent: percent,
newTime: newTime,
duration: this.audio.duration
});
} else {
console.log('🎵 Progress bar clicked but audio not ready:', {
hasAudio: !!this.audio,
duration: this.audio?.duration,
isNaN: isNaN(this.audio?.duration)
});
}
});
}
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.code === 'Space' && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
e.preventDefault();
this.togglePlayPause();
}
});
},
async loadCommunityPlaylist() {
try {
console.log('🎵 Loading community playlist from database...');
// Load tracks from database via PHP
const response = await fetch('/api/get_community_tracks.php');
if (response.ok) {
const data = await response.json();
console.log('🎵 Community tracks loaded:', data);
if (data.success && data.tracks && data.tracks.length > 0) {
this.playlist = data.tracks;
console.log('🎵 Loaded', this.playlist.length, 'community tracks');
// Update playlist header
const playlistHeader = document.querySelector('#globalPlaylistPanel h3');
if (playlistHeader) {
playlistHeader.textContent = `Community Tracks (${this.playlist.length})`;
}
// Update track count display
const trackCountSpan = document.getElementById('globalTrackCount');
const artistNameSpan = document.getElementById('globalTrackArtistName');
if (trackCountSpan && artistNameSpan) {
artistNameSpan.textContent = `${this.playlist.length} community tracks loaded`;
trackCountSpan.textContent = `Ready to play`;
trackCountSpan.style.display = 'inline';
}
} else {
console.log('🎵 No community tracks found, loading fallback tracks');
this.loadFallbackTracks();
}
} else {
console.error('🎵 Failed to load community tracks:', response.status);
this.loadFallbackTracks();
}
this.renderPlaylist();
} catch (error) {
console.error('🎵 Error loading community playlist:', error);
this.loadFallbackTracks();
this.renderPlaylist();
}
},
loadFallbackTracks() {
console.log('🎵 Loading fallback tracks...');
this.playlist = [
{
id: 'fallback1',
title: 'Lounge Lyrics',
artist_name: 'stephane bergeron',
audio_url: 'https://apiboxfiles.erweima.ai/MTk4YTg3OGYtM2Y4NS00YWJhLWIxMjMtMjk1OWFjOTUwMDFk.mp3',
user_id: null
},
{
id: 'fallback2',
title: 'Chains of Dominion',
artist_name: 'stephane bergeron',
audio_url: 'https://apiboxfiles.erweima.ai/MTk4YTg3OGYtM2Y4NS00YWJhLWIxMjMtMjk1OWFjOTUwMDFk.mp3',
user_id: null
},
{
id: 'fallback3',
title: 'Deep Groove',
artist_name: 'stephane bergeron',
audio_url: 'https://apiboxfiles.erweima.ai/MTk4YTg3OGYtM2Y4NS00YWJhLWIxMjMtMjk1OWFjOTUwMDFk.mp3',
user_id: null
}
];
console.log('🎵 Loaded', this.playlist.length, 'fallback tracks');
// Update playlist header
const playlistHeader = document.querySelector('#globalPlaylistPanel h3');
if (playlistHeader) {
playlistHeader.textContent = `Demo Tracks (${this.playlist.length})`;
}
// Update track count display
const trackCountSpan = document.getElementById('globalTrackCount');
const artistNameSpan = document.getElementById('globalTrackArtistName');
if (trackCountSpan && artistNameSpan) {
artistNameSpan.textContent = `${this.playlist.length} demo tracks loaded`;
trackCountSpan.textContent = `Ready to play`;
trackCountSpan.style.display = 'inline';
}
},
renderPlaylist() {
console.log('🎵 Rendering community playlist with', this.playlist.length, 'tracks');
const container = document.getElementById('globalPlaylistTracks');
if (!container) {
console.error('🎵 Playlist container not found!');
return;
}
// Hide loading indicator
const loadingIndicator = document.getElementById('playlistLoading');
if (loadingIndicator) {
loadingIndicator.style.display = 'none';
}
container.innerHTML = '';
if (this.playlist.length === 0) {
container.innerHTML = `
<div class="playlist-loading">
<i class="fas fa-exclamation-triangle"></i>
<span>No tracks available</span>
<button onclick="window.globalPlayer.loadCommunityPlaylist()" style="margin-top: 1rem; padding: 0.5rem 1rem; background: #667eea; color: white; border: none; border-radius: 6px; cursor: pointer;">
<i class="fas fa-refresh"></i> Retry
</button>
</div>
`;
return;
}
this.playlist.forEach((track, index) => {
console.log('🎵 Rendering community track:', track.title);
const trackElement = document.createElement('div');
trackElement.className = 'playlist-track';
if (index === this.currentTrackIndex) {
trackElement.classList.add('active');
}
trackElement.innerHTML = `
<div class="playlist-track-info">
<div class="playlist-track-title">${track.title}</div>
<div class="playlist-track-artist">${track.artist_name || 'Unknown Artist'}</div>
</div>
`;
trackElement.addEventListener('click', () => {
console.log('🎵 Community track clicked:', track.title);
this.wasPlaying = this.isPlaying;
this.playTrack(track.audio_url, track.title, track.artist_name || 'Unknown Artist', track.user_id);
// Update active state
document.querySelectorAll('.playlist-track').forEach(t => t.classList.remove('active'));
trackElement.classList.add('active');
this.currentTrackIndex = index;
});
container.appendChild(trackElement);
});
console.log('🎵 Community playlist rendered successfully');
},
playTrack(audioUrl, title, artist, userId = null, isPreview = false) {
console.log('🎵 Playing track:', { audioUrl, title, artist, isPreview });
// Pause current audio if playing
if (this.audio) {
this.audio.pause();
this.isPlaying = false;
}
// Reset progress bar and time display
this.resetProgressBar();
// Show loading state
const totalTimeElement = document.getElementById('globalTotalTime');
if (totalTimeElement) {
totalTimeElement.textContent = 'Loading...';
}
// Create new audio element
this.audio = new Audio(audioUrl);
this.audio.volume = this.volume;
// Force user interaction flags for autoplay
this.userInteracted = true;
this.wasPlaying = true;
// For individual track playback (preview tracks), ensure it will auto-play
if (userId === null) {
console.log('🎵 Preview track detected - will auto-play when ready');
}
// Update track info immediately
this.updateTrackInfo(title, artist, userId);
// Setup audio event listeners
this.audio.addEventListener('loadedmetadata', () => {
const totalTimeElement = document.getElementById('globalTotalTime');
if (totalTimeElement && this.audio.duration && !isNaN(this.audio.duration) && this.audio.duration !== Infinity) {
totalTimeElement.textContent = this.formatTime(this.audio.duration);
console.log('🎵 Audio duration loaded:', this.audio.duration, 'formatted as:', this.formatTime(this.audio.duration));
} else {
console.log('🎵 Audio duration not available or invalid:', this.audio.duration);
totalTimeElement.textContent = '0:00';
}
});
this.audio.addEventListener('timeupdate', () => {
if (this.audio.duration && !isNaN(this.audio.duration) && this.audio.duration !== Infinity) {
const progress = (this.audio.currentTime / this.audio.duration) * 100;
const progressFill = document.getElementById('globalProgressFill');
const currentTimeElement = document.getElementById('globalCurrentTime');
if (progressFill) {
progressFill.style.width = Math.min(100, Math.max(0, progress)) + '%';
}
if (currentTimeElement) {
currentTimeElement.textContent = this.formatTime(this.audio.currentTime);
}
// Debug logging (only log every 5 seconds to avoid spam)
if (Math.floor(this.audio.currentTime) % 5 === 0) {
console.log('🎵 Progress update:', {
currentTime: this.audio.currentTime,
duration: this.audio.duration,
progress: progress + '%',
formattedCurrent: this.formatTime(this.audio.currentTime),
formattedDuration: this.formatTime(this.audio.duration)
});
}
// Handle 30-second preview
if (isPreview && this.audio.currentTime >= 30) {
console.log('🎵 30-second preview ended, stopping playback');
this.audio.pause();
this.isPlaying = false;
this.wasPlaying = false;
this.updatePlayButton();
// Show notification about preview ending
if (typeof window.showNotification === 'function') {
window.showNotification('30-second preview ended. Purchase the track for full access!', 'info');
}
}
} else {
console.log('🎵 Audio duration not available for progress update:', this.audio.duration);
}
});
this.audio.addEventListener('ended', () => {
console.log('🎵 Track ended');
// Only auto-play next track if we're in playlist mode (currentTrackIndex >= 0)
if (this.currentTrackIndex >= 0 && this.playlist.length > 0) {
console.log('🎵 Auto-playing next track from playlist...');
setTimeout(() => {
this.nextTrack();
}, 100);
} else {
console.log('🎵 Individual track ended, not auto-playing next track');
this.isPlaying = false;
this.wasPlaying = false;
this.updatePlayButton();
}
});
this.audio.addEventListener('canplaythrough', () => {
console.log('🎵 Audio ready to play:', title);
// Check if track was explicitly stopped
if (!this.audio || this.audio.src === '') {
console.log('🎵 Audio was cleared (stopped), not auto-playing');
return;
}
// For individual track playback (preview tracks), always auto-play
if (this.currentTrackIndex === -1) {
console.log('🎵 Auto-playing preview track (individual track)');
this.playAudio();
} else if (this.wasPlaying) {
console.log('🎵 Auto-playing new track (was playing)');
this.playAudio();
} else {
console.log('🎵 Track ready, waiting for user to click play button');
this.isPlaying = false;
this.updatePlayButton();
}
});
// Update track info immediately
this.updateTrackInfo(title, artist, userId);
this.updatePlayButton();
this.showPlayer();
// No playlist needed for individual track playback
this.currentTrackIndex = -1;
console.log('🎵 Individual track playback - no playlist needed');
},
togglePlayPause() {
console.log('🎵 togglePlayPause called');
if (!this.audio) {
console.log('🎵 No audio loaded, checking playlist...');
// If we have a playlist, play the first track
if (this.playlist.length > 0) {
console.log('🎵 Playing first track from playlist...');
this.currentTrackIndex = 0;
const track = this.playlist[0];
this.wasPlaying = true;
this.playTrack(track.audio_url, track.title, track.artist_name || 'Unknown Artist', track.user_id);
return;
}
// Otherwise load default track
console.log('🎵 Loading default track...');
this.loadDefaultTrack();
return;
}
if (this.isPlaying) {
console.log('🎵 Pausing audio');
this.pauseAudio();
} else {
console.log('🎵 Playing audio');
this.playAudio();
}
},
playAudio() {
if (!this.audio) {
console.error('🎵 No audio element to play');
return;
}
this.audio.play().then(() => {
this.isPlaying = true;
this.wasPlaying = true;
this.updatePlayButton();
console.log('🎵 Play successful');
}).catch(error => {
console.error('🎵 Play failed:', error);
this.isPlaying = false;
this.wasPlaying = false;
this.updatePlayButton();
});
},
pauseAudio() {
if (this.audio) {
this.audio.pause();
}
this.isPlaying = false;
this.wasPlaying = false;
this.updatePlayButton();
},
nextTrack() {
console.log('🎵 nextTrack called');
if (this.playlist.length === 0) {
console.log('🎵 No tracks in playlist, cannot play next');
return;
}
this.wasPlaying = this.isPlaying;
if (this.shuffleMode) {
// Shuffle mode - pick random track
this.playRandomTrack();
} else {
// Sequential mode - go to next track
if (this.currentTrackIndex < 0) {
// No track currently playing, start with first track
this.currentTrackIndex = 0;
console.log('🎵 Starting with first track (index 0)');
} else {
// Go to next track
this.currentTrackIndex = (this.currentTrackIndex + 1) % this.playlist.length;
console.log('🎵 Going to next track (index ' + this.currentTrackIndex + ')');
}
const track = this.playlist[this.currentTrackIndex];
console.log('🎵 Playing next track:', track.title);
this.playTrack(track.audio_url, track.title, track.artist_name || 'Unknown Artist', track.user_id);
}
},
previousTrack() {
if (this.playlist.length === 0) return;
this.wasPlaying = this.isPlaying;
this.currentTrackIndex = this.currentTrackIndex === 0 ? this.playlist.length - 1 : this.currentTrackIndex - 1;
const track = this.playlist[this.currentTrackIndex];
this.playTrack(track.audio_url, track.title, track.artist_name || 'Unknown Artist', track.user_id);
},
stopTrack() {
console.log('🎵 Stop track called');
// Clear any existing audio element completely
if (this.audio) {
this.audio.pause();
this.audio.currentTime = 0;
this.audio.src = '';
this.audio = null;
}
// Reset all state flags
this.isPlaying = false;
this.wasPlaying = false;
this.userInteracted = false;
// Reset playlist state for individual tracks
this.currentTrackIndex = -1;
this.updatePlayButton();
// Reset progress bar
this.resetProgressBar();
console.log('🎵 Track stopped completely');
},
updateTrackInfo(title, artist, userId = null) {
console.log('🎵 updateTrackInfo called with:', { title, artist, userId });
const trackTitleElement = document.getElementById('globalTrackTitle');
const trackArtistElement = document.getElementById('globalTrackArtistName');
if (trackTitleElement) {
trackTitleElement.textContent = title;
}
if (trackArtistElement) {
trackArtistElement.textContent = artist;
}
// Show/hide artist profile link
const artistLink = document.getElementById('globalTrackArtistLink');
if (userId && userId !== 'Unknown Artist') {
artistLink.href = `/artist_profile.php?id=${userId}`;
artistLink.style.display = 'inline-flex';
} else {
artistLink.style.display = 'none';
}
},
updatePlayButton() {
const playButton = document.getElementById('globalPlayBtn');
if (playButton) {
const icon = playButton.querySelector('i');
if (icon) {
icon.className = this.isPlaying ? 'fas fa-pause' : 'fas fa-play';
}
}
},
updateVolumeIcon() {
const volumeIcon = document.getElementById('globalVolumeIcon');
if (volumeIcon) {
if (this.volume === 0) {
volumeIcon.className = 'fas fa-volume-mute';
} else if (this.volume < 0.3) {
volumeIcon.className = 'fas fa-volume-down';
} else if (this.volume < 0.7) {
volumeIcon.className = 'fas fa-volume-off';
} else {
volumeIcon.className = 'fas fa-volume-up';
}
}
},
showPlayer() {
console.log('🎵 Showing global player');
const playerElement = document.getElementById('globalMusicPlayer');
if (playerElement) {
playerElement.classList.add('active');
playerElement.style.display = 'flex';
playerElement.style.opacity = '1';
playerElement.style.visibility = 'visible';
}
},
togglePlaylist() {
console.log('🎵 Toggling playlist panel');
const panel = document.getElementById('globalPlaylistPanel');
if (panel) {
panel.classList.toggle('active');
if (panel.classList.contains('active') && this.playlist.length === 0) {
console.log('🎵 Playlist empty, loading tracks...');
this.loadCommunityPlaylist();
}
}
},
formatTime(seconds) {
if (isNaN(seconds) || seconds === Infinity) {
return '0:00';
}
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
},
resetProgressBar() {
console.log('🎵 Resetting progress bar');
// Reset progress bar
const progressFill = document.getElementById('globalProgressFill');
if (progressFill) {
progressFill.style.width = '0%';
}
// Reset time display
const currentTime = document.getElementById('globalCurrentTime');
if (currentTime) {
currentTime.textContent = '0:00';
}
// Reset total time display
const totalTime = document.getElementById('globalTotalTime');
if (totalTime) {
totalTime.textContent = '0:00';
}
},
loadDefaultTrack() {
console.log('🎵 Loading default CDN track...');
const cdnTracks = [
{
audio_url: 'https://apiboxfiles.erweima.ai/MTk4YTg3OGYtM2Y4NS00YWJhLWIxMjMtMjk1OWFjOTUwMDFk.mp3',
title: 'Lounge Lyrics',
artist_name: 'stephane bergeron'
}
];
this.playTrack(cdnTracks[0].audio_url, cdnTracks[0].title, cdnTracks[0].artist_name, null);
this.wasPlaying = true; // Auto-play when loading default track
},
toggleShuffle() {
this.shuffleMode = !this.shuffleMode;
console.log('🎵 Shuffle mode:', this.shuffleMode ? 'ON' : 'OFF');
// Save to localStorage
localStorage.setItem('globalPlayerShuffle', this.shuffleMode);
// Update button appearance
this.updateShuffleButton();
// Clear shuffle history when toggling
this.shuffleHistory = [];
},
updateShuffleButton() {
const shuffleToggle = document.getElementById('globalShuffleToggle');
if (shuffleToggle) {
if (this.shuffleMode) {
shuffleToggle.classList.add('active');
shuffleToggle.title = 'Shuffle: ON';
} else {
shuffleToggle.classList.remove('active');
shuffleToggle.title = 'Shuffle: OFF';
}
}
},
playRandomTrack() {
if (this.playlist.length === 0) {
console.log('🎵 No tracks in playlist for shuffle');
return;
}
// Add current track to history if it exists
if (this.currentTrackIndex >= 0 && this.currentTrackIndex < this.playlist.length) {
this.shuffleHistory.push(this.currentTrackIndex);
// Keep only last 10 tracks in history to avoid repetition
if (this.shuffleHistory.length > 10) {
this.shuffleHistory.shift();
}
}
// Generate random index, avoiding recent tracks
let randomIndex;
let attempts = 0;
const maxAttempts = 50;
do {
randomIndex = Math.floor(Math.random() * this.playlist.length);
attempts++;
} while (
this.shuffleHistory.includes(randomIndex) &&
attempts < maxAttempts &&
this.shuffleHistory.length < this.playlist.length
);
// If we can't find a non-recent track, just pick any random one
if (attempts >= maxAttempts) {
randomIndex = Math.floor(Math.random() * this.playlist.length);
this.shuffleHistory = []; // Reset history
}
this.currentTrackIndex = randomIndex;
const track = this.playlist[randomIndex];
console.log('🎵 Playing random track:', track.title);
this.playTrack(track.audio_url, track.title, track.artist_name || 'Unknown Artist', track.user_id);
}
};
// Initialize global player
console.log('🎵 Creating global player object...');
window.globalPlayer = globalPlayer;
// Site settings for player behavior
window.playerSettings = {
autoPlay: <?= isAutoPlayEnabled() ? 'true' : 'false' ?>,
shuffleEnabled: <?= isShuffleEnabled() ? 'true' : 'false' ?>,
globalPlayerEnabled: <?= isGlobalPlayerEnabled() ? 'true' : 'false' ?>
};
console.log('🎵 Player settings loaded:', window.playerSettings);
// Initialize when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
console.log('🎵 DOM loaded, initializing global player...');
setTimeout(() => {
window.globalPlayer.init().then(() => {
console.log('🎵 Global player initialization completed successfully');
// Apply site settings
if (window.playerSettings.shuffleEnabled) {
window.globalPlayer.toggleShuffle();
}
if (window.playerSettings.autoPlay) {
// Auto-play after a short delay
setTimeout(() => {
window.globalPlayer.play();
}, 2000);
}
// Dispatch event to notify other scripts
window.dispatchEvent(new CustomEvent('globalPlayerReady'));
}).catch(error => {
console.error('🎵 Global player initialization failed:', error);
});
}, 100);
});
} else {
console.log('🎵 DOM already loaded, initializing immediately...');
setTimeout(() => {
window.globalPlayer.init().then(() => {
console.log('🎵 Global player initialization completed successfully');
// Apply site settings
if (window.playerSettings.shuffleEnabled) {
window.globalPlayer.toggleShuffle();
}
if (window.playerSettings.autoPlay) {
// Auto-play after a short delay
setTimeout(() => {
window.globalPlayer.play();
}, 2000);
}
// Dispatch event to notify other scripts
window.dispatchEvent(new CustomEvent('globalPlayerReady'));
}).catch(error => {
console.error('🎵 Global player initialization failed:', error);
});
}, 100);
}
// Global function to play track
window.playTrackWithGlobalPlayer = function(audioUrl, title, artist, userId = null) {
console.log('🎵 playTrackWithGlobalPlayer called:', { audioUrl, title, artist });
if (window.globalPlayer && window.globalPlayer.playTrack) {
window.globalPlayer.wasPlaying = true;
window.globalPlayer.playTrack(audioUrl, title, artist, userId);
return true;
} else {
console.error('🎵 Global player not available');
return false;
}
};
console.log('🎵 Global player script loaded');
console.log('🎵 SCRIPT COMPLETE - Global player script finished loading');
</script>