{"id":38224,"date":"2026-02-17T04:51:43","date_gmt":"2026-02-17T11:51:43","guid":{"rendered":"https:\/\/traklife.com\/culture\/?page_id=38224"},"modified":"2026-02-18T01:28:28","modified_gmt":"2026-02-18T08:28:28","slug":"radio-player","status":"publish","type":"page","link":"https:\/\/traklife.com\/culture\/radio-player\/","title":{"rendered":"Radio Player"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"38224\" class=\"elementor elementor-38224\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section data-particle_enable=\"false\" data-particle-mobile-disabled=\"false\" class=\"elementor-section elementor-top-section elementor-element elementor-element-448aa5d3 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"448aa5d3\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-360db7e5\" data-id=\"360db7e5\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-4f0f62f7 elementor-widget elementor-widget-text-editor\" data-id=\"4f0f62f7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\n<!-- Font Awesome -->\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/5.15.4\/css\/all.min.css\" integrity=\"sha512-1ycn6IcaQQ40\/MKBW2W4Rhis\/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY\/NS5R+E6ztJQ==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\" \/>\n\n<!-- Radio Player Widget HTML -->\n\n<div id=\"radio-player\" class=\"radio-player\" style=\"margin:0 auto;\">\n    \n    <div class=\"album-artwork\">\n        <img decoding=\"async\" class=\"artwork-image\" src=\"\" alt=\"Album Art\" style=\"display: none;\" \/>\n        <div class=\"artwork-placeholder\">ALBUM ARTWORK AREA<\/div>\n    <\/div>\n    \n\n    \n    <div class=\"time-bar-container\">\n        <div class=\"time-bar\">\n            <div class=\"time-bar-progress\"><\/div>\n        <\/div>\n    <\/div>\n    \n    \n    <div class=\"time-info\">\n        <span class=\"elapsed-time\">0:00<\/span>\n        <span class=\"duration-time\">0:00<\/span>\n    <\/div>\n    \n    <div class=\"station-info\">\n        <div class=\"radio-name\"><\/div>\n        \n        <div class=\"live-container\">\n            <div class=\"live-indicator\"><\/div>\n            <div class=\"live-text\">LIVE<\/div>\n        <\/div>\n        \n    <\/div>\n    \n    <div class=\"song-info\">\n        <div class=\"song-name\"><\/div>\n        <div class=\"artist-name\"><\/div>\n    <\/div>\n    \n    <div class=\"controls-container\">\n        <div class=\"controls\">\n            \n            <button class=\"control-button history-button\">\n                <i class=\"fas fa-history\"><\/i>\n            <\/button>\n            \n            <button class=\"control-button play-button\">\n                <i class=\"fas fa-play\"><\/i>\n            <\/button>\n            \n            <button class=\"control-button volume-button\">\n                <i class=\"fas fa-volume-up\"><\/i>\n            <\/button>\n            <div class=\"volume-bar-container\">\n                <input type=\"range\" class=\"volume-slider\" min=\"0\" max=\"100\" value=\"100\">\n            <\/div>\n            \n        <\/div>\n    <\/div>\n\n    <!-- History Modal -->\n    \n    <div class=\"history-modal\" style=\"display: none;\">\n        <div class=\"history-modal-overlay\"><\/div>\n        <div class=\"history-modal-content\">\n            <h3 class=\"history-modal-title\">Song History<\/h3>\n            <button class=\"history-modal-close\">\n                <i class=\"fas fa-times\"><\/i>\n            <\/button>\n            <div class=\"history-list\"><\/div>\n        <\/div>\n    <\/div>\n    \n<\/div>\n\n<!-- Radio Player Widget CSS -->\n<style>\n\n\/* Font imports *\/\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@400;500;600&display=swap');\n\n.radio-player {\n    font-family: 'Poppins', sans-serif;\n    position: relative;\n    width: 300px;\n    height: auto;\n    background: #f7f7f7;\n    border-radius: 8px;\n    border: 0px solid #f7f7f7;\n    padding: 15px;\n    margin: 10px;\n    box-sizing: border-box;\n    box-shadow: -2.82842712474619px 2.8284271247461903px 15px #NaNNaNNaN12;\n    color: #000000;\n    overflow: hidden;\n}\n\n.player-content {\n    display: flex;\n    flex-direction: column;\n    flex: 1;\n}\n\n.album-artwork {\n    width: 100%;\n    aspect-ratio: 1;\n    position: relative;\n    overflow: hidden;\n}\n\n.artwork-image {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n}\n\n.artwork-placeholder {\n    position: absolute;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    background: rgba(51, 51, 51, 0.2);\n    color: #000000;\n}\n\n.time-bar-container {\n    width: 100%;\n    padding: 5px 0;\n    position: relative;\n}\n\n.time-bar {\n    width: 100%;\n    height: 4px;\n    background: #00000033;\n    border-radius: 2px;\n    overflow: hidden;\n    position: relative;\n}\n\n.time-bar-progress {\n    height: 100%;\n    background: #000000;\n    width: 0;\n    border-radius: 2px;\n    transition: width 0.1s linear;\n}\n\n.time-info {\n    display: flex;\n    justify-content: space-between;\n    padding: 5px 0;\n    font-size: 12px;\n    color: #000000 !important;\n    width: 100%;\n}\n\n.elapsed-time {\n    text-align: left;\n}\n\n.duration-time {\n    text-align: right;\n}\n\n.station-info {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    width: 100%;\n    padding: 10px 0;\n}\n\n.radio-name {\n    font-size: 12px;\n    font-weight: 600;\n    color: #000000 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.live-container {\n    display: flex;\n    align-items: center;\n    gap: 5px;\n}\n\n.live-indicator {\n    width: 8px;\n    height: 8px;\n    border-radius: 50%;\n    background: #FF0000;\n    animation: pulse 2s infinite;\n}\n\n.live-text {\n    font-size: 12px;\n    color: #000000 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.song-info {\n    width: 100%;\n    padding: 15px 0;\n    text-align: center;\n}\n\n.song-name {\n    font-size: 14px;\n    font-weight: bold;\n    margin-bottom: 5px;\n    color: #000000 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.artist-name {\n    font-size: 12px;\n    opacity: 0.8;\n    color: #000000 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.controls-container {\n    position: relative;\n    width: 100%;\n}\n\n.controls {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 30px;\n    padding: 15px 20px;\n}\n\n.control-button {\n    background: #e9e9e9;\n    border: none;\n    color: #000000 !important;\n    cursor: pointer;\n    padding: 0.5rem;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 1rem;\n    font-weight: normal;\n    box-shadow: -1.414213562373095px 1.4142135623730951px 4px #NaNNaNNaN1a;\n    border-radius: 50%;\n    min-width: 36px;\n    width: 36px;\n    height: 36px;\n    aspect-ratio: 1;\n    text-transform: none;\n    transition: color 0.1s ease;\n}\n\n.control-button:hover {\n    color: #e6ac49 !important;\n}\n\n.volume-bar-container {\n    position: absolute;\n    bottom: calc(100% + 5px);\n    left: 50%;\n    transform: translate(170%, 15px);\n    background: #f7f7f7;\n    padding: 12px 8px;\n    border-radius: 8px;\n    opacity: 0;\n    visibility: hidden;\n    transition: all 0.2s ease;\n    z-index: 100;\n    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n    cursor: default;\n    height: 100px;\n    width: 32px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n\n.volume-bar-container:before {\n    content: '';\n    position: absolute;\n    bottom: -5px;\n    left: 50%;\n    transform: translateX(-50%);\n    width: 0;\n    height: 0;\n    border-left: 5px solid transparent;\n    border-right: 5px solid transparent;\n    border-top: 5px solid #f7f7f7;\n}\n\n.volume-bar-container.show {\n    opacity: 1;\n    visibility: visible;\n}\n\n.volume-slider {\n    -webkit-appearance: none !important;\n    appearance: none !important;\n    width: 80px !important;\n    height: 4px !important;\n    background: #00000040 !important;\n    border-radius: 2px !important;\n    outline: none !important;\n    transform: rotate(-90deg) !important;\n    transform-origin: center !important;\n    margin: 0 !important;\n    cursor: pointer !important;\n    position: absolute !important;\n    border: none !important;\n    box-shadow: none !important;\n}\n\n.volume-slider::-webkit-slider-thumb {\n    -webkit-appearance: none !important;\n    appearance: none !important;\n    width: 12px !important;\n    height: 12px !important;\n    background: #000000 !important;\n    border-radius: 50% !important;\n    cursor: pointer !important;\n    transition: transform 0.2s ease !important;\n    transform-origin: center !important;\n    border: none !important;\n    margin-top: -4px !important;\n    box-shadow: none !important;\n}\n\n.volume-slider::-moz-range-thumb {\n    width: 12px !important;\n    height: 12px !important;\n    background: #000000 !important;\n    border-radius: 50% !important;\n    cursor: pointer !important;\n    transition: transform 0.2s ease !important;\n    transform-origin: center !important;\n    border: none !important;\n    margin-top: -4px !important;\n    box-shadow: none !important;\n}\n\n.volume-slider::-webkit-slider-runnable-track {\n    height: 4px !important;\n    border-radius: 2px !important;\n    background: inherit !important;\n    border: none !important;\n    box-shadow: none !important;\n}\n\n.volume-slider::-moz-range-track {\n    height: 4px !important;\n    border-radius: 2px !important;\n    background: inherit !important;\n    border: none !important;\n    box-shadow: none !important;\n}\n\n.volume-slider::-webkit-slider-thumb:hover {\n    transform: scale(1.2) !important;\n}\n\n.volume-slider::-moz-range-thumb:hover {\n    transform: scale(1.2) !important;\n}\n\n.volume-button:hover .volume-bar-container,\n.volume-bar-container:hover {\n    opacity: 1;\n    visibility: visible;\n}\n\n\/* History Modal Styles *\/\n.history-modal {\n    position: fixed;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    z-index: 9999;\n}\n\n.history-modal-overlay {\n    position: fixed;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    background: rgba(0, 0, 0, 0.5);\n    z-index: 10000;\n}\n\n.history-modal-content {\n    position: fixed;\n    top: 50%;\n    left: 50%;\n    transform: translate(-50%, -50%);\n    background: #f7f7f7;\n    padding: 1.45rem;\n    border-radius: 12px;\n    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);\n    z-index: 10001;\n    max-width: 500px;\n    width: 90%;\n    max-height: 80vh;\n    overflow-y: auto;\n    font-family: 'Poppins', sans-serif;\n    scrollbar-width: thin;\n    scrollbar-color: rgba(255, 255, 255, 0.3) transparent;\n}\n\n\/* WebKit scrollbar styles *\/\n.history-modal-content::-webkit-scrollbar {\n    width: 6px;\n    height: 6px;\n}\n\n.history-modal-content::-webkit-scrollbar-track {\n    background: transparent;\n    border-radius: 3px;\n}\n\n.history-modal-content::-webkit-scrollbar-thumb {\n    background: rgba(255, 255, 255, 0.3);\n    border-radius: 3px;\n    transition: background 0.2s;\n}\n\n.history-modal-content::-webkit-scrollbar-thumb:hover {\n    background: rgba(255, 255, 255, 0.5);\n}\n\n.history-modal-title {\n    font-size: 1.125rem;\n    font-weight: 600;\n    color: #000000 !important;\n    margin: 0 0 0.97rem 0;\n    padding-right: 1.45rem;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.history-modal-close {\n    position: absolute;\n    top: 0.97rem;\n    right: 0.97rem;\n    background: none;\n    border: none;\n    color: #000000 !important;\n    cursor: pointer;\n    padding: 0.387rem;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border-radius: 7px;\n}\n\n.history-modal-close:hover {\n    background: rgba(255, 255, 255, 0.1);\n}\n\n.history-list {\n    display: flex;\n    flex-direction: column;\n    gap: 1rem;\n}\n\n.history-item {\n    display: flex;\n    gap: 1rem;\n    align-items: center;\n    padding: 0.5rem;\n    border-radius: 8px;\n    transition: background-color 0.2s;\n}\n\n.history-item:hover {\n    background: rgba(255, 255, 255, 0.05);\n}\n\n.history-artwork {\n    width: 50px;\n    height: 50px;\n    border-radius: 4px;\n    overflow: hidden;\n    flex-shrink: 0;\n}\n\n.history-artwork img {\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n}\n\n.history-song-info {\n    display: flex;\n    flex-direction: column;\n    gap: 0.25rem;\n}\n\n.history-song-title {\n    font-size: 0.875rem;\n    font-weight: 500;\n    color: #000000 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n.history-artist-name {\n    font-size: 0.75rem;\n    color: #00000099 !important;\n    letter-spacing: 0px;\n    line-height: 1.5em;\n    word-spacing: 0px;\n}\n\n@keyframes pulse {\n    0% { opacity: 1; }\n    50% { opacity: 0.5; }\n    100% { opacity: 1; }\n}\n\n.radio-player .control-button {\n    padding: 5px;\n    width: 36px;\n    height: 36px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 1rem;\n}\n\n.radio-player .control-button.play-button {\n    width: calc(36px * 1.3);\n    height: calc(36px * 1.3);\n    font-size: 1.5rem;\n}\n\n.radio-player .control-button .fa-play {\n    margin-left: 2px;\n    font-size: inherit;\n}\n\n.radio-player .control-button .fa-pause {\n    font-size: inherit;\n}\n\n\n<\/style>\n\n\n<script>\nclass RadioPlayer {\n    constructor(container, config) {\n        this.container = container;\n        this.config = config;\n        this.audio = new Audio();\n        this.isPlaying = false;\n        this.currentVolume = 1;\n        this.elapsed = 0;\n        this.metadata = null;\n        this.lastFetchTime = 0;\n        this.fetchInProgress = false;\n\n        this.init();\n    }\n\n    init() {\n        this.audio.src = this.config.streamUrl;\n        this.audio.preload = 'none';\n\n        this.setupElements();\n        this.attachEventListeners();\n        this.startMetadataPolling();\n        this.startTimeTracking();\n    }\n\n    setupElements() {\n        this.artworkImage = this.container.querySelector('.artwork-image');\n        this.artworkPlaceholder = this.container.querySelector('.artwork-placeholder');\n        this.songNameDiv = this.container.querySelector('.song-name');\n        this.artistNameDiv = this.container.querySelector('.artist-name');\n        this.radioNameDiv = this.container.querySelector('.radio-name');\n        if (this.radioNameDiv) {\n            this.radioNameDiv.style.fontWeight = '600';\n        }\n        this.liveContainer = this.container.querySelector('.live-container');\n        this.playButton = this.container.querySelector('.play-button');\n        this.volumeButton = this.container.querySelector('.volume-button');\n        this.volumeSlider = this.container.querySelector('.volume-slider');\n        this.timeBarProgress = this.container.querySelector('.time-bar-progress');\n        this.elapsedTimeSpan = this.container.querySelector('.elapsed-time');\n        this.durationTimeSpan = this.container.querySelector('.duration-time');\n        this.historyModal = document.querySelector('.history-modal');\n        this.historyList = document.querySelector('.history-list');\n\n        \/\/ Initialize volume state\n        if (this.volumeSlider) {\n            this.volumeSlider.value = 100;\n            this.isMuted = false;\n            this.preMuteVolume = 1;\n        }\n\n        \/\/ Apply border color if specified\n        if (this.config.borderColor) {\n            this.container.style.borderColor = this.config.borderColor;\n        }\n\n        if (this.volumeButton && this.volumeSlider) {\n            this.setupVolumeControls();\n        }\n\n        if (this.historyModal) {\n            this.attachHistoryEventListeners();\n        }\n    }\n\n    setupVolumeControls() {\n        const volumeContainer = this.container.querySelector('.volume-bar-container');\n        let hideTimeout;\n\n        const showVolume = () => {\n            clearTimeout(hideTimeout);\n            volumeContainer.classList.add('show');\n        };\n\n        const hideVolume = () => {\n            hideTimeout = setTimeout(() => {\n                volumeContainer.classList.remove('show');\n            }, 200);\n        };\n\n        \/\/ Hover events\n        this.volumeButton.addEventListener('mouseenter', showVolume);\n        this.volumeButton.addEventListener('mouseleave', hideVolume);\n        volumeContainer.addEventListener('mouseenter', showVolume);\n        volumeContainer.addEventListener('mouseleave', hideVolume);\n\n        \/\/ Click events\n        this.volumeButton.addEventListener('click', (e) => {\n            e.stopPropagation();\n            this.toggleMute();\n        });\n\n        this.volumeSlider.addEventListener('input', (e) => {\n            const value = e.target.value \/ 100;\n            this.setVolume(value);\n            if (value > 0 && this.isMuted) {\n                this.isMuted = false;\n            }\n        });\n\n        \/\/ Close volume bar when clicking outside\n        document.addEventListener('click', (e) => {\n            if (!e.target.closest('.volume-bar-container') && \n                !e.target.closest('.volume-button')) {\n                volumeContainer.classList.remove('show');\n            }\n        });\n    }\n\n    attachEventListeners() {\n        this.audio.addEventListener('play', () => this.updatePlayState());\n        this.audio.addEventListener('pause', () => this.updatePlayState());\n        this.audio.addEventListener('volumechange', () => this.updateVolumeState());\n\n        if (this.playButton) {\n            this.playButton.addEventListener('click', () => this.togglePlay());\n        }\n    }\n\n    startMetadataPolling() {\n        this.fetchMetadata();\n        setInterval(() => this.fetchMetadata(), 10000);\n    }\n\n    startTimeTracking() {\n        this.elapsedInterval = setInterval(() => {\n            this.elapsed++;\n            this.updateTimeDisplay();\n        }, 1000);\n    }\n\n    async fetchMetadata() {\n        if (this.fetchInProgress || Date.now() - this.lastFetchTime < 2000) return;\n        this.fetchInProgress = true;\n\n        try {\n            const response = await fetch(this.config.apiUrl);\n            const data = await response.json();\n            this.metadata = data;\n            this.updateMetadata(data);\n            this.lastFetchTime = Date.now();\n        } catch (error) {\n            console.error('Error fetching metadata:', error);\n        } finally {\n            this.fetchInProgress = false;\n        }\n    }\n\n    async togglePlay() {\n        try {\n            if (this.isPlaying) {\n                this.audio.pause();\n            } else {\n                await this.audio.play();\n            }\n            this.isPlaying = !this.isPlaying;\n            this.updatePlayState();\n        } catch (error) {\n            console.error('Error toggling play state:', error);\n        }\n    }\n\n    updatePlayState() {\n        if (this.playButton) {\n            if ('circle' === 'text') {\n                this.playButton.textContent = this.isPlaying ? 'Pause' : 'Play';\n            } else {\n                this.playButton.innerHTML = `<i class=\"fas fa-${this.isPlaying ? 'pause' : 'play'}\"><\/i>`;\n            }\n        }\n    }\n\n    setVolume(value) {\n        this.audio.volume = value;\n        this.currentVolume = value;\n        this.isMuted = value === 0;\n        this.updateVolumeState();\n    }\n\n    toggleMute() {\n        if (this.audio.volume > 0) {\n            this.preMuteVolume = this.audio.volume;\n            this.setVolume(0);\n        } else {\n            this.setVolume(this.preMuteVolume);\n        }\n    }\n\n    updateVolumeState() {\n        if (this.volumeButton && this.volumeSlider) {\n            const volume = this.audio.volume;\n            this.volumeSlider.value = volume * 100;\n            \n            let icon = 'volume-up';\n            if (volume === 0) icon = 'volume-mute';\n            else if (volume < 0.33) icon = 'volume-off';\n            else if (volume < 0.66) icon = 'volume-down';\n\n            if ('circle' === 'text') {\n                this.volumeButton.textContent = volume === 0 ? 'Unmute' : 'Mute';\n            } else {\n                this.volumeButton.innerHTML = `<i class=\"fas fa-${icon}\"><\/i>`;\n            }\n        }\n    }\n\n    formatTime(seconds) {\n        const mins = Math.floor(seconds \/ 60);\n        const secs = Math.floor(seconds % 60);\n        return `${mins}:${secs.toString().padStart(2, '0')}`;\n    }\n\n    updateTimeDisplay() {\n        if (this.timeBarProgress && this.metadata?.now_playing) {\n            const duration = this.metadata.now_playing.duration || 0;\n            const progress = duration > 0 ? (this.elapsed \/ duration) * 100 : 0;\n            this.timeBarProgress.style.width = `${Math.min(progress, 100)}%`;\n        }\n        \n        if (this.elapsedTimeSpan) {\n            this.elapsedTimeSpan.textContent = this.formatTime(this.elapsed);\n        }\n        if (this.durationTimeSpan && this.metadata?.now_playing) {\n            this.durationTimeSpan.textContent = this.formatTime(this.metadata.now_playing.duration || 0);\n        }\n    }\n\n    updateMetadata(data) {\n        const nowPlaying = data.now_playing;\n        if (!nowPlaying) return;\n\n        \/\/ Reset elapsed time when new song starts\n        this.elapsed = Math.max(0, data.now_playing.elapsed || 0);\n\n        \/\/ Update artwork\n        if (this.artworkImage && nowPlaying.song.art) {\n            this.artworkImage.src = nowPlaying.song.art;\n            this.artworkImage.style.display = 'block';\n            this.artworkPlaceholder.style.display = 'none';\n        } else if (this.artworkImage) {\n            this.artworkImage.style.display = 'none';\n            this.artworkPlaceholder.style.display = 'flex';\n        }\n\n        \/\/ Update song info\n        if (this.songNameDiv) {\n            this.songNameDiv.textContent = nowPlaying.song.title || '';\n        }\n        if (this.artistNameDiv) {\n            this.artistNameDiv.textContent = nowPlaying.song.artist || '';\n        }\n\n        \/\/ Update radio name\n        if (this.radioNameDiv && data.station?.name) {\n            this.radioNameDiv.textContent = data.station.name;\n        }\n\n        \/\/ Update live status\n        if (this.liveContainer) {\n            const isLive = data.live?.is_live || false;\n            this.liveContainer.style.display = isLive ? 'flex' : 'none';\n            const liveText = this.liveContainer.querySelector('.live-text');\n            if (liveText && isLive) {\n                liveText.textContent = data.live?.streamer_name || 'LIVE';\n            }\n        }\n\n        \/\/ Update history list if modal is open\n        if (this.historyModal && this.historyModal.style.display === 'block') {\n            this.updateHistoryList();\n        }\n    }\n\n    cleanup() {\n        if (this.elapsedInterval) {\n            clearInterval(this.elapsedInterval);\n            this.elapsedInterval = null;\n        }\n        if (this.metadataInterval) {\n            clearInterval(this.metadataInterval);\n            this.metadataInterval = null;\n        }\n        if (this.audio) {\n            this.audio.pause();\n            this.audio.src = '';\n            this.isPlaying = false;\n            this.currentVolume = 1;\n            this.elapsed = 0;\n            this.metadata = null;\n            this.lastFetchTime = 0;\n            this.fetchInProgress = false;\n        }\n        if (this.historyModal) {\n            this.hideHistoryModal();\n        }\n    }\n\n    attachHistoryEventListeners() {\n        const historyButton = this.container.querySelector('.history-button');\n        const historyModalClose = document.querySelector('.history-modal-close');\n        const historyModalOverlay = document.querySelector('.history-modal-overlay');\n\n        if (historyButton && this.historyModal) {\n            historyButton.addEventListener('click', () => this.showHistoryModal());\n            historyModalClose.addEventListener('click', () => this.hideHistoryModal());\n            historyModalOverlay.addEventListener('click', () => this.hideHistoryModal());\n        }\n    }\n\n    showHistoryModal() {\n        if (this.historyModal && this.metadata?.song_history) {\n            this.updateHistoryList();\n            this.historyModal.style.display = 'block';\n            document.body.style.overflow = 'hidden';\n        }\n    }\n\n    hideHistoryModal() {\n        if (this.historyModal) {\n            this.historyModal.style.display = 'none';\n            document.body.style.overflow = '';\n        }\n    }\n\n    updateHistoryList() {\n        if (!this.historyList || !this.metadata?.song_history) return;\n\n        this.historyList.innerHTML = this.metadata.song_history.map(item => `\n            <div class=\"history-item\">\n                <div class=\"history-artwork\">\n                    <img decoding=\"async\" src=\"${item.song.art}\" alt=\"${item.song.title}\" \/>\n                <\/div>\n                <div class=\"history-song-info\">\n                    <div class=\"history-song-title\">${item.song.title}<\/div>\n                    <div class=\"history-artist-name\">${item.song.artist}<\/div>\n                <\/div>\n            <\/div>\n        `).join('');\n    }\n}\n\n\/\/ Initialize the player\ndocument.addEventListener('DOMContentLoaded', () => {\n    const container = document.getElementById('radio-player');\n    const config = {\n        streamUrl: 'https:\/\/s49.radiolize.com\/radio\/8040\/radio.mp3',\n        apiUrl: 'https:\/\/s49.radiolize.com\/api\/nowplaying\/96',\n        borderColor: 'transparent'\n    };\n    window.radioPlayer = new RadioPlayer(container, config);\n});\n\n\/\/ Cleanup on page unload\nwindow.addEventListener('unload', () => {\n    if (window.radioPlayer) {\n        window.radioPlayer.cleanup();\n    }\n});\n<\/script>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section data-particle_enable=\"false\" data-particle-mobile-disabled=\"false\" class=\"elementor-section elementor-top-section elementor-element elementor-element-5da90c0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"5da90c0\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-befff32\" data-id=\"befff32\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2d82f9b elementor-widget elementor-widget-heading\" data-id=\"2d82f9b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Track History<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-02891c2 elementor-widget elementor-widget-html\" data-id=\"02891c2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<iframe src=\"https:\/\/s49.radiolize.com\/public\/traklife_radio_gcen4v\/history?theme=light\" frameborder=\"0\" allowtransparency=\"true\" style=\"width: 100%; min-height: 550px; border: 0;\"><\/iframe>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>ALBUM ARTWORK AREA 0:00 0:00 LIVE Song History Track History<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-38224","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Radio Player - Traklife Music - Culture<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/traklife.com\/culture\/radio-player\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Radio Player - Traklife Music - Culture\" \/>\n<meta property=\"og:description\" content=\"ALBUM ARTWORK AREA 0:00 0:00 LIVE Song History Track History\" \/>\n<meta property=\"og:url\" content=\"https:\/\/traklife.com\/culture\/radio-player\/\" \/>\n<meta property=\"og:site_name\" content=\"Traklife Music - Culture\" \/>\n<meta property=\"article:modified_time\" content=\"2026-02-18T08:28:28+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/traklife.com\/culture\/radio-player\/\",\"url\":\"https:\/\/traklife.com\/culture\/radio-player\/\",\"name\":\"Radio Player - Traklife Music - Culture\",\"isPartOf\":{\"@id\":\"https:\/\/traklife.com\/culture\/#website\"},\"datePublished\":\"2026-02-17T11:51:43+00:00\",\"dateModified\":\"2026-02-18T08:28:28+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/traklife.com\/culture\/radio-player\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/traklife.com\/culture\/radio-player\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/traklife.com\/culture\/radio-player\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/traklife.com\/culture\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Radio Player\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/traklife.com\/culture\/#website\",\"url\":\"https:\/\/traklife.com\/culture\/\",\"name\":\"Traklife Music - Culture\",\"description\":\"Curated music, performances, conversations, and documentation from the Traklife community.\",\"publisher\":{\"@id\":\"https:\/\/traklife.com\/culture\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/traklife.com\/culture\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/traklife.com\/culture\/#organization\",\"name\":\"Traklife Music - Culture\",\"url\":\"https:\/\/traklife.com\/culture\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/traklife.com\/culture\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/traklife.com\/culture\/wp-content\/uploads\/sites\/22\/2023\/08\/cropped-traklife-main-logo-light.png\",\"contentUrl\":\"https:\/\/traklife.com\/culture\/wp-content\/uploads\/sites\/22\/2023\/08\/cropped-traklife-main-logo-light.png\",\"width\":129,\"height\":38,\"caption\":\"Traklife Music - Culture\"},\"image\":{\"@id\":\"https:\/\/traklife.com\/culture\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Radio Player - Traklife Music - Culture","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/traklife.com\/culture\/radio-player\/","og_locale":"en_US","og_type":"article","og_title":"Radio Player - Traklife Music - Culture","og_description":"ALBUM ARTWORK AREA 0:00 0:00 LIVE Song History Track History","og_url":"https:\/\/traklife.com\/culture\/radio-player\/","og_site_name":"Traklife Music - Culture","article_modified_time":"2026-02-18T08:28:28+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/traklife.com\/culture\/radio-player\/","url":"https:\/\/traklife.com\/culture\/radio-player\/","name":"Radio Player - Traklife Music - Culture","isPartOf":{"@id":"https:\/\/traklife.com\/culture\/#website"},"datePublished":"2026-02-17T11:51:43+00:00","dateModified":"2026-02-18T08:28:28+00:00","breadcrumb":{"@id":"https:\/\/traklife.com\/culture\/radio-player\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/traklife.com\/culture\/radio-player\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/traklife.com\/culture\/radio-player\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/traklife.com\/culture\/"},{"@type":"ListItem","position":2,"name":"Radio Player"}]},{"@type":"WebSite","@id":"https:\/\/traklife.com\/culture\/#website","url":"https:\/\/traklife.com\/culture\/","name":"Traklife Music - Culture","description":"Curated music, performances, conversations, and documentation from the Traklife community.","publisher":{"@id":"https:\/\/traklife.com\/culture\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/traklife.com\/culture\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/traklife.com\/culture\/#organization","name":"Traklife Music - Culture","url":"https:\/\/traklife.com\/culture\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/traklife.com\/culture\/#\/schema\/logo\/image\/","url":"https:\/\/traklife.com\/culture\/wp-content\/uploads\/sites\/22\/2023\/08\/cropped-traklife-main-logo-light.png","contentUrl":"https:\/\/traklife.com\/culture\/wp-content\/uploads\/sites\/22\/2023\/08\/cropped-traklife-main-logo-light.png","width":129,"height":38,"caption":"Traklife Music - Culture"},"image":{"@id":"https:\/\/traklife.com\/culture\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/pages\/38224","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/comments?post=38224"}],"version-history":[{"count":61,"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/pages\/38224\/revisions"}],"predecessor-version":[{"id":38327,"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/pages\/38224\/revisions\/38327"}],"wp:attachment":[{"href":"https:\/\/traklife.com\/culture\/wp-json\/wp\/v2\/media?parent=38224"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}