![]() 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/domains/soundstudiopro.com/public_html/ |
<?php
require_once 'config/database.php';
session_start();
$user_id = $_SESSION['user_id'] ?? null;
$track_id = $_GET['id'] ?? null;
if (!$track_id) {
header('Location: /community_fixed.php');
exit;
}
try {
$pdo = getDBConnection();
// Get the specific track with all details
$track_query = "
SELECT
mt.*,
u.name as artist_name,
u.plan as artist_plan,
COALESCE(tp.play_count, 0) as play_count,
COALESCE(tl.like_count, 0) as like_count,
0 as vote_count,
CASE WHEN tl_user.track_id IS NOT NULL THEN 1 ELSE 0 END as user_liked,
NULL as user_vote
FROM music_tracks mt
JOIN users u ON mt.user_id = u.id
LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) tp ON mt.id = tp.track_id
LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) tl ON mt.id = tl.track_id
LEFT JOIN track_likes tl_user ON mt.id = tl_user.track_id AND tl_user.user_id = ?
WHERE mt.id = ? AND mt.status = 'complete'
";
$stmt = $pdo->prepare($track_query);
$stmt->execute([$user_id, $track_id]);
$track = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$track) {
header('Location: /community_fixed.php');
exit;
}
// Note: Play recording is now only done when user actually plays the track
// No automatic play recording on page load
// Parse metadata
$metadata = json_decode($track['metadata'] ?? '{}', true) ?: [];
$genre = $metadata['genre'] ?? 'Electronic';
$bpm = $metadata['bpm'] ?? 120;
$key = $metadata['key'] ?? 'C major';
$time_signature = $metadata['time_signature'] ?? '4/4';
$instruments = $metadata['instruments'] ?? [];
$mood = $metadata['mood'] ?? 'Neutral';
$energy = $metadata['energy'] ?? 'Medium';
} catch (Exception $e) {
error_log("Track page error: " . $e->getMessage());
header('Location: /community_fixed.php');
exit;
}
$page_title = htmlspecialchars($track['title']) . ' by ' . htmlspecialchars($track['artist_name']);
$page_description = 'Listen to ' . htmlspecialchars($track['title']) . ' by ' . htmlspecialchars($track['artist_name']) . ' - ' . htmlspecialchars($track['prompt'] ?: 'AI-generated music') . ' on SoundStudioPro';
$page_url = 'https://soundstudiopro.com/track.php?id=' . $track_id;
$page_image = !empty($track['image_url']) ? $track['image_url'] : 'https://soundstudiopro.com/uploads/track_covers/track_45_1754191923.jpg';
$track_duration = gmdate("i:s", $track['duration'] ?? 180);
$release_date = date('Y-m-d', strtotime($track['created_at']));
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#667eea">
<meta name="msapplication-TileColor" content="#667eea">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="SoundStudioPro">
<meta name="mobile-web-app-capable" content="yes">
<title><?= $page_title ?> - SoundStudioPro</title>
<!-- SEO Meta Tags -->
<meta name="description" content="<?= $page_description ?>">
<meta name="keywords" content="<?= htmlspecialchars($track['title']) ?>, <?= htmlspecialchars($track['artist_name']) ?>, AI music, SoundStudioPro, <?= htmlspecialchars($genre) ?>, <?= htmlspecialchars($mood) ?>">
<meta name="author" content="<?= htmlspecialchars($track['artist_name']) ?>">
<meta name="robots" content="index, follow">
<meta name="language" content="English">
<meta name="revisit-after" content="7 days">
<!-- Canonical URL -->
<link rel="canonical" href="<?= $page_url ?>">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="music.song">
<meta property="og:url" content="<?= $page_url ?>">
<meta property="og:title" content="<?= $page_title ?>">
<meta property="og:description" content="<?= $page_description ?>">
<meta property="og:image" content="<?= $page_image ?>">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="<?= $page_title ?>">
<meta property="og:site_name" content="SoundStudioPro">
<meta property="og:locale" content="en_US">
<!-- Music-specific Open Graph -->
<meta property="music:duration" content="<?= $track['duration'] ?? 180 ?>">
<meta property="music:musician" content="<?= htmlspecialchars($track['artist_name']) ?>">
<meta property="music:album" content="<?= htmlspecialchars($track['title']) ?>">
<meta property="music:release_date" content="<?= $release_date ?>">
<!-- Twitter Cards -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="<?= $page_url ?>">
<meta name="twitter:title" content="<?= $page_title ?>">
<meta name="twitter:description" content="<?= $page_description ?>">
<meta name="twitter:image" content="<?= $page_image ?>">
<meta name="twitter:image:alt" content="<?= $page_title ?>">
<meta name="twitter:site" content="@soundstudiopro">
<meta name="twitter:creator" content="@soundstudiopro">
<!-- Additional Social Media -->
<meta property="article:published_time" content="<?= $release_date ?>T00:00:00Z">
<meta property="article:author" content="<?= htmlspecialchars($track['artist_name']) ?>">
<meta property="article:section" content="Music">
<meta property="article:tag" content="<?= htmlspecialchars($genre) ?>">
<!-- Structured Data / JSON-LD -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "MusicRecording",
"name": "<?= htmlspecialchars($track['title']) ?>",
"byArtist": {
"@type": "MusicGroup",
"name": "<?= htmlspecialchars($track['artist_name']) ?>"
},
"description": "<?= htmlspecialchars($track['prompt'] ?: 'AI-generated music track') ?>",
"genre": "<?= htmlspecialchars($genre) ?>",
"duration": "PT<?= floor(($track['duration'] ?? 180) / 60) ?>M<?= ($track['duration'] ?? 180) % 60 ?>S",
"datePublished": "<?= $release_date ?>",
"url": "<?= $page_url ?>",
"image": "<?= $page_image ?>",
"audio": "<?= htmlspecialchars($track['audio_url']) ?>",
"interactionStatistic": [
{
"@type": "InteractionCounter",
"interactionType": "https://schema.org/ListenAction",
"userInteractionCount": <?= $track['play_count'] ?>
},
{
"@type": "InteractionCounter",
"interactionType": "https://schema.org/LikeAction",
"userInteractionCount": <?= $track['like_count'] ?>
}
],
"publisher": {
"@type": "Organization",
"name": "SoundStudioPro",
"url": "https://soundstudiopro.com"
}
}
</script>
<!-- Favicon and App Icons -->
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0f0f0f 100%);
min-height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #ffffff;
line-height: 1.6;
position: relative;
overflow-x: hidden;
}
/* Ultra Advanced Particle System */
.particles-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
}
/* Ensure global player is always on top */
#enhancedGlobalPlayer {
z-index: 100000 !important;
position: fixed !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
display: flex !important;
visibility: visible !important;
opacity: 1 !important;
}
.player-track-info {
display: flex !important;
visibility: visible !important;
opacity: 1 !important;
z-index: 100001 !important;
}
.track-title, .track-artist {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
color: #ffffff !important;
font-weight: 700 !important;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important;
}
#playerTrackTitle, #playerTrackArtist {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
color: #ffffff !important;
font-weight: 700 !important;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3) !important;
}
.particle {
position: absolute;
background: radial-gradient(circle, rgba(102, 126, 234, 0.8) 0%, rgba(118, 75, 162, 0.4) 50%, transparent 100%);
border-radius: 50%;
animation: float 8s infinite ease-in-out;
}
.particle:nth-child(odd) {
background: radial-gradient(circle, rgba(255, 215, 0, 0.6) 0%, rgba(255, 165, 0, 0.3) 50%, transparent 100%);
animation-duration: 12s;
}
.particle:nth-child(3n) {
background: radial-gradient(circle, rgba(255, 105, 180, 0.7) 0%, rgba(255, 20, 147, 0.3) 50%, transparent 100%);
animation-duration: 10s;
}
@keyframes float {
0%, 100% {
transform: translateY(0px) translateX(0px) scale(1);
opacity: 0.3;
}
25% {
transform: translateY(-20px) translateX(10px) scale(1.1);
opacity: 0.7;
}
50% {
transform: translateY(-40px) translateX(-5px) scale(0.9);
opacity: 0.5;
}
75% {
transform: translateY(-20px) translateX(15px) scale(1.2);
opacity: 0.8;
}
}
/* Musical Waveform Animation */
.waveform-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
}
.waveform-line {
position: absolute;
height: 2px;
background: linear-gradient(90deg, transparent, rgba(102, 126, 234, 0.6), transparent);
animation: waveform 3s infinite ease-in-out;
}
@keyframes waveform {
0%, 100% {
transform: scaleX(0);
opacity: 0;
}
50% {
transform: scaleX(1);
opacity: 1;
}
}
/* Glowing Orbs */
.glow-orb {
position: absolute;
border-radius: 50%;
background: radial-gradient(circle, rgba(102, 126, 234, 0.3) 0%, transparent 70%);
animation: glow 4s infinite ease-in-out;
}
@keyframes glow {
0%, 100% {
transform: scale(1);
opacity: 0.3;
}
50% {
transform: scale(1.5);
opacity: 0.7;
}
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
.container {
max-width: 1000px;
margin: 0 auto;
padding: 1.5rem;
position: relative;
z-index: 10;
}
/* Ultra Advanced Glass Morphism */
.glass-card {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 20px;
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.3),
0 2px 16px rgba(102, 126, 234, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
position: relative;
overflow: hidden;
}
.glass-card::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0% { left: -100%; }
100% { left: 100%; }
}
.back-nav {
margin-bottom: 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.8rem 0;
}
.nav-left, .nav-right {
flex: 1;
}
.nav-center {
flex: 2;
text-align: center;
}
.logo {
display: inline-flex;
align-items: center;
gap: 0.8rem;
color: #ffd700;
font-weight: 700;
font-size: 1.2rem;
}
.logo img {
height: 32px;
width: auto;
}
.logo-text {
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.back-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 12px;
padding: 0.8rem 1.5rem;
color: white;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
}
.back-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
}
.track-hero {
background: linear-gradient(145deg,
rgba(20, 20, 20, 0.95) 0%,
rgba(30, 30, 30, 0.9) 50%,
rgba(40, 40, 40, 0.85) 100%);
border-radius: 20px;
padding: 2.5rem;
margin-bottom: 2rem;
position: relative;
overflow: hidden;
backdrop-filter: blur(20px);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
0 2px 16px rgba(102, 126, 234, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
animation: heroGlow 4s ease-in-out infinite;
}
.track-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle at 30% 20%, rgba(102, 126, 234, 0.1) 0%, transparent 50%),
radial-gradient(circle at 70% 80%, rgba(118, 75, 162, 0.1) 0%, transparent 50%);
pointer-events: none;
}
@keyframes heroGlow {
0%, 100% {
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
0 2px 16px rgba(102, 126, 234, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
50% {
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.4),
0 2px 16px rgba(102, 126, 234, 0.2),
0 0 20px rgba(102, 126, 234, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
}
.track-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg,
rgba(102, 126, 234, 0.05) 0%,
rgba(118, 75, 162, 0.05) 100%);
pointer-events: none;
}
.track-header {
position: relative;
z-index: 2;
text-align: center;
margin-bottom: 2rem;
}
.track-cover-section {
margin-bottom: 2rem;
}
.track-cover {
position: relative;
display: inline-block;
margin-bottom: 1rem;
}
.cover-image {
width: 200px;
height: 200px;
border-radius: 16px;
object-fit: cover;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
.cover-placeholder {
width: 200px;
height: 200px;
border-radius: 16px;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
color: rgba(102, 126, 234, 0.6);
}
.update-cover-btn {
position: absolute;
bottom: 10px;
right: 10px;
width: 40px;
height: 40px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
color: white;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}
.update-cover-btn:hover {
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}
.track-title {
font-size: 2.5rem;
font-weight: 900;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, #ffffff, #667eea, #764ba2, #ffd700);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
animation: titleGlow 3s ease-in-out infinite;
text-shadow: 0 0 30px rgba(102, 126, 234, 0.3);
position: relative;
}
.track-title::after {
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 3px;
background: linear-gradient(90deg, transparent, #667eea, transparent);
animation: titleLine 2s ease-in-out infinite;
}
.free-label {
color: #667eea;
font-size: 0.6em;
font-weight: 700;
margin-left: 0.5rem;
padding: 0.2rem 0.8rem;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
border: 1px solid rgba(102, 126, 234, 0.4);
border-radius: 8px;
display: inline-block;
vertical-align: middle;
animation: freeGlow 2s ease-in-out infinite;
}
@keyframes freeGlow {
0%, 100% {
box-shadow: 0 0 10px rgba(102, 126, 234, 0.3);
}
50% {
box-shadow: 0 0 20px rgba(102, 126, 234, 0.6);
}
}
@keyframes titleGlow {
0%, 100% {
filter: drop-shadow(0 0 10px rgba(102, 126, 234, 0.3));
}
50% {
filter: drop-shadow(0 0 20px rgba(102, 126, 234, 0.6));
}
}
@keyframes titleLine {
0%, 100% {
width: 100px;
opacity: 0.5;
}
50% {
width: 200px;
opacity: 1;
}
}
.track-artist {
font-size: 1.8rem;
color: #ffffff;
margin-bottom: 2rem;
text-align: center;
font-weight: 700;
animation: artistPulse 4s ease-in-out infinite;
position: relative;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.track-artist::before {
content: '🎵';
position: absolute;
left: -40px;
top: 50%;
transform: translateY(-50%);
font-size: 1.5rem;
animation: musicNote 2s ease-in-out infinite;
}
@keyframes artistPulse {
0%, 100% {
color: #a0aec0;
}
50% {
color: #667eea;
}
}
@keyframes musicNote {
0%, 100% {
transform: translateY(-50%) rotate(0deg);
}
50% {
transform: translateY(-50%) rotate(10deg);
}
}
.artist-link {
color: #667eea;
text-decoration: none;
font-weight: 700;
font-size: 1.1em;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
text-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
}
.artist-link::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: linear-gradient(90deg, #667eea, #764ba2);
transition: width 0.3s ease;
}
.artist-link:hover {
color: #764ba2;
transform: translateY(-1px);
}
.artist-link:hover::before {
width: 100%;
}
.track-prompt {
font-size: 1.1rem;
color: #cbd5e0;
max-width: 600px;
margin: 0 auto 2rem;
line-height: 1.8;
}
.track-stats {
display: flex;
justify-content: center;
gap: 2rem;
margin-bottom: 1.5rem;
}
.stat-item {
text-align: center;
}
.stat-value {
font-size: 2rem;
font-weight: 700;
color: #667eea;
display: block;
}
.stat-label {
font-size: 0.9rem;
color: #a0aec0;
text-transform: uppercase;
letter-spacing: 1px;
}
.dj-tech-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 0.8rem;
margin-bottom: 1.5rem;
padding: 1.2rem;
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.tech-item {
text-align: center;
padding: 0.8rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
transition: all 0.3s ease;
}
.tech-item:hover {
background: rgba(255, 215, 0, 0.1);
transform: translateY(-1px);
}
.tech-label {
font-size: 0.8rem;
color: #a0aec0;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 0.5rem;
display: block;
}
.tech-value {
font-size: 1.1rem;
font-weight: 700;
color: #667eea;
}
.track-waveform {
height: 60px;
background: rgba(0, 0, 0, 0.4);
border-radius: 8px;
padding: 0.8rem;
margin-bottom: 1.5rem;
cursor: pointer;
transition: all 0.3s ease;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.track-waveform:hover {
background: rgba(255, 215, 0, 0.1);
border-color: rgba(255, 215, 0, 0.4);
}
.waveform-bars {
display: flex;
align-items: end;
justify-content: center;
gap: 2px;
height: 100%;
}
.waveform-bar {
width: 2px;
background: linear-gradient(to top, #667eea, #764ba2);
border-radius: 1px;
transition: all 0.3s ease;
}
.track-actions {
display: flex;
justify-content: center;
gap: 0.8rem;
margin-bottom: 1.5rem;
}
.action-btn {
padding: 1rem 2rem;
border: none;
border-radius: 12px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.6rem;
text-decoration: none;
color: white;
font-size: 1rem;
position: relative;
overflow: hidden;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.8), rgba(118, 75, 162, 0.8));
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
}
.action-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
.action-btn:hover::before {
left: 100%;
}
.action-btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
}
.play-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
position: relative;
overflow: hidden;
}
.play-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
transition: left 0.5s ease;
}
.play-btn:hover::before {
left: 100%;
}
.play-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.play-btn.highlighted {
animation: pulse 2s infinite;
box-shadow: 0 0 20px rgba(102, 126, 234, 0.8);
background: linear-gradient(135deg, #ffd700, #ffed4e);
color: #333;
}
.cart-btn {
background: linear-gradient(135deg, #28a745, #20c997);
}
.cart-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(40, 167, 69, 0.4);
}
.like-btn {
background: linear-gradient(135deg, #dc3545, #e74c3c);
position: relative;
overflow: hidden;
}
.like-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: all 0.6s ease;
}
.like-btn:hover::before {
width: 300px;
height: 300px;
}
.like-btn:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 8px 25px rgba(220, 53, 69, 0.5);
}
.like-btn.liked {
background: linear-gradient(135deg, #dc3545, #e74c3c);
animation: likePulse 0.6s ease-out;
}
.like-btn.liked i {
animation: heartBeat 0.6s ease-out;
}
@keyframes likePulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes heartBeat {
0% { transform: scale(1); }
25% { transform: scale(1.3); }
50% { transform: scale(1.1); }
75% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.share-btn {
background: linear-gradient(135deg, #6c757d, #495057);
}
.share-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(108, 117, 125, 0.4);
}
.vote-btn {
background: linear-gradient(135deg, #17a2b8, #138496);
position: relative;
overflow: hidden;
}
.vote-btn::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 0;
height: 0;
background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
border-radius: 50%;
transform: translate(-50%, -50%);
transition: all 0.6s ease;
}
.vote-btn:hover::before {
width: 300px;
height: 300px;
}
.vote-btn:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 8px 25px rgba(23, 162, 184, 0.5);
}
.vote-btn.voted {
background: linear-gradient(135deg, #f6ad55, #ed8936);
animation: votePulse 0.6s ease-out;
}
.vote-btn.voted i {
animation: thumbsUp 0.6s ease-out;
}
@keyframes votePulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes thumbsUp {
0% { transform: scale(1) rotate(0deg); }
25% { transform: scale(1.2) rotate(-10deg); }
50% { transform: scale(1.1) rotate(5deg); }
75% { transform: scale(1.15) rotate(-5deg); }
100% { transform: scale(1) rotate(0deg); }
}
@keyframes heartFloat {
0% {
transform: translate(-50%, -50%) scale(0);
opacity: 1;
}
50% {
transform: translate(-50%, -100px) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -200px) scale(0.5);
opacity: 0;
}
}
@keyframes thumbsUpFloat {
0% {
transform: translate(-50%, -50%) scale(0);
opacity: 1;
}
50% {
transform: translate(-50%, -100px) scale(1);
opacity: 1;
}
100% {
transform: translate(-50%, -200px) scale(0.5);
opacity: 0;
}
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.track-creation {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.creation-content {
display: grid;
gap: 2rem;
}
.prompt-section h3 {
color: #667eea;
margin-bottom: 1rem;
font-size: 1.2rem;
}
.prompt-text {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 1.5rem;
font-style: italic;
font-size: 1.1rem;
line-height: 1.6;
color: #cbd5e0;
border-left: 4px solid #667eea;
}
.creation-meta {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.meta-item {
padding: 1rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
text-align: center;
}
.meta-label {
font-size: 0.9rem;
color: #a0aec0;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 0.5rem;
display: block;
}
.meta-value {
font-size: 1.1rem;
font-weight: 600;
color: white;
}
.track-details {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}
.detail-item {
padding: 1rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
text-align: center;
}
.detail-label {
font-size: 0.9rem;
color: #a0aec0;
text-transform: uppercase;
letter-spacing: 1px;
margin-bottom: 0.5rem;
display: block;
}
.detail-value {
font-size: 1.1rem;
font-weight: 600;
color: white;
}
.track-lyrics {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.lyrics-toggle {
background: none;
border: none;
color: #667eea;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
}
.lyrics-content {
display: none;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
line-height: 1.8;
font-family: 'Georgia', serif;
text-align: center;
}
.lyrics-content.show {
display: block;
}
.track-engagement {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.engagement-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1.5rem;
}
.engagement-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
transition: all 0.3s ease;
}
.engagement-item:hover {
background: rgba(102, 126, 234, 0.1);
transform: translateY(-2px);
}
.engagement-icon {
width: 48px;
height: 48px;
background: linear-gradient(135deg, #667eea, #764ba2);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
color: white;
}
.engagement-info {
flex: 1;
}
.engagement-value {
font-size: 1.5rem;
font-weight: 700;
color: #667eea;
margin-bottom: 0.2rem;
}
.engagement-label {
font-size: 0.9rem;
color: #a0aec0;
text-transform: uppercase;
letter-spacing: 1px;
}
.track-comments {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.comment-form {
margin-bottom: 1.5rem;
}
.comment-form textarea {
width: 100%;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(102, 126, 234, 0.3);
border-radius: 8px;
padding: 1rem;
color: white;
font-family: inherit;
font-size: 0.9rem;
resize: vertical;
margin-bottom: 1rem;
}
.comment-form textarea:focus {
outline: none;
border-color: rgba(102, 126, 234, 0.6);
background: rgba(255, 255, 255, 0.08);
}
.comment-submit {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
border-radius: 8px;
padding: 0.8rem 1.5rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
}
.comment-submit:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.comments-list {
max-height: 400px;
overflow-y: auto;
}
.comment-item {
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
border-left: 3px solid rgba(102, 126, 234, 0.5);
}
.comment-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.comment-author {
font-weight: 600;
color: #667eea;
font-size: 0.9rem;
}
.comment-date {
font-size: 0.8rem;
color: #a0aec0;
}
.comment-text {
color: #cbd5e0;
line-height: 1.5;
font-size: 0.9rem;
}
.related-tracks {
background: rgba(0, 0, 0, 0.4);
border-radius: 12px;
padding: 1.5rem;
border: 1px solid rgba(255, 215, 0, 0.2);
}
.section-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1.5rem;
color: #667eea;
}
.tracks-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.mini-track-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 1rem;
transition: all 0.3s ease;
cursor: pointer;
}
.mini-track-card:hover {
background: rgba(102, 126, 234, 0.1);
transform: translateY(-2px);
}
.mini-track-title {
font-weight: 600;
margin-bottom: 0.5rem;
}
.mini-track-artist {
font-size: 0.9rem;
color: #a0aec0;
}
@media (max-width: 768px) {
.container {
padding: 1rem;
}
.back-nav {
flex-direction: column;
gap: 1rem;
}
.nav-center {
order: -1;
}
.track-title {
font-size: 2.5rem;
}
.track-artist {
font-size: 1.8rem;
}
.track-stats {
flex-direction: column;
gap: 1rem;
}
.dj-tech-grid {
grid-template-columns: repeat(3, 1fr);
}
.track-actions {
flex-wrap: wrap;
}
.action-btn {
flex: 1;
min-width: 120px;
}
.engagement-stats {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<!-- Ultra Advanced Particle System -->
<div class="particles-container" id="particles"></div>
<!-- Musical Waveform Background -->
<div class="waveform-container" id="waveform"></div>
<!-- Glowing Orbs -->
<div class="glow-orb" style="top: 20%; left: 10%; width: 100px; height: 100px; animation-delay: 0s;"></div>
<div class="glow-orb" style="top: 60%; right: 15%; width: 150px; height: 150px; animation-delay: 2s;"></div>
<div class="glow-orb" style="bottom: 30%; left: 20%; width: 80px; height: 80px; animation-delay: 4s;"></div>
<div class="container">
<div class="back-nav">
<div class="nav-left">
<a href="/community_fixed.php" class="back-btn">
<i class="fas fa-arrow-left"></i>
Back to Community
</a>
</div>
<div class="nav-center">
<div class="logo">
<img src="/assets/images/logo.png" alt="SoundStudioPro" onerror="this.style.display='none'">
<span class="logo-text">SoundStudioPro</span>
</div>
</div>
<div class="nav-right">
<!-- Space for future elements -->
</div>
</div>
<div class="track-hero">
<div class="track-header">
<div class="track-cover-section">
<div class="track-cover">
<?php if (!empty($track['image_url'])): ?>
<img src="<?= htmlspecialchars($track['image_url']) ?>" alt="Track Cover" class="cover-image">
<?php else: ?>
<img src="/uploads/track_covers/track_45_1754191923.jpg" alt="Default Track Cover" class="cover-image">
<?php endif; ?>
<?php if ($user_id && $user_id == $track['user_id']): ?>
<label for="trackCoverUpload" class="update-cover-btn">
<i class="fas fa-camera"></i>
</label>
<input type="file" id="trackCoverUpload" accept="image/*" style="display: none;">
<?php endif; ?>
</div>
</div>
<h1 class="track-title">
<?= htmlspecialchars($track['title'] ?: 'Untitled Track') ?>
<?php if (($track['price'] ?? 1.99) == 0): ?>
<span class="free-label">FREE</span>
<?php endif; ?>
</h1>
<div class="track-artist">
by <a href="/artist_profile.php?id=<?= $track['user_id'] ?>" class="artist-link"><?= htmlspecialchars($track['artist_name']) ?></a>
</div>
<div class="track-prompt"><?= htmlspecialchars($track['prompt'] ?: 'A creative AI-generated track') ?></div>
</div>
<div class="track-stats">
<div class="stat-item">
<span class="stat-value"><?= number_format($track['play_count']) ?></span>
<span class="stat-label">Plays</span>
</div>
<div class="stat-item">
<span class="stat-value"><?= number_format($track['like_count']) ?></span>
<span class="stat-label">Likes</span>
</div>
<div class="stat-item">
<span class="stat-value"><?= gmdate("i:s", $track['duration'] ?? 180) ?></span>
<span class="stat-label">Duration</span>
</div>
<div class="stat-item">
<span class="stat-value"><?= date('M j', strtotime($track['created_at'])) ?></span>
<span class="stat-label">Released</span>
</div>
</div>
<div class="dj-tech-grid">
<div class="tech-item">
<span class="tech-label">BPM</span>
<span class="tech-value"><?= $bpm ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Key</span>
<span class="tech-value"><?= $key ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Time</span>
<span class="tech-value"><?= $time_signature ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Mood</span>
<span class="tech-value"><?= $mood ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Genre</span>
<span class="tech-value"><?= htmlspecialchars($genre) ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Energy</span>
<span class="tech-value"><?= htmlspecialchars($energy) ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Duration</span>
<span class="tech-value"><?= gmdate("i:s", $track['duration'] ?? 180) ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Release</span>
<span class="tech-value"><?= date('M j, Y', strtotime($track['created_at'])) ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Artist Plan</span>
<span class="tech-value"><?= ucfirst($track['artist_plan'] ?? 'Free') ?></span>
</div>
<div class="tech-item">
<span class="tech-label">Price</span>
<span class="tech-value">$<?= number_format($track['price'] ?? 1.99, 2) ?></span>
</div>
</div>
<div class="track-actions">
<button class="action-btn play-btn" onclick="playThisTrack()">
<i class="fas fa-play"></i>
Play Track
</button>
<button class="action-btn cart-btn" onclick="addToCart(<?= $track['id'] ?>, '<?= htmlspecialchars($track['title'], ENT_QUOTES) ?>', <?= $track['price'] ?? 1.99 ?>)">
<i class="fas fa-shopping-cart"></i>
Add to Cart
</button>
<button class="action-btn like-btn <?= $track['user_liked'] ? 'liked' : '' ?>" onclick="toggleLike(<?= $track['id'] ?>, this)">
<i class="fas fa-heart"></i>
Like
</button>
<button class="action-btn vote-btn" onclick="voteTrack(<?= $track['id'] ?>, 'up')">
<i class="fas fa-thumbs-up"></i>
Vote
</button>
<button class="action-btn share-btn" onclick="shareTrack(<?= $track['id'] ?>, '<?= htmlspecialchars($track['title'], ENT_QUOTES) ?>', '<?= htmlspecialchars($track['artist_name'], ENT_QUOTES) ?>')">
<i class="fas fa-share-alt"></i>
Share
</button>
</div>
</div>
<div class="track-creation">
<h2 class="section-title">Creation Details</h2>
<div class="creation-content">
<div class="prompt-section">
<h3>Original Prompt</h3>
<div class="prompt-text">
"<?= htmlspecialchars($track['prompt'] ?: 'A creative AI-generated track') ?>"
</div>
</div>
<div class="creation-meta">
<div class="meta-item">
<span class="meta-label">Model Version</span>
<span class="meta-value"><?= htmlspecialchars($track['model_version'] ?? 'v3') ?></span>
</div>
<div class="meta-item">
<span class="meta-label">Music Type</span>
<span class="meta-value"><?= ucfirst(htmlspecialchars($track['music_type'] ?? 'music')) ?></span>
</div>
</div>
</div>
</div>
<?php if (!empty($track['lyrics'])): ?>
<div class="track-lyrics">
<h2 class="section-title">Lyrics</h2>
<button class="lyrics-toggle" onclick="toggleLyrics()">
<i class="fas fa-align-left"></i>
Show Lyrics
<i class="fas fa-chevron-down"></i>
</button>
<div class="lyrics-content" id="lyrics-content">
<?= nl2br(htmlspecialchars($track['lyrics'])) ?>
</div>
</div>
<?php endif; ?>
<div class="track-engagement">
<h2 class="section-title">Community Engagement</h2>
<div class="engagement-stats">
<div class="engagement-item">
<div class="engagement-icon">
<i class="fas fa-play"></i>
</div>
<div class="engagement-info">
<div class="engagement-value"><?= number_format($track['play_count']) ?></div>
<div class="engagement-label">Total Plays</div>
</div>
</div>
<div class="engagement-item">
<div class="engagement-icon">
<i class="fas fa-heart"></i>
</div>
<div class="engagement-info">
<div class="engagement-value"><?= number_format($track['like_count']) ?></div>
<div class="engagement-label">Likes</div>
</div>
</div>
<div class="engagement-item">
<div class="engagement-icon">
<i class="fas fa-thumbs-up"></i>
</div>
<div class="engagement-info">
<div class="engagement-value"><?= number_format($track['vote_count'] ?? 0) ?></div>
<div class="engagement-label">Votes</div>
</div>
</div>
<div class="engagement-item">
<div class="engagement-icon">
<i class="fas fa-comment"></i>
</div>
<div class="engagement-info">
<div class="engagement-value"><?= number_format($track['comment_count'] ?? 0) ?></div>
<div class="engagement-label">Comments</div>
</div>
</div>
</div>
</div>
<div class="track-comments">
<h2 class="section-title">Comments & Feedback</h2>
<div class="comment-form">
<textarea id="comment-text" placeholder="Share your thoughts about this track..." rows="3"></textarea>
<button class="comment-submit" onclick="submitComment(<?= $track['id'] ?>)">
<i class="fas fa-paper-plane"></i>
Post Comment
</button>
</div>
<div class="comments-list" id="comments-list">
<!-- Comments will be loaded here -->
</div>
</div>
<div class="related-tracks">
<h2 class="section-title">More from <?= htmlspecialchars($track['artist_name']) ?></h2>
<div class="tracks-grid">
<?php
// Get more tracks from the same artist
$related_query = "
SELECT mt.*, u.name as artist_name
FROM music_tracks mt
JOIN users u ON mt.user_id = u.id
WHERE mt.user_id = ? AND mt.id != ? AND mt.status = 'complete'
ORDER BY mt.created_at DESC
LIMIT 3
";
$related_stmt = $pdo->prepare($related_query);
$related_stmt->execute([$track['user_id'], $track['id']]);
$related_tracks = $related_stmt->fetchAll();
foreach ($related_tracks as $related_track):
?>
<div class="mini-track-card" onclick="window.location.href='/track.php?id=<?= $related_track['id'] ?>'">
<div class="mini-track-title"><?= htmlspecialchars($related_track['title']) ?></div>
<div class="mini-track-artist">by <a href="/artist_profile.php?id=<?= $related_track['user_id'] ?>" class="artist-link"><?= htmlspecialchars($related_track['artist_name']) ?></a></div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<script>
// Record Track Play
function recordTrackPlay(trackId) {
fetch('/api_social.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=play&track_id=${trackId}`
})
.catch(error => console.error('Play tracking error:', error));
}
// Ultra Advanced Particle System
function createParticles() {
const particlesContainer = document.getElementById('particles');
const particleCount = 50;
for (let i = 0; i < particleCount; i++) {
const particle = document.createElement('div');
particle.className = 'particle';
// Random size between 2px and 8px
const size = Math.random() * 6 + 2;
particle.style.width = size + 'px';
particle.style.height = size + 'px';
// Random position
particle.style.left = Math.random() * 100 + '%';
particle.style.top = Math.random() * 100 + '%';
// Random animation delay
particle.style.animationDelay = Math.random() * 8 + 's';
particle.style.animationDuration = (Math.random() * 4 + 8) + 's';
particlesContainer.appendChild(particle);
}
}
// Musical Waveform Animation
function createWaveform() {
const waveformContainer = document.getElementById('waveform');
const lineCount = 20;
for (let i = 0; i < lineCount; i++) {
const line = document.createElement('div');
line.className = 'waveform-line';
// Random position and size
line.style.left = Math.random() * 100 + '%';
line.style.top = Math.random() * 100 + '%';
line.style.width = Math.random() * 200 + 100 + 'px';
// Random animation delay
line.style.animationDelay = Math.random() * 3 + 's';
line.style.animationDuration = (Math.random() * 2 + 2) + 's';
waveformContainer.appendChild(line);
}
}
// Advanced Hover Effects
function addAdvancedHoverEffects() {
const cards = document.querySelectorAll('.track-hero, .engagement-stats, .track-comments');
cards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'scale(1.02)';
this.style.boxShadow = '0 20px 40px rgba(102, 126, 234, 0.3)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'scale(1)';
this.style.boxShadow = '';
});
});
}
// Initialize ultra-advanced effects
document.addEventListener('DOMContentLoaded', function() {
createParticles();
createWaveform();
addAdvancedHoverEffects();
// Ensure global player is always visible and on top
const globalPlayer = document.getElementById('enhancedGlobalPlayer');
if (globalPlayer) {
globalPlayer.style.zIndex = '100000';
globalPlayer.style.position = 'fixed';
globalPlayer.style.bottom = '0';
globalPlayer.style.left = '0';
globalPlayer.style.right = '0';
globalPlayer.style.display = 'flex';
globalPlayer.style.visibility = 'visible';
globalPlayer.style.opacity = '1';
console.log('🎵 Global player CSS forced to be visible');
}
});
// Track page functionality using global player - EXACTLY LIKE HOMEPAGE
// Check if enhanced global player is loaded (same as homepage)
window.addEventListener('load', function() {
console.log('🎵 Track page loaded');
console.log('🎵 Enhanced Global player status:', typeof window.enhancedGlobalPlayer !== 'undefined');
console.log('🎵 Enhanced Global player element exists:', !!document.getElementById('enhancedGlobalPlayer'));
// Ensure enhanced global player is available
if (typeof window.enhancedGlobalPlayer === 'undefined') {
console.error('🎵 Enhanced Global player not loaded!');
// Try to manually initialize if not loaded
setTimeout(() => {
if (typeof window.enhancedGlobalPlayer !== 'undefined') {
console.log('🎵 Enhanced Global player loaded after delay');
initializeTrackPagePlayer();
} else {
console.error('🎵 Enhanced Global player still not available after delay');
}
}, 1000);
} else {
console.log('🎵 Enhanced Global player loaded successfully');
initializeTrackPagePlayer();
}
});
// Initialize track page player functionality - TRACK SPECIFIC
function initializeTrackPagePlayer() {
// Force show the player
if (window.enhancedGlobalPlayer && window.enhancedGlobalPlayer.showPlayer) {
window.enhancedGlobalPlayer.showPlayer();
}
// DON'T load VIP playlist - this is a track page, not a playlist page
console.log('🎵 Track page player initialized - ready to play specific track');
// Immediately set the correct track info
const trackTitle = '<?= htmlspecialchars($track['title'], ENT_QUOTES) ?>';
const trackArtist = '<?= htmlspecialchars($track['artist_name'], ENT_QUOTES) ?>';
setTimeout(() => {
const trackTitleElement = document.getElementById('playerTrackTitle');
const trackArtistElement = document.getElementById('playerTrackArtist');
if (trackTitleElement) {
trackTitleElement.textContent = trackTitle;
trackTitleElement.style.display = 'block';
trackTitleElement.style.visibility = 'visible';
trackTitleElement.style.opacity = '1';
trackTitleElement.style.color = '#ffffff';
trackTitleElement.style.fontWeight = '700';
console.log('🎵 Initialized track title:', trackTitle);
}
if (trackArtistElement) {
trackArtistElement.textContent = trackArtist;
trackArtistElement.style.display = 'block';
trackArtistElement.style.visibility = 'visible';
trackArtistElement.style.opacity = '1';
trackArtistElement.style.color = '#ffffff';
trackArtistElement.style.fontWeight = '500';
console.log('🎵 Initialized track artist:', trackArtist);
}
}, 100);
}
// Play this specific track directly - bypass global player issues
function playThisTrack() {
const audioUrl = '<?= htmlspecialchars($track['audio_url'], ENT_QUOTES) ?>';
const title = '<?= htmlspecialchars($track['title'], ENT_QUOTES) ?>';
const artist = '<?= htmlspecialchars($track['artist_name'], ENT_QUOTES) ?>';
const trackId = <?= $track['id'] ?>;
console.log('🎵 Playing specific track:', { audioUrl, title, artist, trackId });
// Validate audio URL
if (!audioUrl || audioUrl === 'NULL' || audioUrl === 'null' || audioUrl === '') {
console.error('❌ Invalid audio URL:', audioUrl);
if (typeof window.showNotification === 'function') {
window.showNotification('Audio file not available', 'error');
}
return;
}
// Create a simple audio player for this track
let trackAudio = window.trackAudio;
if (!trackAudio) {
trackAudio = new Audio();
trackAudio.volume = 0.7;
window.trackAudio = trackAudio;
}
// Set up audio event listeners
trackAudio.src = audioUrl;
trackAudio.load();
// Update global player display with correct track info
const trackTitleElement = document.getElementById('playerTrackTitle');
const trackArtistElement = document.getElementById('playerTrackArtist');
if (trackTitleElement) {
trackTitleElement.textContent = title;
trackTitleElement.style.display = 'block';
trackTitleElement.style.visibility = 'visible';
trackTitleElement.style.opacity = '1';
trackTitleElement.style.color = '#ffffff';
trackTitleElement.style.fontWeight = '700';
console.log('🎵 Set track title:', title);
}
if (trackArtistElement) {
trackArtistElement.textContent = artist;
trackArtistElement.style.display = 'block';
trackArtistElement.style.visibility = 'visible';
trackArtistElement.style.opacity = '1';
trackArtistElement.style.color = '#ffffff';
trackArtistElement.style.fontWeight = '500';
console.log('🎵 Set track artist:', artist);
}
// Show the global player
const globalPlayer = document.getElementById('enhancedGlobalPlayer');
if (globalPlayer) {
globalPlayer.classList.add('playing');
globalPlayer.style.display = 'flex';
globalPlayer.style.visibility = 'visible';
globalPlayer.style.opacity = '1';
console.log('🎵 Showed global player');
}
// Play the audio
trackAudio.play().then(() => {
console.log('🎵 Track playback started successfully');
// Update play button to show pause
const playBtn = document.querySelector('.play-pause-btn');
if (playBtn) {
const icon = playBtn.querySelector('i');
if (icon) {
icon.className = 'fas fa-pause';
}
}
// Record play analytics
recordTrackPlay(trackId);
// Show success notification
if (typeof window.showNotification === 'function') {
window.showNotification(`🎵 Now playing: ${title}`, 'success');
}
}).catch(error => {
console.error('❌ Playback failed:', error);
if (typeof window.showNotification === 'function') {
window.showNotification('Failed to start playback', 'error');
}
});
// Set up audio event listeners for progress updates
trackAudio.addEventListener('timeupdate', function() {
const progressBar = document.getElementById('playerProgressBar');
const timeDisplay = document.getElementById('playerTimeDisplay');
const durationDisplay = document.getElementById('playerDurationDisplay');
if (progressBar && !isNaN(trackAudio.duration)) {
const progress = (trackAudio.currentTime / trackAudio.duration) * 100;
progressBar.style.width = progress + '%';
}
if (timeDisplay) {
timeDisplay.textContent = formatTime(trackAudio.currentTime);
}
if (durationDisplay) {
durationDisplay.textContent = formatTime(trackAudio.duration);
}
});
// Handle track end
trackAudio.addEventListener('ended', function() {
console.log('🎵 Track playback ended');
const playBtn = document.querySelector('.play-pause-btn');
if (playBtn) {
const icon = playBtn.querySelector('i');
if (icon) {
icon.className = 'fas fa-play';
}
}
});
}
// Helper function to format time
function formatTime(seconds) {
if (isNaN(seconds)) return '0:00';
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
}
function addToCart(trackId, title, price) {
if (!<?= $user_id ? 'true' : 'false' ?>) {
alert('Please log in to add tracks to cart');
setTimeout(() => {
window.location.href = '/auth/login.php';
}, 2000);
return;
}
console.log('🛒 Adding to cart:', { trackId, title, price });
// Add loading state to button
const button = event.target.closest('.cart-btn');
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Adding...';
button.disabled = true;
// Send to cart.php via POST
const formData = new FormData();
formData.append('track_id', trackId);
formData.append('action', 'add');
formData.append('artist_plan', '<?= $track['artist_plan'] ?? 'free' ?>');
fetch('cart.php', {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(responseText => {
console.log('🛒 Raw cart response:', responseText);
let data;
try {
data = JSON.parse(responseText);
console.log('🛒 Parsed cart response:', data);
} catch (e) {
console.error('🛒 Failed to parse JSON response:', e);
console.error('🛒 Raw response was:', responseText);
throw new Error('Invalid JSON response from cart');
}
if (!data.success) {
throw new Error(data.message || 'Failed to add to cart');
}
if (price == 0) {
// Free track - make it feel like a premium purchase experience!
console.log(`🎵 "${title}" added to cart for FREE! 🛒 Ready to purchase and own!`);
} else {
// Paid track added to cart
const revenueInfo = ('<?= $track['artist_plan'] ?? 'free' ?>' === 'free') ? ' (Platform Revenue)' : '';
console.log(`"${title}" added to cart! ($${price})${revenueInfo}`);
}
// Update cart UI if there's a cart counter
const cartCounter = document.querySelector('.cart-count, .cart-counter');
if (cartCounter && data.cart_count) {
cartCounter.textContent = data.cart_count;
}
// Log debug info if available
if (data.debug) {
console.log('🛒 Debug info:', data.debug);
}
// Change button to "Added" state temporarily
button.innerHTML = '<i class="fas fa-check"></i> Added!';
button.classList.add('added');
// Add a subtle pulse animation to draw attention
button.style.animation = 'pulse 0.5s ease-in-out';
// Show cart modal immediately
if (typeof showCartModal === 'function') {
setTimeout(() => {
showCartModal();
}, 300); // Quick delay to show the "Added!" message first
} else {
// Fallback: redirect to cart page if modal function doesn't exist
setTimeout(() => {
window.location.href = '/cart.php';
}, 500);
}
setTimeout(() => {
button.innerHTML = originalText;
button.classList.remove('added');
button.disabled = false;
}, 2000);
})
.catch(error => {
console.error('🛒 Cart error:', error);
alert('Failed to add to cart: ' + error.message);
// Restore button
button.innerHTML = originalText;
button.disabled = false;
});
}
function toggleLike(trackId, button) {
console.log('🎵 Toggle like called for track:', trackId);
// Check if user is logged in
const isLoggedIn = <?= $user_id ? 'true' : 'false' ?>;
if (!isLoggedIn) {
console.log('🎵 User not logged in, redirecting to login');
alert('Please log in to like tracks');
setTimeout(() => {
window.location.href = '/auth/login.php';
}, 2000);
return;
}
console.log('🎵 Toggling like for track:', trackId);
// Add loading state with ultra-advanced animation
button.style.pointerEvents = 'none';
const originalText = button.innerHTML;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
button.style.animation = 'pulse 0.5s ease-in-out';
const requestData = { action: 'like', track_id: trackId };
fetch('/api_social.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
})
.then(response => {
console.log('🎵 Like API response status:', response.status);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => {
console.log('🎵 Like API response data:', data);
if (data.success) {
button.classList.toggle('liked');
const icon = button.querySelector('i');
if (button.classList.contains('liked')) {
icon.className = 'fas fa-heart';
// Add heart burst effect
createHeartBurst(button);
} else {
icon.className = 'far fa-heart';
}
// Update like count with animation
updateLikeCount(button.classList.contains('liked'));
// Show success notification
const action = button.classList.contains('liked') ? 'liked' : 'unliked';
console.log(`Track ${action}!`);
} else {
console.error('🎵 Like API error:', data.message);
if (data.message === 'Please log in to like tracks') {
alert('Please log in to like tracks');
setTimeout(() => {
window.location.href = '/auth/login.php';
}, 2000);
} else {
alert(data.message || 'Failed to update like status');
}
}
})
.catch(error => {
console.error('🎵 Like network error:', error);
alert('Failed to update like status. Please try again.');
})
.finally(() => {
// Restore button
button.style.pointerEvents = 'auto';
button.innerHTML = originalText;
button.style.animation = '';
});
}
function updateLikeCount(isLiked) {
// Update like count in engagement section
const likeCount = document.querySelector('.engagement-item:nth-child(2) .engagement-value');
if (likeCount) {
const currentCount = parseInt(likeCount.textContent.replace(/,/g, '')) || 0;
const newCount = isLiked ? currentCount + 1 : Math.max(0, currentCount - 1);
// Animate the count change
likeCount.style.transform = 'scale(1.2)';
likeCount.style.color = isLiked ? '#dc3545' : '#667eea';
likeCount.textContent = newCount.toLocaleString();
setTimeout(() => {
likeCount.style.transform = 'scale(1)';
likeCount.style.color = '#667eea';
}, 300);
}
// Also update like count in track stats
const trackStatsLike = document.querySelector('.stat-item:nth-child(2) .stat-value');
if (trackStatsLike) {
const currentCount = parseInt(trackStatsLike.textContent.replace(/,/g, '')) || 0;
const newCount = isLiked ? currentCount + 1 : Math.max(0, currentCount - 1);
trackStatsLike.textContent = newCount.toLocaleString();
}
}
function createHeartBurst(button) {
// Create floating hearts effect
for (let i = 0; i < 5; i++) {
const heart = document.createElement('div');
heart.innerHTML = '❤️';
heart.style.position = 'absolute';
heart.style.left = '50%';
heart.style.top = '50%';
heart.style.transform = 'translate(-50%, -50%)';
heart.style.fontSize = '20px';
heart.style.pointerEvents = 'none';
heart.style.zIndex = '1000';
heart.style.animation = `heartFloat ${1 + Math.random()}s ease-out forwards`;
button.appendChild(heart);
setTimeout(() => heart.remove(), 1000);
}
}
function shareTrack(trackId, title, artist) {
const url = window.location.href;
const text = `Check out "${title}" by ${artist} on SoundStudioPro!`;
if (navigator.share) {
navigator.share({
title: title,
text: text,
url: url
});
} else {
// Fallback to copying URL
navigator.clipboard.writeText(url).then(() => {
alert('Track URL copied to clipboard!');
});
}
}
function toggleLyrics() {
const content = document.getElementById('lyrics-content');
const toggle = document.querySelector('.lyrics-toggle');
const icon = toggle.querySelector('.fa-chevron-down');
if (content.classList.contains('show')) {
content.classList.remove('show');
icon.style.transform = 'rotate(0deg)';
} else {
content.classList.add('show');
icon.style.transform = 'rotate(180deg)';
}
}
function submitComment(trackId) {
const commentText = document.getElementById('comment-text').value.trim();
if (!commentText) {
alert('Please enter a comment');
return;
}
fetch('/api_social.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=add_comment&track_id=${trackId}&comment=${encodeURIComponent(commentText)}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('comment-text').value = '';
loadComments(trackId);
// Update comment count
const commentCount = document.querySelector('.engagement-item:last-child .engagement-value');
if (commentCount) {
const currentCount = parseInt(commentCount.textContent.replace(/,/g, ''));
commentCount.textContent = (currentCount + 1).toLocaleString();
}
} else {
alert('Failed to post comment');
}
})
.catch(error => {
console.error('Comment error:', error);
alert('Network error');
});
}
function loadComments(trackId) {
fetch(`/api_social.php?action=get_comments&track_id=${trackId}`)
.then(response => response.json())
.then(data => {
const commentsList = document.getElementById('comments-list');
if (data.success && data.comments) {
commentsList.innerHTML = data.comments.map(comment => `
<div class="comment-item">
<div class="comment-header">
<span class="comment-author">${comment.author}</span>
<span class="comment-date">${comment.date}</span>
</div>
<div class="comment-text">${comment.text}</div>
</div>
`).join('');
} else {
commentsList.innerHTML = '<p style="color: #a0aec0; text-align: center;">No comments yet. Be the first to comment!</p>';
}
})
.catch(error => {
console.error('Load comments error:', error);
});
}
function voteTrack(trackId, voteType) {
console.log('🎵 Vote called for track:', trackId, 'vote type:', voteType);
// Check if user is logged in
const isLoggedIn = <?= $user_id ? 'true' : 'false' ?>;
if (!isLoggedIn) {
console.log('🎵 User not logged in, redirecting to login');
alert('Please log in to vote on tracks');
setTimeout(() => {
window.location.href = '/auth/login.php';
}, 2000);
return;
}
console.log('🎵 Voting on track:', trackId, 'vote type:', voteType);
// Add loading state with ultra-advanced animation
const voteBtn = document.querySelector('.vote-btn');
if (voteBtn) {
voteBtn.style.pointerEvents = 'none';
const originalText = voteBtn.innerHTML;
voteBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
voteBtn.style.animation = 'pulse 0.5s ease-in-out';
}
const requestData = { action: 'vote_track', track_id: trackId, vote_type: voteType };
fetch('/api_social.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
})
.then(response => {
console.log('🎵 Vote API response status:', response.status);
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => {
console.log('🎵 Vote API response data:', data);
if (data.success) {
// Add voted state with animation
voteBtn.classList.add('voted');
const icon = voteBtn.querySelector('i');
if (icon) icon.className = 'fas fa-thumbs-up';
// Create thumbs up burst effect
createThumbsUpBurst(voteBtn);
// Update vote count with animation
updateVoteCount();
console.log(`Vote recorded successfully!`);
} else {
console.error('🎵 Vote API error:', data.message);
if (data.message === 'Please log in to vote on tracks') {
alert('Please log in to vote on tracks');
setTimeout(() => {
window.location.href = '/auth/login.php';
}, 2000);
} else {
alert(data.message || 'Failed to record vote');
}
}
})
.catch(error => {
console.error('🎵 Vote network error:', error);
alert('Failed to record vote. Please try again.');
})
.finally(() => {
// Restore button
if (voteBtn) {
voteBtn.style.pointerEvents = 'auto';
voteBtn.innerHTML = originalText;
voteBtn.style.animation = '';
}
});
}
function updateVoteCount() {
// Update vote count in engagement section
const voteCount = document.querySelector('.engagement-item:nth-child(3) .engagement-value');
if (voteCount) {
const currentCount = parseInt(voteCount.textContent.replace(/,/g, '')) || 0;
const newCount = currentCount + 1;
// Animate the count change
voteCount.style.transform = 'scale(1.2)';
voteCount.style.color = '#f6ad55';
voteCount.textContent = newCount.toLocaleString();
setTimeout(() => {
voteCount.style.transform = 'scale(1)';
voteCount.style.color = '#667eea';
}, 300);
}
}
function createThumbsUpBurst(button) {
// Create floating thumbs up effect
for (let i = 0; i < 3; i++) {
const thumbsUp = document.createElement('div');
thumbsUp.innerHTML = '👍';
thumbsUp.style.position = 'absolute';
thumbsUp.style.left = '50%';
thumbsUp.style.top = '50%';
thumbsUp.style.transform = 'translate(-50%, -50%)';
thumbsUp.style.fontSize = '20px';
thumbsUp.style.pointerEvents = 'none';
thumbsUp.style.zIndex = '1000';
thumbsUp.style.animation = `thumbsUpFloat ${1 + Math.random()}s ease-out forwards`;
button.appendChild(thumbsUp);
setTimeout(() => thumbsUp.remove(), 1000);
}
}
function uploadTrackCoverImage(file) {
console.log('🎵 Starting cover image upload for track:', <?= $track['id'] ?>);
console.log('🎵 File details:', { name: file.name, size: file.size, type: file.type });
const formData = new FormData();
formData.append('cover_image', file);
formData.append('track_id', <?= $track['id'] ?>);
console.log('🎵 FormData created, sending to API...');
fetch('/api/upload_track_cover.php', {
method: 'POST',
body: formData
})
.then(response => {
console.log('🎵 Upload response status:', response.status);
console.log('🎵 Upload response headers:', response.headers);
return response.json();
})
.then(data => {
console.log('🎵 Upload response data:', data);
if (data.success) {
console.log('✅ Cover image uploaded successfully!');
updateTrackCoverDisplay(data.data.image_url);
alert('Cover image uploaded successfully!');
} else {
console.error('❌ Upload failed:', data.error);
alert('Error uploading cover image: ' + (data.error || 'Unknown error'));
}
})
.catch(error => {
console.error('❌ Upload network error:', error);
alert('Error uploading cover image. Please try again.');
});
}
function updateTrackCoverDisplay(imageUrl) {
const coverContainer = document.querySelector('.track-cover-section');
if (coverContainer) {
coverContainer.innerHTML = `
<img src="${imageUrl}" alt="Track Cover" class="cover-image">
${<?= $user_id && $user_id == $track['user_id'] ? 'true' : 'false' ?> ? `
<label for="trackCoverUpload" class="update-cover-btn">
<i class="fas fa-camera"></i>
</label>
<input type="file" id="trackCoverUpload" accept="image/*" style="display: none;">
` : ''}
`;
// Re-attach the file upload listener
const trackCoverUpload = document.getElementById('trackCoverUpload');
if (trackCoverUpload) {
trackCoverUpload.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
// Validate file type
if (!file.type.startsWith('image/')) {
alert('Please select an image file');
return;
}
// Validate file size (5MB max)
if (file.size > 5 * 1024 * 1024) {
alert('File size must be less than 5MB');
return;
}
uploadTrackCoverImage(file);
}
});
}
}
}
function playTrackFromWaveform(trackId, audioUrl, title, artist) {
playTrack(trackId, audioUrl, title, artist);
}
function recordTrackPlay(trackId) {
console.log('🎵 Recording play for track:', trackId);
// Record play analytics
fetch('/api_social.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `action=play&track_id=${trackId}`
})
.then(response => {
console.log('🎵 Play recording response status:', response.status);
return response.json();
})
.then(data => {
console.log('🎵 Play recording response data:', data);
if (data.success) {
console.log('✅ Play recorded successfully');
// Update play count display in real-time
updatePlayCount();
} else {
console.error('❌ Play recording failed:', data.message);
}
})
.catch(error => {
console.error('❌ Error recording play:', error);
// Still update the UI even if the API call fails
updatePlayCount();
});
}
function updatePlayCount() {
console.log('🎵 Updating play count display...');
// Update play count in track stats
const playCountElement = document.querySelector('.stat-item:first-child .stat-value');
if (playCountElement) {
const currentCount = parseInt(playCountElement.textContent.replace(/,/g, '')) || 0;
const newCount = currentCount + 1;
playCountElement.textContent = newCount.toLocaleString();
console.log('🎵 Updated track stats play count:', newCount);
// Add a subtle animation effect
playCountElement.style.transform = 'scale(1.1)';
playCountElement.style.color = '#ffd700';
setTimeout(() => {
playCountElement.style.transform = 'scale(1)';
playCountElement.style.color = '#667eea';
}, 300);
} else {
console.warn('🎵 Could not find track stats play count element');
}
// Also update play count in engagement section
const engagementPlayCount = document.querySelector('.engagement-item:first-child .engagement-value');
if (engagementPlayCount) {
const currentCount = parseInt(engagementPlayCount.textContent.replace(/,/g, '')) || 0;
const newCount = currentCount + 1;
engagementPlayCount.textContent = newCount.toLocaleString();
console.log('🎵 Updated engagement play count:', newCount);
// Add animation effect
engagementPlayCount.style.transform = 'scale(1.1)';
engagementPlayCount.style.color = '#ffd700';
setTimeout(() => {
engagementPlayCount.style.transform = 'scale(1)';
engagementPlayCount.style.color = '#667eea';
}, 300);
} else {
console.warn('🎵 Could not find engagement play count element');
}
}
// Load comments when page loads
document.addEventListener('DOMContentLoaded', function() {
loadComments(<?= $track['id'] ?>);
// Initialize track cover image upload functionality
const trackCoverUpload = document.getElementById('trackCoverUpload');
console.log('🎵 Track cover upload element found:', !!trackCoverUpload);
if (trackCoverUpload) {
trackCoverUpload.addEventListener('change', function(e) {
console.log('🎵 File input change event triggered');
const file = e.target.files[0];
console.log('🎵 Selected file:', file);
if (file) {
console.log('🎵 File validation starting...');
// Validate file type
if (!file.type.startsWith('image/')) {
console.error('❌ Invalid file type:', file.type);
alert('Please select an image file');
return;
}
// Validate file size (5MB max)
if (file.size > 5 * 1024 * 1024) {
console.error('❌ File too large:', file.size);
alert('File size must be less than 5MB');
return;
}
console.log('✅ File validation passed, starting upload...');
uploadTrackCoverImage(file);
} else {
console.log('❌ No file selected');
}
});
console.log('✅ File upload listener attached');
} else {
console.error('❌ Track cover upload element not found');
}
});
</script>
</body>
</html>