Komple Yeniden Yazım icin Detayli Referans
player-core.js • 9.186 satir • ~420 KB
Bu dosya, Muzibu muzik platformunun kalbidir. Siteye girdiginizde sarki calma, durdurma, sonraki sarkiya gecme, ses ayarlama gibi TUM islemleri bu tek dosya yapiyor.
Dosya 9.186 satir uzunlugundadir ve icinde yaklasik 120+ fonksiyon vardir. Normalde boyle buyuk bir dosya 10-15 kucuk dosyaya bolunmelidir. Su an her sey tek dosyada toplandigi icin bakimi ve guncellemesi cok zordur.
Neden Onemli? Yeniden yazim (rewrite) yapilacaksa, bu dosyadaki her mekanizmanin ne yaptigini bilmek gerekir. Bu rapor, her fonksiyonu, her state degiskenini ve her event handler'i tek tek listeleyerek yeniden yazim icin tam bir referans saglar.
Tek bir Alpine.js component (muzibuApp()) icinde her sey tanimli. Modullerin spread ile aktarildigi monolitik yapi:
player-core.js (9.186 satir)
|
|-- Satirlar 1-36 : ensureHlsJs() - HLS.js lazy loader
|-- Satirlar 38-109 : Debug sistemi (pLog, pWarn, console uyari)
|-- Satirlar 111-163 : Cihaz algilama + _mzParam test helper
|-- Satirlar 165-261 : playerDebug(), safeAudioCleanup(), createHlsBlobUrl()
|-- Satirlar 263-315 : Blob URL takibi, XOR decrypt, decryptStreamData()
|-- Satirlar 317-455 : HLS key on-bellek: _hlsKeyCache, CachingKeyLoader
|-- Satirlar 457-678 : HlsPool yoneticisi (2 instance havuz)
|-- Satirlar 680-780 : serverLog() - sunucu tarafli hata loglama
|-- Satirlar 781-9179 : muzibuApp() - ANA COMPONENT
|-- 781-860 : Spread modules + config + auth state
|-- 860-940 : Player state degiskenleri (~60 adet)
|-- 940-1060 : getCoverUrl, updatePlayerColors, getActiveHlsAudio
|-- 1062-1190 : authenticatedFetch, LRU stream cache, _ensureHlsReady
|-- 1192-1310 : init() - baslangic fonksiyonu
|-- 1310-1515 : animateDurationCounter, loadFeaturedPlaylists, preloadLastPlayedSong
|-- 1519-1718 : togglePlayPause
|-- 1720-1823 : playRandomSongs, fallbackToPopularSongs
|-- 1825-2006 : saveQueueState, loadQueueState, loadInitialQueue
|-- 2008-2406 : loadEmergencyQueue, previousTrack, nextTrack, _safePlayFromQueue, _refillQueue
|-- 2408-2498 : toggleLike, toggleMute
|-- 2500-2976 : Crossfade: startCrossfade, createNextHowlerPlayer, createNextHlsPlayer
|-- 2978-3158 : completeCrossfade, seekTo
|-- 3160-3697 : Volume, onTrackEnded, Watchdog v3, Spot Player
|-- 3699-3844 : MediaSession, seekRelative, playContext
|-- 3846-4382 : playAlbum, playPlaylist, playGenre, playSector, playRadio, playSong
|-- 4384-5317 : playSongFromQueue (3 yol: preloaded/takeover/fresh)
|-- 5319-5604 : stopCurrentPlayback, playWithHowler
|-- 5606-6612 : playHlsStream (tum HLS mantigi)
|-- 6614-6858 : retryHlsWithNewUrl, triggerMp3Fallback, fadeAudioElement, progress tracking
|-- 6860-7311 : SPA navigasyon, sarki izleme (track-start/hit/end), kuyruk islemleri
|-- 7313-7816 : Auth (login/register/forgot), tema, drag-and-drop
|-- 7818-8340 : Preload sistemi (3 sarki + hover + next song HLS preload)
|-- 8340-8523 : Buffer saglik sistemi (devre disi)
|-- 8525-9179 : refreshHlsUrl, queue monitor, background playback, session terminated
| Modul | Dosya | Spread Yontemi |
|---|---|---|
muzibuFavorites | features/favorites.js | ...muzibuFavorites() |
muzibuAuth | features/auth.js (tahmini) | ...muzibuAuth() |
MuzibuApi | features/api.js | ...(window.MuzibuApi || {}) |
MuzibuSession | features/session.js | ...(window.MuzibuSession || {}) |
MuzibuSpaRouter | features/spa-router.js | ...(window.MuzibuSpaRouter || {}) |
debugFeature | features/performance-debug.js | ...(window.debugFeature || {}) |
safeStorage | core/safe-storage.js | Global erisim |
Hls | lib/hls.min.js (lazy) | Dinamik script ekleme |
Howl | Howler.js (global) | window.Howl |
MuzibuSpotPlayer | features/spot-player.js | window.MuzibuSpotPlayer |
MuzibuDeviceProfiler | features/device-profiler.js | window.MuzibuDeviceProfiler |
| Desen | Kullanim | Konum |
|---|---|---|
| Object Pool | HlsPool - 2 HLS.js instance havuzu | Satir 457-678 |
| LRU Cache | Stream URL cache (max 30, 5dk TTL) | Satir 1148-1176 |
| Lazy Loading | HLS.js script + pool ilk kullanimda yuklenir | Satir 14-36, 1178-1190 |
| Blacklist | Basarisiz sarkilar 5dk boyunca atlanir | Satir 7998-8026 |
| Concurrent Guard | nextTrack, queue refill, auth error icin tekil calisma | Satirlar 2100+ |
| Debounce | togglePlayPause, onTrackEnded, trackSongStart | Cesitli |
Alpine.js x-init ile cagrilan ana baslangic fonksiyonu. Sira:
_initialized flag kontrolu_hlsPoolReady = false, beforeunload'da destroyAllmuzibuApp() disinda, dosya yuklendiginde hemen calisan kodlar:
| _hlsJsLoaded | HLS.js global var kontrolu |
| _MZ_DBG | Debug modu (debug=1 param veya localhost) |
| Console uyari IIFE | DevTools acanlar icin korkutucu mesaj + fingerprint |
| _hlsKeyCache | HLS key on-bellek Map'i |
| HlsPool objesi | Pool singleton (ama init() henuz cagrilmaz) |
| activeBlobUrls | Blob URL takip Set'i (memory leak onleme) |
| Fonksiyon | Satir | Aciklama |
|---|---|---|
| playSong(song) | 4200+ | Tek sarki cal — context otomatik algilar, kuyrugun basina ekler |
| playAlbum(albumId) | 3846+ | Album sarkilarini yukle, kuyruga at, cal |
| playPlaylist(playlistId) | 3880+ | Playlist yukle, shuffle, min 15 sarki (genre'den tamamla) |
| playGenre(genreId) | 3960+ | Tur sarkilarini yukle ve cal |
| playSector(sectorId) | 4080+ | Sektor sarkilarini yukle ve cal |
| playRadio(radioId) | 4120+ | Radyo sarkilarini yukle, shuffle, cal |
| playFromQueue(index) | 7200+ | Kuyruktaki belirli index'i cal |
| togglePlayPause() | 1519 | Dur/devam toggle — premium/guest kontrol, debounce |
Kullanici tiklar
|
v
playSong() / playAlbum() / playPlaylist() / ...
|
v
Kuyruktaki index belirlenir
|
v
playSongFromQueue(index) ← ANA FONKSIYON (Satir 4384-5317, ~930 satir!)
|
+--[1] Preloaded Ready Path: _preloadedNext.ready === true
| HLS instance + audio element dogrudan devralinir (gapless)
|
+--[2] Preload Takeover Path: _preloadedNext var ama ready degil
| Preload'un HLS'ini bekle veya tamamla
|
+--[3] Fresh Load Path: Preload yok
|
v
Stream URL al (cache veya API)
|
v
decryptStreamData() — XOR + Base64 decode
|
+--> stream_type === 'hls' --> playHlsStream()
|
+--> stream_type === 'mp3' --> playWithHowler()
| Fonksiyon | Satir | Aciklama |
|---|---|---|
| playSongFromQueue(index, autoplay) | 4384 | Ana oynatma — 3 yol (preloaded/takeover/fresh), ~930 satir |
| playHlsStream(url, vol, autoplay, isRetry, startPos) | 5606 | HLS.js ile calma — 1000+ satir, Alpine proxy bypass |
| playWithHowler(url, vol, autoplay) | 5500+ | Howler.js ile MP3 calma |
| loadAndPlaySong(songId) | 5380+ | Stream URL al ve HLS/MP3'e yonlendir |
| stopCurrentPlayback() | 5319 | Her seyi durdur — HLS pool release, blob cleanup, Howler stop |
| togglePlayPause() | 1519 | Dur/devam — crossfade sirasinda ozel davranis |
| previousTrack() | 2070+ | Onceki sarki (3sn kuralı: basladaysa basa sar) |
| nextTrack(fromNaturalEnd) | 2120+ | Sonraki — concurrent guard, 10sn timeout, double-trigger guard |
| _safePlayFromQueue(index) | 2250+ | nextTrack icinden cagrilan guvenli oynatma, auth token yenileme |
| onTrackEnded(fromOnended) | 3248 | Sarki bitti — spot kontrolu, debounce, dogal son vs kullanici durma |
| seekTo(percent) | 3100+ | Pozisyon degistir — event/number destek, 3sn fallback timeout |
| seekRelative(seconds) | 3750+ | Goreceli atlama (+/-N saniye) |
| retryHlsWithNewUrl() | 6614 | HLS hatasi sonrasi yeni signed URL ile tekrar dene |
| triggerMp3Fallback() | 6650+ | HLS basarisiz → MP3'e gec |
| refreshHlsUrlForCurrentSong(applyToActive) | 8525 | Canli URL yenileme + HLS swap |
ensureHlsJs() (Satir 17-36): HLS.js kutuphanesi sayfa yuklendiginde degil, ilk ihtiyac aninda yuklenir.
/themes/muzibu/js/player/lib/hls.min.js2 adet HLS.js instance'i havuzda tutar. Her release() aslinda destroy + yeniden olustur yapar (MediaSource sifirlamasi icin).
| HlsPool.init(config) | Havuzu baslat — 2 instance olustur, _trackId takibi |
| HlsPool.acquire() | Havuzdan bir instance al — Alpine proxy bypass icin _trackId kullanir |
| HlsPool.release(instance) | Instance'i yok et ve havuza yenisini koy (tam sifirlama) |
| HlsPool.taint(instance) | Hata durumunda instance'i "kirli" isaretle |
| HlsPool.destroyAll() | Tum instance'lari yok et (beforeunload'da) |
| HlsPool.status() | Havuz durumu: toplam, kullanilan, hazir |
HLS sifreleme anahtarlarini bellekte onbellegeleyen loader. queueMicrotask() ile asenkron cache-serve yaparak "decryptdata unset" hatasini onler.
| _hlsKeyCache | Map<normalizedUrl, ArrayBuffer> — Global key cache |
| normalizeKeyUrl(url) | URL'deki expires/signature parametrelerini cikar → sabit key |
| constructKeyUrl(songId) | /hls-key/muzibu/songs/{id} formatinda URL olustur |
| prefetchHlsKey(songId) | Sarki calma oncesi anahtari bellege yukle |
| CachingKeyLoader.load() | Cache'de varsa queueMicrotask ile serve, yoksa XHR ile yukle + cache'e at |
Sarkı baslarken en yuksek kalite (level 3 = high) zorlanir, sonra ABR serbest birakilir:
BASLANGIC: hls.currentLevel = startLevel (genelde 3=high) hls.autoLevelCapping = startLevel SERBEST BIRAKMA (2 kosuldan hangisi once olursa): 1. FRAG_BUFFERED event'i → autoLevelCapping = -1 2. 5 saniye timeout → autoLevelCapping = -1 (currentLevel DEGISTIRILMEZ — pause yok!) SOFT MODE (hls_soft): autoLevelCapping = 2 (max mid, high filtrelenir)
Seviyeler: 0=ultralow(32k), 1=low(64k), 2=mid(128k), 3=high(orijinal)
~1000 satirlik dev fonksiyon. Onemli noktalar:
var _rawHls = HlsPool.acquire() — closure degiskeni, this.hls'e atanmaz (proxy cascade onleme)createHlsBlobUrl(url) ile gercek URL gizlenirMP3 fallback modu. HLS basarisiz oldugunda veya format mp3 ise kullanilir:
new Howl({ src: [url], html5: true, volume }) ile olusturuluronload (duration set), onplay (progress tracking baslat), onend (onTrackEnded), onerror (toast mesaji)howl.play(), false ise sadece yuklethis.isHlsStream = false olarak isaretlenirNot: Howler kullanimi giderek azaliyor, HLS ana yontem. MP3 sadece fallback.
Iki sarki arasi yumusak ses gecisi. Crossfade suresi config'den gelir (varsayilan 7000ms).
TETIKLEME:
startProgressTracking() veya timeupdate event'inde:
kalan_sure <= crossfadeDuration/1000 VE !isCrossfading
→ startCrossfade()
AKIS:
startCrossfade() (Satir 2510)
|
+--[Preload hazir] → Preload'un HLS + audio'sunu dogrudan kullan
| removeAllListeners() + sahiplik aktar
| nextAudio.volume = 0 → play() → fadeIn
|
+--[Preload yok] → Stream URL al → createNextHlsPlayer() veya createNextHowlerPlayer()
|
v
Eski player'i fade-out (rAF tabanli), yeni player'i fade-in
UI hemen guncellenir (yeni sarki bilgisi + progress bar)
|
v
completeCrossfade() (crossfadeDuration sonrasi)
Eski player yok edilir, yeni player this.hls/this.howl olur
activeHlsAudioId degistirilir
Progress tracking yeni player'a baglanir
| startCrossfade() | 2510 | Ana baslatici — guard'lar, preload reuse, fresh create, UI guncelleme |
| createNextHowlerPlayer(url, vol) | 2750+ | Howler ile sonraki sarki icin player olustur |
| createNextHlsPlayer(url, vol) | 2800+ | HLS ile sonraki — pool acquire, key prefetch, ABR lock |
| completeCrossfade() | 2978 | Gecis tamamla — eski yok et, yeni'yi ana yap, blob temizle |
| fadeAudioElement(el, from, to, dur) | 6720+ | requestAnimationFrame tabanli yumusak ses gecisi |
| crossfadeEnabled | true | Crossfade aktif mi |
| crossfadeDuration | 7000 | Gecis suresi (ms) — config'den |
| isCrossfading | false | Su an gecis yapiliyor mu |
| crossfadeTimeoutId | null | completeCrossfade timeout ID |
| crossfadeNextIndex | -1 | Gecis yapilan sonraki index |
| howlNext | null | Sonraki sarki Howler instance |
| hlsNext | null | Sonraki sarki HLS instance |
| nextHlsAudioId | - | Sonraki HLS audio element ID (runtime) |
| Fonksiyon | Satir | Aciklama |
|---|---|---|
| loadInitialQueue() | 1920+ | Sayfa acilisinda kuyruk yukle — 3 retry, exponential backoff |
| loadEmergencyQueue() | 2008 | Acil durum — populer → genre fallback |
| addToQueue(song) | 7180+ | Kuyruga sarki ekle (sonuna) |
| removeFromQueue(index) | 7200+ | Kuyruktan cikar (current index ayarla) |
| clearQueue() | 7220+ | Tum kuyrugu temizle |
| playFromQueue(index) | 7240+ | Belirli index'i cal |
| cleanQueue() | 7680+ | Kuyruktan duplicate'leri temizle |
| saveQueueState() | 1825 | localStorage'a kaydet — minimal 22 sarki (current +-10) |
| loadQueueState() | 1890+ | localStorage'dan geri yukle — sadece UI, stream istegi yok |
| startQueueMonitor() | 8576 | 10sn interval ile kuyruk kontrolu |
| checkAndRefillQueue() | 8596 | 3 sarkiya dustuyse otomatik doldur |
| _refillQueue() | 2300+ | Genre → Popular → Shuffle Repeat zinciri |
| _fetchUniqueGenreSongs() | 2380+ | Kuyrukta olmayan genre sarkilarini getir |
| getNextSongIndex() | 2502 | Sonraki sarki index'i (-1 = yok) |
| shuffleArray(array) | 4160+ | Fisher-Yates shuffle |
checkAndRefillQueue() — her 10sn
|
kalan sarki <= 3?
|
v
_refillQueue()
|
+--[1] Genre sarkisi al (currentSong.genre_id'den)
| API: /api/muzibu/songs/random?genre_id=X&limit=15
|
+--[2] Genre bos? → Popular al
| API: /api/muzibu/songs/random?sort=popular&limit=15
|
+--[3] Popular da bos? → Mevcut kuyrugu karistir ve tekrar cal
| (Shuffle Repeat — sonsuz calma)
|
v
Duplicate filtresi: kuyrukta zaten olan sarkilar eklenmez
Kuyruk icinde sarkilari surukleyerek yeniden siralama (Satir 7730-7816):
| draggedIndex | Suruklenen sarkinin index'i |
| dropTargetIndex | Birakilacak pozisyon |
| dragStart(index) | Sureklemeyi baslat |
| dragOver(e, index) | Pozisyon guncelle |
| drop(dropIndex) | Sarkiyi tasi — queueIndex'i ayarla |
| dragEnd() | Temizle |
| Hata | Tepki | Detay |
|---|---|---|
bufferStalledError | Sessiz | Loglama, baska islem yok |
fragLoadError (401/403) | URL Yenile | refreshHlsUrlForCurrentSong() → yeni signed URL |
fragLoadError (diger) | HLS Retry | hls.startLoad() ile tekrar dene |
keyLoadError | Key Cache Yenile | prefetchHlsKey + hls.startLoad() |
internalException | MP3 Fallback | Dogrudan triggerMp3Fallback() |
| Fatal + recoverable | Recover | hls.recoverMediaError() veya hls.swapAudioCodec() |
| Fatal + non-recoverable | MP3 Fallback | retryHlsWithNewUrl() → basarisizsa MP3 |
authenticatedFetch() (Satir 1062-1146) tum API cagrilarini sarar:
Her 10 saniyede bir kontrol. 3 anomali tespit eder:
_watchdogBusy flag ile race condition onlenir
| addToFailedSongs(songId) | Sarkiyi 5dk blacklist'e ekle |
| isFailedSong(songId) | Sarki blacklist'te mi kontrol (suresi dolmussa cikar) |
| clearFailedSongs() | Tum blacklist'i temizle |
activeBlobUrls (Set) ile olusturulan tum blob URL'leri izlenir ve URL.revokeObjectURL() ile serbest birakilir.
| createHlsBlobUrl(url) | URL'yi Blob'a cevir + activeBlobUrls'e ekle |
| revokeBlobUrl(url) | Blob URL'yi iptal et + Set'ten cikar |
| stopCurrentPlayback() | Tum blob URL'leri revoke eder |
| completeCrossfade() | Eski player'in blob URL'sini revoke eder |
| _cleanupPreloadedNext() | Preload blob URL'sini revoke eder |
addToStreamCache() (Satir 1148-1176): Max 30 entry, 5dk TTL. Stream URL'lerini bellekte tutar.
getCachedStream() URL'deki expires parametresini kontrol ederHlsPool.release() — her zaman destroy + yeniden olustur (MediaSource sifirlama)safeAudioCleanup(audio, removeFromDom) — src temizle, load(), opsiyonel DOM'dan cikarHlsPool.destroyAll()_cleanupPreloadedNext() — timeout iptal, blob revoke, pool release, DOM cikarpreloadedSongs Set'i 150'yi asarsa son 75'e kirpilir_failedSongs Map'i 5dk TTL ile otomatik temizlenirsaveQueueState() kuyruktan sadece 22 sarki kaydeder (current +-10)| isLoggedIn | boolean | Giris yapilmis mi (config'den) |
| currentUser | object|null | Kullanici bilgileri |
| todayPlayedCount | number | Bugun dinlenen sarki sayisi |
| showAuthModal | null|string | Auth modal tipi (login/register/forgot) |
| showQueue | boolean | Kuyruk paneli acik mi |
| showLyrics | boolean | Sarki sozleri paneli |
| showMobileMenu | boolean | Mobil 3-nokta menu |
| progressPercent | number | Progress bar yuzde (0-100) |
| authLoading | boolean | Auth islemi devam ediyor |
| authError | string | Auth hata mesaji |
| authSuccess | string | Auth basari mesaji |
| isLoading | boolean | Sayfa yukleniyor (SPA) |
| isSongLoading | boolean | Sarki yukleniyor spinner |
| isSeeking | boolean | Seek sirasinda buffer bekleniyor |
| contentLoaded | boolean | Icerik hazir |
| searchQuery | string | Arama sorgusu |
| searchResults | array | Arama sonuclari |
| searchOpen | boolean | Arama paneli acik mi |
| isPlaying | boolean | Caliniyor mu |
| isBuffering | boolean | Buffer yetersiz, bekleniyor |
| isToggling | boolean | togglePlayPause debounce flag |
| currentTime | number | Suanki pozisyon (saniye) |
| duration | number | Sarki suresi (saniye) |
| animatedDuration | number | Animasyonlu sure (counter) |
| volume | number | Ses (0-100), localStorage'dan |
| isMuted | boolean | Sessiz mi |
| currentSong | object|null | Su an calan sarki |
| currentContext | object|null | Calma konteksti (playlist/album/genre) |
| currentFallbackUrl | string|null | MP3 fallback URL (signed) |
| queue | array | Sarki kuyrugu |
| queueIndex | number | Suanki index |
| isDarkMode | boolean | Karanlik tema (varsayilan: true) |
| currentPath | string | Suanki URL path (SPA) |
| _initialized | boolean | Double-init guard |
| isLoggingOut | boolean | Cikis yapiliyor |
| favorites | array | Favori sarki listesi |
| howl | Howl|null | Suanki Howler instance |
| hls | Hls|null | Suanki HLS.js instance |
| isHlsStream | boolean | HLS mi MP3 mi |
| lastFallbackReason | string|null | MP3'e gecis nedeni (debug) |
| hlsCurrentLevel | number | Suanki HLS kalite (0-3, -1=auto) |
| hlsLevelCount | number | Toplam HLS kalite sayisi |
| isSlowConnection | boolean | Yavas baglanti uyarisi |
| activeHlsAudioId | string | 'hlsAudio' veya 'hlsAudioNext' |
| crossfadeEnabled | true | |
| crossfadeDuration | 7000 | |
| isCrossfading | false | |
| crossfadeTimeoutId | null | |
| crossfadeNextIndex | -1 | |
| howlNext | null | |
| hlsNext | null |
| currentPlayId | number|null | API'den donen dinleme kaydi ID |
| playbackStartTime | number|null | Sarki baslama zamani (Date.now()) |
| totalListenedMs | number | Toplam dinlenen sure (ms) |
| playCountTimerId | number|null | 30sn hit timer ID |
| hitTracked | boolean | Hit kaydedildi mi |
| playTracked | boolean | Play kaydedildi mi |
| _preloadedNext | object|null | {songId, hls, audioId, ready, blobUrl, ...} |
| _preloadNextInProgress | boolean | Preload devam ediyor mu |
| _lastNextTrackTime | number|null | Double-trigger guard |
| _nextTrackInProgress | boolean | Concurrent nextTrack guard |
| _bufferHealthEnabled | false | Buffer monitor devre disi |
| _minBufferBeforePlay | 8 | Referans (kullanilmiyor) |
| _lowBufferThreshold | 3 | Referans (kullanilmiyor) |
| _resumeBufferThreshold | 8 | Referans (kullanilmiyor) |
| _bufferPausedByHealth | false | Buffer pause flag |
| _bufferCheckInterval | null | Buffer monitor interval ID |
Login, register, forgot password formlari + telefon ulke secimi + real-time blur validation state'leri. Satir 810-860.
| get currentStreamType() | Satir 941-944 | 'hls' | 'mp3' | null |
Not: Sadece 1 computed property var. Geri kalan her sey fonksiyon veya duz degisken.
| Event | Ne Zaman | Detail |
|---|---|---|
player:crossfadeStart | Crossfade baslarken | {fromSong, toSong, duration} |
player:crossfadeComplete | Crossfade tamamlandiginda | {songId} |
player:stop | Sarki dogal olarak bittiginde | - |
player:songChanged | Yeni sarki basladiginda | {song, index} |
player:play | Calma basladiginda | {song} |
player:pause | Duraklatildiginda | - |
player:hlsLevelChanged | HLS kalite degistiginde | {level, bitrate} |
| Event | Hedef | Aciklama |
|---|---|---|
beforeunload | window | HlsPool.destroyAll(), trackSongEndBeacon() |
visibilitychange | document | Background playback: buffer recovery, keep-alive ping |
online | window | Kafe Mod: internet dondu → tam kurtarma dizisi |
offline | window | Kafe Mod: internet gitti → _networkOffline = true |
popstate | window | SPA: geri/ileri buton → loadPage() |
timeupdate | audio element | Crossfade tetikleme, progress guncelleme (HLS) |
ended | audio element | onTrackEnded(true) — dogal son |
pause | audio element | 3 katmanli auto-resume (beklenmeyen pause) |
| Event | Aciklama |
|---|---|
MANIFEST_PARSED | Playlist yuklendi → startLoad, ABR lock |
FRAG_BUFFERED | Ilk fragment yuk → ABR unlock |
LEVEL_LOADED | Seviye yuklendi → duration fix |
LEVEL_SWITCHING | Kalite degisiyor → UI guncelle, isSlowConnection |
ERROR | Hata yonetimi — Bolum 8'de detayli |
| Izlenen | Aksyon |
|---|---|
duration | animateDurationCounter() — easeOutCubic animasyon |
queue | saveQueueState() (setupAutoSave icinde) |
queueIndex | saveQueueState() |
currentSong | saveQueueState() |
isPlaying | saveQueueState() |
volume | Howl/HLS volume guncelle + localStorage kaydet |
1. Monolitik Dosya (9.186 satir)
Tek dosyada ~120 fonksiyon. Bakim, test ve hata ayiklama cok zor. playSongFromQueue tek basina ~930 satir.
Oneri: 8-10 module bol (playback-engine, queue-manager, hls-manager, crossfade, preload, tracking, auth, ui-state)
2. Alpine.js Spread Pattern Sinirlamasi
Tum moduller ...spread ile tek objeye karistirilir. Isim cakismasi riski yuksek, encapsulation yok.
Oneri: Alpine.store() veya EventBus ile moduller arasi iletisim
3. Alpine Proxy Bypass Zorunlulugu
HLS.js instance'lari Alpine proxy'den kacinmak icin var _rawHls closure kullanmak zorunda. Bu pattern her HLS erisiminde tekrarlanir.
Oneri: HLS manager'i Alpine disinda tutarak proxy sorununu kokunden coz
4. Volume Kodu Tekrari
updateVolume() ve setVolume() neredeyse ayni kodu tekrarlar (~80 satir). Spot audio volume da ayri yonetilir.
Oneri: Tek bir volume manager olustur, tum audio kaynaklarini merkezi yonet
5. Coklu Guard/Debounce Mekanizmalari
_nextTrackInProgress, _lastNextTrackTime, isToggling, _watchdogBusy, _handlingAuthError, _lastTrackEndedTime... Ayri ayri flag'ler, merkezi bir guard sistemi yok.
Oneri: Merkezi bir state machine veya mutex pattern
6. playSongFromQueue() Karmasikligi
~930 satir, 3 ayri yol (preloaded/takeover/fresh). Her yolda benzer ama farkli duration/color/event handler setup'i var.
Oneri: Strategy pattern — her yol ayri sinif, ortak arayuz
7. playHlsStream() Boyutu
~1000 satir tek fonksiyon. HLS init, event handler'lar, hata yonetimi, Safari path — hepsi ic ice.
Oneri: HLS lifecycle manager sinifi cikart
8. Auth Logiginin Player Icinde Olmasi
Login, register, forgot password, validation — tumu player-core icinde (~500 satir). Player ile ilgisi yok.
Oneri: Auth tamamen ayri module/component'e tasi
9. SPA Router Player Icinde
navigateTo(), loadPage() fonksiyonlari player ile ilgisiz ama player icinde yasiyorlar.
Oneri: SPA router ayri module (kismi yapilmis: MuzibuSpaRouter spread)
10. Buffer Health Sistemi Devre Disi
_bufferHealthEnabled = false. ~150 satir kod hicbir zaman calismaz.
Oneri: Ya aktive et ya da kaldir (dead code)
player/
├── core/
│ ├── PlayerEngine.js ← State machine (playing/paused/loading/error)
│ ├── AudioManager.js ← HLS + Howler soyutlama katmani
│ └── VolumeController.js ← Tek merkezi ses yonetimi
│
├── hls/
│ ├── HlsPool.js ← Instance havuzu (mevcut, iyi)
│ ├── HlsLoader.js ← Lazy loader + CachingKeyLoader
│ └── HlsErrorHandler.js ← Tum HLS hata mantigi
│
├── queue/
│ ├── QueueManager.js ← Kuyruk CRUD + auto-refill
│ ├── QueuePersistence.js ← localStorage save/load
│ └── QueueMonitor.js ← 10sn interval kontrolu
│
├── playback/
│ ├── PlaybackRouter.js ← playSong/Album/Playlist/Genre/...
│ ├── PreloadManager.js ← Next song preload + URL cache
│ └── CrossfadeEngine.js ← Crossfade tamami
│
├── tracking/
│ ├── PlayTracker.js ← track-start/hit/end
│ └── WatchdogTimer.js ← v3 watchdog
│
├── network/
│ ├── AuthenticatedFetch.js ← 401/419 yonetimi
│ ├── StreamCache.js ← LRU cache + failed songs
│ └── BackgroundPlayback.js ← visibility/online/offline
│
├── ui/
│ ├── MediaSession.js ← Lock screen kontrolleri
│ ├── ProgressTracker.js ← Progress bar guncelleme
│ └── PlayerColors.js ← Gradient renk hesaplama
│
└── auth/ ← Player DISINA tasi!
├── LoginHandler.js
├── RegisterHandler.js
└── SessionManager.js
25 Subat 2026 • Muzibu.com.tr