1// --- Kombinált, régi és új logika: minden funkció működik, csatornaváltáskor minden UI frissül --- 2 3$(document).ready(function () { 4 const audio = document.getElementById('radio-player'); 5 const apiKey = '9e84032a429186dc2ccc2538a6c632b7'; 6 const defaultCover = 'assets/images/logosdr.png'; 7 8 // Csatorna API-k (playlist és info) 9 const channelInfo = { 10 "1": { 11 stream: "https://s03.diazol.hu:35152/stream", 12 info: "https://s03.diazol.hu:633/api/info.cgi?user=superdjradio&streamid=1&mount=%2Fstream&out=json", 13 playlist: "https://s03.diazol.hu:633/api/playlist.cgi?user=superdjradio&streamid=1&mount=%2Fstream&num=10&out=json" 14 }, 15 "2": { 16 stream: "https://s03.diazol.hu:35152/stream2", 17 info: "https://s03.diazol.hu:633/api/info.cgi?user=superdjradio&streamid=5&mount=%2Fstream2&out=json", 18 playlist: "https://s03.diazol.hu:633/api/playlist.cgi?user=superdjradio&streamid=5&mount=%2Fstream2&num=10&out=json" 19 }, 20 "3": { 21 stream: "https://s03.diazol.hu:35152/stream3", 22 info: "https://s03.diazol.hu:633/api/info.cgi?user=superdjradio&streamid=9&mount=%2Fstream3&out=json", 23 playlist: "https://s03.diazol.hu:633/api/playlist.cgi?user=superdjradio&streamid=9&mount=%2Fstream3&num=10&out=json" 24 }, 25 "4": { 26 stream: "https://s03.diazol.hu:35152/stream4", 27 info: "https://s03.diazol.hu:633/api/info.cgi?user=superdjradio&streamid=13&mount=%2Fstream4&out=json", 28 playlist: "https://s03.diazol.hu:633/api/playlist.cgi?user=superdjradio&streamid=13&mount=%2Fstream4&num=10&out=json" 29 } 30 }; 31 32 let currentChannel = "1"; 33 let infoInterval = null; 34 35 // --- UI vezérlés (hangerÅ, play/pause, sticky) --- 36 $('#play-btn, #sticky-play-btn').click(function () { 37 if (audio.paused) { 38 audio.play(); 39 } else { 40 audio.pause(); 41 } 42 }); 43 44 // A play/szünet ikon a hangelem tényleges állapotát követi 45 function syncPlayIcons() { 46 const playing = !audio.paused && !audio.error; 47 $('#play-btn i, #sticky-play-btn i').toggleClass('fa-pause', playing).toggleClass('fa-play', !playing); 48 } 49 $(audio).on('play pause ended error', syncPlayIcons); 50 51 // Az alsó lejátszó csak akkor látszik, ha a felsÅ már kigördült a képbÅl 52 let stickyCollapsed = true; // az elsÅ lejátszásig rejtve marad 53 let topPlayerVisible = true; 54 55 function updateStickyPlayer() { 56 $('#sticky-radio-player').toggleClass('d-none', stickyCollapsed || topPlayerVisible); 57 $('#toggle-sticky-player').toggleClass('d-none', topPlayerVisible) 58 .find('i').toggleClass('fa-chevron-down', !stickyCollapsed).toggleClass('fa-headphones', stickyCollapsed); 59 } 60 61 new IntersectionObserver(function (entries) { 62 topPlayerVisible = entries[0].isIntersecting; 63 updateStickyPlayer(); 64 }).observe(document.querySelector('.radio-player')); 65 66 $(audio).on('play', function () { 67 stickyCollapsed = false; 68 updateStickyPlayer(); 69 }); 70 71 $('#toggle-sticky-player').click(function () { 72 stickyCollapsed = !stickyCollapsed; 73 updateStickyPlayer(); 74 }); 75 76 // A két hangerÅszabályzó együtt mozog 77 $('#volume-control').hide(); 78 $('#volume-btn').click(function () { 79 $('#volume-control').toggle(); 80 }); 81 82 $('#sticky-volume-control').hide(); 83 $('#sticky-volume-btn').click(function () { 84 $('#sticky-volume-control').toggle(); 85 }); 86 87 $('#volume-slider, #sticky-volume-slider').on('input', function () { 88 audio.volume = $(this).val(); 89 }); 90 $(audio).on('volumechange', function () { 91 $('#volume-slider, #sticky-volume-slider').val(audio.volume); 92 }); 93 94 // Az adatforrás az ékezetes cÃmeket néha hibás kódolással adja (âÃÂ" az âÃ" helyett); 95 // ezt visszaalakÃtjuk, a jó szöveget pedig érintetlenül hagyjuk 96 function fixEncoding(text) { 97 try { 98 return decodeURIComponent(escape(text)); 99 } catch (e) { 100 return text; 101 } 102 } 103 104 // Ha a kapott borÃtó nem tölthetÅ be, a rádió logója marad a lejátszókban 105 $('#album-cover-img, #sticky-album-cover').on('error', function () { 106 if (!this.src.endsWith(defaultCover)) this.src = defaultCover; 107 });
108 109 // --- DalcÃm, elÅadó, borÃtókép frissÃtése --- 110 // Playlist API-t használunk, hogy mindig a ténylegesen játszott dal jelenjen meg (és ne sweeper vagy azonosÃtó) 111 function updatePlayerInfo(channelId) { 112 const playlistUrl = channelInfo[channelId].playlist; 113 $.ajax({ 114 url: playlistUrl, 115 dataType: 'json', 116 cache: false, 117 success: function (data) { 118 // Keressük az elsÅ valódi dalt (artist és title nem üres, title nem sweeper/superdjradio) 119 let song = null; 120 if (data.mscp && Array.isArray(data.mscp.playlist)) { 121 song = data.mscp.playlist.find(item => 122 item.title && 123 item.title.trim() !== '' && 124 !/^sweeper/i.test(item.title) && 125 !/^superdjradio/i.test(item.title) 126 ); 127 } 128 const title = song && song.title ? fixEncoding(song.title) : 'Ismeretlen szám'; 129 const artist = song && song.artist ? fixEncoding(song.artist) : 'Ismeretlen elÅadó'; 130 $('#song-title').text(title); 131 $('#artist-name').text(artist); 132 $('#sticky-song-title').text(title); 133 $('#sticky-artist-name').text(artist); 134 135 // BorÃtókép Last.fm-rÅl 136 $.getJSON(`https://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=${apiKey}&artist=${encodeURIComponent(artist)}&track=${encodeURIComponent(title)}&format=json`, function (trackData) { 137 let albumCover = defaultCover; 138 if (trackData.track && trackData.track.album && trackData.track.album.image) { 139 const coverImage = trackData.track.album.image.find(img => img.size === 'large'); 140 if (coverImage && coverImage['#text']) { 141 albumCover = coverImage['#text']; 142 } 143 } 144 $('#album-cover-img').attr('src', albumCover); 145 $('#sticky-album-cover').attr('src', albumCover); 146 }).fail(function () { 147 $('#album-cover-img').attr('src', defaultCover); 148 $('#sticky-album-cover').attr('src', defaultCover); 149 }); 150 }, 151 error: function () { 152 $('#song-title').text('Ismeretlen szám'); 153 $('#artist-name').text('Ismeretlen elÅadó'); 154 $('#album-cover-img').attr('src', defaultCover); 155 $('#sticky-album-cover').attr('src', defaultCover); 156 } 157 }); 158 } 159 160 function startInfoPolling(channelId) { 161 if (infoInterval) clearInterval(infoInterval); 162 updatePlayerInfo(channelId); 163 infoInterval = setInterval(function () { 164 updatePlayerInfo(channelId); 165 }, 10000); 166 } 167 168 // --- Nem rég szólt nálunk dinamikus frissÃtése borÃtóképpel --- 169 let playlistInterval = null; 170 let lastRecentSongs = []; 171 172 function updateRecentSongs(channelId) { 173 const playlistUrl = channelInfo[channelId].playlist; 174 fetch(playlistUrl) 175 .then(response => response.json()) 176 .then(data => { 177 // Csak az utolsó 3 zene kell, a most szólót kihagyva 178 const playlist = (data.mscp && Array.isArray(data.mscp.playlist)) ? data.mscp.playlist.slice(1, 4) : []; 179 const currentSongs = playlist.map(song => ({ 180 title: song.title || 'Ismeretlen szám', 181 artist: song.artist || 'Ismeretlen elÅadó', 182 time: song.time || '', 183 })); 184 185 const recentSongsContainer = document.getElementById('recent-songs'); 186 if (!recentSongsContainer) return; 187 188 // EllenÅrizzük, hogy változott-e a tartalom (visszanavigálás után a konténer üres) 189 if (JSON.stringify(currentSongs) === JSON.stringify(lastRecentSongs) && recentSongsContainer.children.length) { 190 // Nem változott, ne frissÃtsük a DOM-ot 191 return; 192 } 193 lastRecentSongs = currentSongs; 194 195 recentSongsContainer.innerHTML = ''; 196 197 playlist.forEach(song => { 198 const title = fixEncoding(song.title || 'Ismeretlen szám'); 199 const artist = fixEncoding(song.artist || 'Ismeretlen elÅadó'); 200 // Az idÅbÅl elég az óra és a perc (17:41:35 -> 17:41) 201 const time = (song.time || '').replace(/^(\d{1,2}:\d{2}):\d{2}$/, '$1'); 202 const defaultCover = 'assets/images/logosdr.png'; 203 204 // Kártya létrehozása alapértelmezett borÃtóval 205 const card = document.createElement('div'); 206 card.className = 'col-md-4'; 207 card.innerHTML = ` 208 <div class="card bg-dark text-white h-100 shadow recent-song-card"> 209 <img src="${defaultCover}" alt="BorÃtókép" class="card-img-top recent-cover-img" style="max-height:200px;object-fit:cover;"> 210 <div class="card-body"> 211 <h5 class="card-title">${title}</h5> 212 <p class="card-text">${artist}</p> 213 <small class="text-muted">${time}</small> 214 </div> 215 </div> 216 `; 217 recentSongsContainer.appendChild(card); 218 219 // BorÃtókép aszinkron betöltése Last.fm-rÅl 220 $.getJSON(`https://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=${apiKey}&artist=${encodeURIComponent(artist)}&track=${encodeURIComponent(title)}&format=json`, function (trackData) { 221 let albumCover = defaultCover; 222 if (trackData.track && trackData.track.album && trackData.track.album.image) { 223 const coverImage = trackData.track.album.image.find(img => img.size === 'large'); 224 if (coverImage && coverImage['#text']) { 225 albumCover = coverImage['#text']; 226 } 227 } 228 const img = card.querySelector('.recent-cover-img'); 229 if (img) img.src = albumCover; 230 }).fail(function () { 231 // Ha nincs borÃtó, marad az alapértelmezett 232 }); 233 }); 234 }) 235 .catch(error => { 236 console.error('Error fetching recent songs:', error); 237 }); 238 } 239 240 function startPlaylistPolling(channelId) { 241 if (playlistInterval) clearInterval(playlistInterval); 242 updateRecentSongs(channelId); 243 playlistInterval = setInterval(function () { 244 updateRecentSongs(channelId); 245 }, 10000); 246 } 247 248 // --- Csatornaváltás --- 249 function switchChannel(streamId) { 250 audio.src = channelInfo[streamId].stream; 251 audio.play(); 252 currentChannel = streamId; 253 startInfoPolling(currentChannel); 254 255 // Az alsó lejátszó gombján a kiválasztott csatorna neve 256 const menuItem = $('.dropdown-item[data-streamid="' + streamId + '"]').first(); 257 $('#sticky-channel-name').text(menuItem.text().replace('ð§', '').trim()); 258 259 // Nem rég szólt nálunk frissÃtése 260 startPlaylistPolling(currentChannel); 261 updateChannelCards(); 262 } 263 264 $('.dropdown-item[data-streamid]').click(function (e) { 265 e.preventDefault(); 266 switchChannel($(this).attr('data-streamid') || "1"); 267 });
268 269 // --- KezdÅlapi csatornakártyák --- 270 // A kártyák a tartalommal együtt cserélÅdnek, ezért delegált eseménykezelés kell 271 $(document).on('click', '.channel-play', function () { 272 const streamId = String($(this).data('streamid')); 273 if (streamId !== currentChannel) { 274 switchChannel(streamId); 275 } else if (audio.paused) { 276 audio.play(); 277 } else { 278 audio.pause(); 279 } 280 }); 281 282 // Az éppen szóló csatorna kártyája kiemelve, a gombja szünetre vált 283 function updateChannelCards() { 284 const playing = !audio.paused && !audio.error; 285 $('.channel-card').each(function () { 286 const active = playing && String($(this).data('streamid')) === currentChannel; 287 $(this).toggleClass('is-playing', active); 288 $(this).find('.channel-play i').toggleClass('fa-pause', active).toggleClass('fa-play', !active); 289 $(this).find('.channel-play span').text(active ? 'Szünet' : 'Hallgatom'); 290 }); 291 } 292 $(audio).on('play pause ended error', updateChannelCards); 293 294 // Mindegyik kártyán az adott csatornán éppen szóló dal 295 function updateChannelSongs() { 296 $('.channel-card').each(function () { 297 const card = $(this); 298 fetch(channelInfo[String(card.data('streamid'))].playlist) 299 .then(response => response.json()) 300 .then(data => { 301 const playlist = (data.mscp && Array.isArray(data.mscp.playlist)) ? data.mscp.playlist : []; 302 const song = playlist.find(item => 303 item.title && 304 item.title.trim() !== '' && 305 !/^sweeper/i.test(item.title) && 306 !/^superdjradio/i.test(item.title) 307 ); 308 const title = song ? fixEncoding(song.title) : 'Ismeretlen szám'; 309 const artist = song && song.artist ? fixEncoding(song.artist) : ''; 310 card.find('.channel-song-title').text(title); 311 card.find('.channel-song-artist').text(artist); 312 313 // BorÃtót csak akkor kérünk újra, ha a dal megváltozott 314 const songKey = title + '|' + artist; 315 if (card.data('song') === songKey) return; 316 card.data('song', songKey); 317 318 const cover = card.find('.channel-cover'); 319 // Ha a kapott kép nem tölthetÅ be, marad a rádió logója 320 cover.off('error').on('error', function () { 321 if (!this.src.endsWith(defaultCover)) this.src = defaultCover; 322 }); 323 $.getJSON(`https://ws.audioscrobbler.com/2.0/?method=track.getInfo&api_key=${apiKey}&artist=${encodeURIComponent(artist)}&track=${encodeURIComponent(title)}&format=json`, function (trackData) { 324 let albumCover = defaultCover; 325 if (trackData.track && trackData.track.album && trackData.track.album.image) { 326 const coverImage = trackData.track.album.image.find(img => img.size === 'large'); 327 if (coverImage && coverImage['#text']) { 328 albumCover = coverImage['#text']; 329 } 330 } 331 cover.attr('src', albumCover); 332 }).fail(function () { 333 cover.attr('src', defaultCover); 334 }); 335 }) 336 .catch(error => console.error('Error fetching channel song:', error)); 337 }); 338 } 339 setInterval(updateChannelSongs, 10000); 340 341 // A main.js hÃvja meg, amikor a kezdÅlap tartalma újra betöltÅdik 342 window.refreshChannelCards = function () { 343 updateChannelCards(); 344 updateChannelSongs(); 345 }; 346 347 // --- Induláskor az alapértelmezett csatorna info és playlist polling --- 348 startInfoPolling(currentChannel); 349 startPlaylistPolling(currentChannel); 350 window.refreshChannelCards(); 351});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.