Co je nového
2.0.9 - 2026-08-23
Oznámení o aktualizaci otevírá své stránky ve vašem jazyce
Co: Odkazy Co je nového a Stáhnout v oznámení o aktualizaci nyní otevírají stránky pluginu v jazyce samotného MusicBee, nikoli v angličtině.
Proč: Tyto dva odkazy zúžily jazyk na jeden ze čtyř – angličtinu, francouzštinu, španělštinu nebo němčinu – před odesláním na web, takže všichni ostatní dostali anglickou stránku, i když existoval její překlad. Nyní předávají jazyk MusicBee beze změny a nechávají webovou stránku rozhodnout, co má zobrazit, což je to, co tlačítko Nápověda vedle nich vždy dělalo.
2.0.8 - 2026-08-22
Plugin se nyní správně představuje aplikacím a zařízením, která jej objeví ve vaší síti, a nastavení profilů zařízení se opět srovnala.
Vaše zařízení zobrazují správného výrobce, model a verzi
Co: když ovládací aplikace, telefon nebo televize najde MusicBee ve vaší síti, tento plugin se nyní prezentuje jako vytvořený společností yaiol, odkazuje na vlastní stránky pluginu, popisuje se jako pokrývající všechny tři role – server, přehrávač a renderer – a hlásí verzi, kterou máte skutečně nainstalovanou.
Proč: každé zařízení UPnP oznamuje, kdo ho vyrobil a co to je, a ovládací aplikace to zobrazují jako identitu zařízení. Tento plugin stále oznamoval podrobnosti původního pluginu, ze kterého byl odvozen: jméno jiného autora, webové stránky MusicBee místo vlastních a číslo modelu zamrzlé na "1.0" od prvního vydání. Z vašeho telefonu nebylo možné zjistit, se kterým pluginem mluvíte, natož jakou jeho verzi. Tyto podrobnosti nyní pocházejí ze samotného pluginu, takže verze zobrazená vedle zařízení zůstává správná s každou aktualizací.
Nastavení profilů zařízení se opět srovnala
Co: na kartě Device Profiles (Profily zařízení) mají popisky a jejich pole jeden levý okraj a jsou rovnoměrně rozmístěny, a rozsah vzorkovací frekvence se čte jako jeden řádek.
Proč: pole se postupem času rozcházela, jak byly na kartu přidávány možnosti, a popisek "to" rozsahu vzorkovací frekvence skončil sedět na poli vedle něj – čitelné, jakmile jste věděli, co říká, matoucí, když jste se podívali poprvé.
2.0.7 - 2026-08-08
Větší stopy si zachovávají svůj název a posuvník pozice
Co: větší stopa odeslaná z telefonu – dlouhý soubor FLAC, soubor s vysokým rozlišením nebo DSD – nyní zobrazuje svůj správný název a lze ji posouvat, stejně jako malou. Dříve se některé z nich přehrávaly místo toho přes síť, s webovou adresou místo názvu a posuvníkem, který nic nedělal.
Proč: plugin čeká na svou lokální kopii před spuštěním, ale dříve se předem rozhodoval, zda se na soubor vyplatí čekat, na základě jeho velikosti. To byl ve skutečnosti odhad rychlosti vaší sítě, kterou nemá jak zjistit: 65 MB stopa byla posouzena jako příliš velká, poté se stáhla o sekundu později – pohodlně v rámci čekání, kterého se již vzdala. Nyní jednoduše sleduje stahování. Dokud stále přichází, plugin čeká, jakkoli dlouho to trvá; vzdá se pouze tehdy, když se přenos skutečně zastaví, což si nyní všimne rychleji než staré pevné zpoždění.
2.0.6 - 2026-08-03
Alba odeslaná z telefonu se nyní přehrávají bez mezer mezi skladbami a internetové rádio je rozpoznáno jako rádio namísto toho, aby bylo považováno za neobvykle dlouhou píseň.
Alba se přehrávají bez mezer
Co: když odešlete celé album z telefonu, MusicBee nyní přechází z jedné skladby na druhou bez pauzy – takže živé nahrávky, DJ sety a souvislá klasická díla drží pohromadě.
Proč: standard umožňuje ovládací aplikaci říci "zde je to, co následuje", což umožňuje plynulé spojení. Tato instrukce nebyla vůbec přijata, takže aplikace neměla kam umístit nadcházející skladbu a oznámila ji, jako by to byla ta aktuální – příčina problému s albem opraveného v předchozí verzi. Nyní je přijata správně: další skladba je načtena, zatímco aktuální stále hraje, a vlastní přehrávač MusicBee překračuje hranici.
Internetové rádio je rozpoznáno jako rádio
Co: živá stanice odeslaná do MusicBee se přehrává jako stream a nikdy se nestahuje.
Proč: stahování vysílání nedává smysl – nemá konec a není nic, čím by se dalo procházet – ale plugin dříve neměl způsob, jak jej odlišit od hudebního souboru, takže začal stahovat a zastavil se, jakmile stahování překročilo pevnou velikost. Ovládací aplikace uvádí, který z těchto dvou typů odesílá, a to je nyní přímo čteno. Žádné nastavení, žádné hádání.
Dlouhé skladby ve vysokém rozlišení si zachovávají svou kopii
Co: soubory DSD a dlouhé 24bitové nahrávky lze nyní procházet jako jakékoli jiné skladby.
Proč: byly zachyceny výše uvedeným limitem velikosti – 20minutová pasáž ve vysokém rozlišení nebo 10minutová skladba DSD obě tento limit překročily – takže jejich kopie byla opuštěna a posuvník pozice přestal fungovat přesně pro materiál, který s největší pravděpodobností stojí za prohledávání. S řádně identifikovaným rádiem není potřeba žádný limit velikosti.
2.0.5 - 2026-08-03
Dvě opravy pro ovládání MusicBee z telefonu: hlasitost nyní znamená totéž na obou koncích a přehrávání celého alba funguje i po první skladbě.
Hlasitost na vašem telefonu odpovídá hlasitosti v MusicBee
Co: nastavení hlasitosti na maximum na vašem telefonu nyní dosáhne maxima v MusicBee a vlastní nastavení MusicBee se správně zobrazí zpět na telefonu.
Proč: plugin nikdy neřekl ovládací aplikaci, jaká je jeho nejvyšší hlasitost, takže každá aplikace musela hádat. Jedna z nich se ustálila na 69, což znamenalo, že jejích 100 % dosáhlo v MusicBee pouze 69 %, zatímco 100 % MusicBee se vrátilo jako 144 % na telefonu – a tlačítka hlasitosti telefonu nikdy nemohla dosáhnout úplného maxima. Renderer nyní jasně uvádí rozsah, takže oba konce mluví o stejné stupnici.
Přehrávání alba zachovává své názvy a posuvník pozice
Co: každá skladba alba odeslaná z telefonu nyní zobrazuje svůj správný název a lze ji posouvat, nejen ta první.
Proč: ovládací aplikace oznamuje další skladbu zlomek sekundy po aktuální a toto oznámení rušilo kopii, která se načítala pro skladbu, která se měla přehrát – takže většina skladeb tiše přešla na přehrávání přes síť, což ztrácí jak název, tak možnost přeskakovat. Kopie pro několik skladeb jsou nyní uchovávány vedle sebe, takže oznámení již nemůže zrušit tu, která se používá.
2.0.4 - 2026-08-02
Hudba odeslaná do MusicBee z telefonu nebo jiného serveru se nyní chová jako skutečná skladba: můžete se v ní pohybovat a okamžitě zobrazuje svůj správný název. Navíc oprava pro hi-fi streamery, které se prezentují jako jedno kombinované zařízení.
Pohyb ve skladbě odeslané odjinud
Co: přetahování posuvníku pozice nyní funguje pro skladbu odeslanou z vašeho telefonu, NAS nebo jiného mediálního serveru. Aby to bylo možné, MusicBee stáhne kopii skladby do dočasné složky, zatímco se začne přehrávat, a přehrává tuto kopii. Na domácí síti to trvá asi sekundu, kopie je smazána, jakmile odešlete další skladbu, a veškeré zbytky jsou vymazány při dalším spuštění MusicBee.
Proč: MusicBee může spustit a zastavit něco, co poslouchá přes síť, ale nemůže se v tom pohybovat – takže posuvník se zdánlivě posunul a pak se okamžitě vrátil tam, kde byl, bez vysvětlení. Přehrávání obyčejného souboru na vlastním disku zcela odstraňuje omezení, namísto jeho obcházení.
Správný název a délka od první noty
Co: skladba odeslaná aplikací, která svým souborům nedává obyčejnou příponu souboru, nyní zobrazuje svůj skutečný název a délku, jakmile se spustí, namísto toho, aby se zobrazovala jako dlouhá webová adresa.
Proč: MusicBee identifikuje skladbu – a najde její tagy – z přípony souboru, a někteří přehrávače rozdávají adresy bez jakékoli přípony. Místní kopie vždy nese tu správnou, takže skladba je rozpoznána bez ohledu na to, jak ji odesílající aplikace nazývá.
Skok, který nelze provést, je nyní oznámen
Co: pokud renderer skutečně nemůže přejít na požadovaný bod, je o tom informována řídící aplikace a nahlásí to.
Proč: dříve odpověděl „hotovo“ bez ohledu na to, takže posuvník se o sekundu později posunul zpět, aniž by cokoli vysvětlilo proč. Upřímné odmítnutí je snazší řešit než tiché.
Kombinované hi-fi streamery jsou čteny správně
Co: když MusicBee přehrává do zařízení, které se prezentuje jako jedna kombinovaná jednotka – streamer Marantz nebo Denon, kde přehrávač sedí uvnitř obalu výrobce vedle mediálního serveru – plugin nyní čte vlastní detaily přehrávače namísto mediálního serveru.
Proč: dříve se ptal špatné poloviny zařízení, jaké zvukové formáty dokáže zpracovat, nedostával žádnou použitelnou odpověď a pokračoval bez kontroly – přesně hardware, kde je zpracování formátů nejdůležitější. Popis modelu zařízení je nyní také brán v úvahu při jeho přiřazování k profilu zařízení; byl čten ze špatného místa a zahozen.
2.0.3 - 2026-08-02
Role přehrávání se rozšiřuje: MusicBee nyní dokáže přehrávat hudbu, která ještě není v jeho knihovně – soubor v telefonu, na NASu, na jiném serveru – namísto pouze skladeb, které již vlastní.
Přehrávejte hudbu odeslanou z telefonu, nejen z vlastní knihovny
Co: když používáte ovládací aplikaci, jako je Symfonium nebo BubbleUPnP, k odesílání hudby do MusicBee, skladba již nemusí pocházet z vlastní knihovny MusicBee. Nyní se přehraje soubor uložený v samotném telefonu, na NASu nebo na jiném mediálním serveru. Název a délka pocházejí z aplikace, která ji odeslala, takže se skladba zobrazí správně, i když MusicBee soubor nikdy neviděl.
Proč: role přehrávání byla vytvořena pro případ, kdy si z telefonu prohlížíte knihovnu tohoto PC a klepnete na skladbu – skladba již byla na PC, takže MusicBee jednoduše přehrál svůj vlastní soubor. Cokoli, co přišlo odjinud, bylo tiše zahozeno, což činilo funkci nepoužitelnou pro stejně přirozený případ odesílání hudby z telefonu na dobré reproduktory.
Skladba, kterou nelze přehrát, to oznámí
Co: pokud přehrávač skutečně nemůže přehrát to, co mu bylo odesláno, nyní to nahlásí zpět aplikaci, která to odeslala.
Proč: dříve na cokoli odpověděl „mám to“, takže ovládací aplikace pokračovala a stiskla přehrát. Jelikož se nic nenačetlo, MusicBee restartoval jakoukoli skladbu, která zbyla z dřívějška – a pokud soubor zmizel, stěžoval si, že jeho zdroj nelze najít. Chyba pojmenovala nesouvisející skladbu a neukazovala nikde blízko skutečného problému.
Odeslání nové skladby během pauzy nyní přehraje tuto skladbu
Co: pokud je MusicBee pozastaven a vaše ovládací aplikace mu pošle něco nového, nová skladba se spustí.
Proč: obnovení mělo přednost před načítáním, takže pozastavená skladba pokračovala tam, kde skončila, a skladba, kterou jste právě vybrali, byla bez jediného slova zrušena.
2.0.2 - 2026-08-01
Tématem je vyhledávání: nyní funguje podle interpreta, vrací správné výsledky a je rychlé i ve velké knihovně. Navíc nový způsob, jak zaměřit náhodné přehrávání vaší ovládací aplikace, a oprava tří tlačítek, která nikam nevedla.
Vyhledávání podle interpreta skutečně funguje
Co: vyhledávání interpreta z vaší ovládací aplikace nyní vrací hudbu tohoto interpreta. Vyhledávání odpovídá jak Artist skladby, tak Album Artist alba, takže kompilace je nalezena, ať už zadáte jméno interpreta nebo jméno, pod kterým je album zařazeno.
Proč: vyhledávání interpreta bylo dříve mylně považováno za „dej mi všechno tohoto druhu“ – zadaný interpret byl ignorován a vrátila se celá knihovna, takže vyhledávání, které mělo odpovídat několika stovkám skladeb, vrátilo desítky tisíc. Shoda pouze jednoho ze dvou polí interpreta by tiše ztratila polovinu výsledků, takže jsou kontrolována obě.
Stránka s výsledky vyhledávání se správně stránkuje
Co: posouvání dlouhým seznamem výsledků vyhledávání se nyní pohybuje skrz něj. Každá stránka, na kterou se posunete, je stránka, kterou dostanete.
Proč: server dříve odpovídal na každý požadavek první hrstkou výsledků, zatímco hlásil plný počet shod, takže aplikace, která se posouvala pro více, stále dostávala stejné položky a nikdy nedosáhla konce.
Vyhledávání je mnohem rychlejší ve velké knihovně
Co: vyhledávání nyní provede jediný dotaz pro celou sadu výsledků a přečte pouze značky stránky, na kterou se díváte.
Proč: každá stránka dříve znovu spouštěla dotaz proti knihovně a poté načítala značky každé shody – tisíce z nich – aby zobrazila tucet. Na velké sbírce to způsobilo, že každé posouvání se pozastavilo. Výsledky jsou také zahozeny, kdykoli je knihovna obnovena, takže úprava není nikdy zastaralá.
Zaměřte své náhodné přehrávání na filtr
Co: nové nastavení Náhodné přehrávání z na kartě Library Options. Ponechte jej na Veškerá hudba a složky Náhodné skladby / Náhodná alba vaší ovládací aplikace se budou chovat jako dříve; vyberte jeden z vašich filtrů MusicBee a každý náhodný požadavek bude čerpat z tohoto filtru. Nabízeny jsou i skryté filtry.
Proč: složka pro náhodné přehrávání žádá o výřez „všeho“ a je to jediný požadavek, který nenese žádnou stopu o tom, co jste mysleli – takže vždy čerpal z celé knihovny, mluveného slova a všeho. Zde řeknete, co „všechno“ znamená. Otevření složky pro náhodné přehrávání uvnitř filtru na zařízení stále náhodně přehrává tento filtr: volba, kterou provedete při procházení, má přednost před nastavením.
Nápověda, GitHub a kontrola aktualizací vedou na skutečné stránky
Co: tlačítka Nápověda a GitHub v dialogovém okně nastavení a automatická kontrola nové verze nyní otevírají stránky, které pojmenovávají.
Proč: všechny tři byly vytvořeny ze zkrácené formy názvu pluginu, na které nikdy neexistovala žádná stránka, takže každá tiše selhala – tlačítka se zdála nic nedělat a kontrola aktualizací nikdy nic nehlásila, bez ohledu na to, jak dlouho byla nová verze venku.
2.0.1 - 2026-07-26
Kolo oprav přehrávání a procházení, zaměřené na podcasty a na ovládací aplikace (jako je BubbleUPnP), které řídí přehrávání a náhodné přehrávání.
Podcasty se začnou přehrávat bez pauzy
Co: stažená epizoda podcastu nyní uvádí svou skutečnou délku a velikost souboru hned na začátku, přenesené přímo ze souboru na disku do metadat média.
Proč: bez uvedené délky ovladač jako BubbleUPnP znovu skenuje celý zvukový proud pokaždé, když stisknete přehrát, jen aby zjistil, jak dlouhá je epizoda – takže přehrávání začalo až po znatelné pauze. S nyní inzerovanou délkou začíná čistě.
Podcasty se zobrazují při procházení podle interpreta
Co: název pořadu podcastu je nyní zařazen jako jeho interpret – zrcadlen do polí Interpret a Interpret alba (a jejich variant řazení), přesně tak, jak již vyplňuje pole Album.
Proč: cesta procházení, která seskupuje podle pole interpreta, dříve nacházela interpreta každého podcastu prázdného a končila na prázdné úrovni. Zacházení se samotným pořadem jako s interpretem – v souladu s tím, že se s ním zachází jako s albem – znamená, že tyto cesty nyní dosáhnou epizod namísto ničeho.
„Nedávno přehrávané“ a streamování fungují hned po restartu
Co: přehrávání podcastu, audioknihy, doručené pošty nebo rozhlasové stopy přímo – bez předchozího procházení k ní, jak to dělají seznam „Nedávno přehrávané“ a cíle streamování BubbleUPnP – již neselhává. Plugin nyní načte stopu na vyžádání, když je o ni požádáno podle ID.
Proč: tyto seznamy požadují stopu hned po restartu MusicBee, než bylo cokoli procházeno, takže plugin nikdy neviděl ID a odpověděl „Špatné ID“. Nyní vynuceně načte relevantní zdroje na tento první přímý požadavek a najde stopu.
„Náhodné stopy“ a „Náhodná alba“ vracejí výsledky
Co: složky „Náhodné stopy“ a „Náhodná alba“ BubbleUPnP, které požadují náhodný výřez celé knihovny, se nyní vracejí vyplněné.
Proč: jedná se o vyhledávání bez názvu k porovnání a plugin na ně dříve odpovídal z prázdného interního seznamu, takže vždy ukazovaly nic. Nyní jsou obsluhovány – správně stránkované – ze stejné cesty dotazu na vyžádání, kterou používá zbytek procházení.
Alba s prázdným tagem uvádějí své stopy
Co: otevření alba, které bylo seskupeno na prázdné hodnotě – například stopy doručené pošty, které nemají rok – nyní zobrazuje jeho stopy.
Proč: shoda, která shromažďuje stopy alba, považovala „tento tag je prázdný“ za „žádná shoda“, takže jakékoli album vytvořené z prázdného pole neprocházelo k ničemu. Prázdná hodnota skupiny nyní správně odpovídá stopám, které ji sdílejí.
2.0.0 - 2026-07-22
Toto je první veřejné vydání open-source forku yaiol pluginu MusicBee UPnP. Je prezentováno ve dvou částech: vše, co je v tomto forku nové, a poté opravy a vylepšení provedené v původním pluginu. Každá položka zachovává formu Co / Proč z interního katalogu funkcí projektu, takže zdůvodnění každé změny je uvedeno přímo, nikoli jen samotná změna.
Novinky v tomto forku
MediaRenderer – přehrávání do MusicBee
N01 – MusicBee jako renderer pro přehrávání
Co: obvykle tento plugin funguje jednosměrně: telefon nebo jiné zařízení prochází knihovnu MusicBee a přehrává hudbu na sobě. Tato funkce přidává opačný směr – umožňuje MusicBee být přehrávačem. Z aplikace ovladače v telefonu (například BubbleUPnP) si můžete vybrat svůj desktopový MusicBee jako zařízení, které přehrává, a poté jej ovládat z ruky: přehrávat, pozastavit, zastavit, přeskočit vpřed nebo vzad, skočit na určitý bod ve skladbě a změnit hlasitost nebo ztlumit.
Proč: promění váš telefon v dálkové ovládání pro hudbu, která je již ve vašem počítači. Sedněte si na gauč, procházejte svou knihovnu v telefonu, klepněte na skladbu a ta se ozve z reproduktorů připojených k vašemu počítači – s plnou kontrolou z místa, kde sedíte. Původní plugin tuto funkci nikdy nedodal jako funkční.
Zapnutí: je ve výchozím nastavení vypnuto, protože jeho zapnutí umožňuje čemukoli ve vaší domácí síti spustit přehrávání na vašem počítači. Povolíte jej zaškrtnutím políčka na kartě Obecné v dialogovém okně nastavení. Každá ze tří rolí pluginu má tam své vlastní zaškrtávací políčko – sdílet mou knihovnu (Server), nechat ostatní přehrávat do mě (Renderer) a přehrávat do jiných zařízení (Control Point) – a dialogové okno zobrazuje pouze karty nastavení, které role, které jste zapnuli, skutečně potřebují, takže se nikdy nesetkáte s možnostmi, které se vás netýkají.
Rozlišení vašich strojů: rendereru můžete dát libovolné jméno (začíná jako „MusicBee (yaiol)“). Toto jméno se zobrazí v seznamu cílů přehrávání vašeho telefonu, takže když běží více než jeden počítač s MusicBee, můžete rozlišit, který je který. Změna názvu se projeví okamžitě, bez restartu.
Nejlepší možný zvuk při přehrávání do sebe: když procházíte vlastní knihovnu MusicBee z telefonu a pošlete skladbu zpět do stejného MusicBee, plugin rozpozná, že je požádán o přehrání jednoho z jeho vlastních souborů a jednoduše jej přehraje přímo z vašeho disku. Výsledek je přesný a okamžitý – bit-perfect, s aplikovaným vlastním ekvalizérem a vyrovnáváním hlasitosti MusicBee – namísto zbytečného posílání zvuku do sítě a přímo zpět k sobě.
Provozování soukromě: tři role fungují nezávisle, takže můžete zapnout renderer a zároveň nechat sdílení knihovny vypnuté. V tomto nastavení „pouze renderer“ zůstane vaše knihovna zcela skrytá před sítí – oznámen je pouze cíl přehrávání – a MusicBee nikdy nenabídne přehrávání do sebe.
Chování přehrávání
N02 – 5.1 FLAC není automaticky downmixován
Co: omezení počtu kanálů v MediaServerDevice.GetEncodedFile bylo If StereoOnly OrElse Not isPcmData Then channelCount = 2. Klauzule Not isPcmData tiše downmixovala každý non-PCM transkód (FLAC, MP3, AAC, Ogg) na stereo bez ohledu na počet kanálů zdroje, což znemožňovalo 5.1-schopným rendererům, když byl zdrojem 5.1 FLAC. Nyní druhá klauzule vylučuje FLAC: Not isPcmData AndAlso encoder.Codec <> FileCodec.Flac. FLAC 5.1 prochází; MP3/AAC/Ogg stále vynucují stereo, protože příkazové řádkové kodéry MusicBee pro tyto formáty očekávají 2-kanálový vstup.
Proč: celým smyslem transkódování 5.1 FLAC zdroje na FLAC výstup je zachování vícekanálového mixu. Tichý downmix činil možnost transkódování FLAC pro prostorový poslech zbytečnou. S N02 dělá správnou věc.
Architektura
Strukturální změna, která činí fork životaschopným na velké knihovně – chybí v původním pluginu.
N03 – Líný (na vyžádání) strom procházení
Co: původní plugin sestavil celý strom procházení při spuštění MusicBee – enumeroval každou skladbu, plný Library_GetFileTags pro každý soubor, sestavil celou hierarchii kontejnerů – před otevřením HTTP portu. Na skutečné knihovně (50k+ skladeb, 5400 epizod podcastů, stovky stanic) to jsou minuty studeného startu a strom zůstává v RAM navždy, včetně větví, které žádný klient nikdy neotevře. Tento fork nic předem nestaví: kořen vystavuje jeden zástupný symbol s předponou L: pro každý koncový bod (L:music, L:podcast, L:filter:…); každá úroveň je vypočítána pouze, když do ní klient prochází (LazyBrowse → EnsureLazyEndpointInMemory → mezipaměti na úrovni), a oznámení o změně knihovny vymažou mezipaměti (SetLibraryDirty).
Proč: studený start je v podstatě okamžitý – HTTP port je otevřen v době, kdy MusicBee dokončí inicializaci pluginu – a paměť zůstává úměrná tomu, co bylo procházeno, nikoli velikosti knihovny. Kompromis: první procházení do koncového bodu platí své náklady na načtení; opětovný vstup je uložen v mezipaměti až do další změny knihovny. To je základ, na kterém závisí vše ostatní. Úplné poznámky: FIXES.md.
Sítě a robustnost
Zpevnění cesty vazby HTTP serveru. Původní plugin tiše umírá, když je jeho port nedostupný.
N04 – Samoopravné vázání HTTP portu
Co: HTTP server pluginu již nezemře, když je jeho nakonfigurovaný port nedostupný. Tři propojené změny:
- Automatický fallback při selhání vazby.
HttpServer.Startzkusí nakonfigurovaný port a přiSocketExceptionprohledá až 20 portů nahoru pro první volný. Skutečný vázaný port je zaznamenán v novémPlugin.boundServerPorta vše, co inzeruje server – SSDPLOCATIONURL (NOTIFY + M-SEARCH odpověď), URL zařízení (PrimaryHostUrl), přesměrování portu routeru a SSDP/control-point self-filtry – nyní čteboundServerPortnamístoSettings.ServerPort. UPnP klienti objeví skutečný port přes SSDP, takže přesunutý port je pro renderery transparentní. - Uživatelské oznámení. Když dojde k fallbacku (uložený port není ten, který se používá), lokalizovaný
MessageBox(WarnPortInUse) sdělí uživateli, který port skutečně slouží a že zařízení jej stále najdou – protože plugin běží bez hlavy a zpráva v dialogovém okně by byla viděna pouze někým, kdo již tušil problém. - Obnova po restartu.
RestartServer(cesta restartu po uložení nastavení) dříve slepě dereferencovalPlugin.controller/Plugin.server. Pokud počátečníInitialisevyhodil chybu před jejich vytvořením (přesně to, co způsobilo selhání vazby), další uložení nastavení narazilo naNullReferenceException– zanechalo polomrtvý plugin. Nyní je znovu vytvoří a spustí, kdyžNothing, takže uložení funkčního portu oživí plugin bez úplného restartu MusicBee.
Proč: spouštěčem byl skutečný incident uživatele. Starý výchozí port 49382 žije v dynamickém rozsahu Windows (49152-65535), kde Hyper-V/WSL2/Docker/WinNAT rezervují velké bloky, které se posouvají při každém spuštění – takže vazba selhala s WSAEACCES („přístup zakázán“) na stroji, kde fungovala měsíce. Změna výchozího portu na volný port se poté střetla se Serviio (samostatný DLNA server již na novém portu), což selhalo s WSAEADDRINUSE. Každé selhání bylo pohlceno v Initialise, což zanechalo plugin tiše mrtvý a poté NRE při dalším uložení nastavení. Po N04 se kolize portů samoopraví – server běží na dalším volném portu, uživatel je informován a klienti jej znovu objeví – namísto toho, aby se celý plugin zhroutil.
Implementace:
- Výchozí port přesunut
49382→9779(pod dynamickým rozsahem, takže Windows jej nikdy automaticky nerezervuje; není známým výchozím nastavením mediálního serveru) ve všech třech deklaracíchServerPort+ fallback při selhání parsování nastavení. Plugin.boundServerPort(nové sdílené pole) drží živý poslechový port;activeServerPortzůstává nakonfigurovaným snímkem, takže logika odznaku „Restart Required“ se nespustí falešně při fallbacku.HttpServer.PortScanRange = 20; sken se zastaví při prvním úspěšnémTcpListener.Start()a vyhodí poslední výjimku pouze, pokud všechny pokusy selžou.- Nový klíč zdroje EN
WarnPortInUse(překlady následují po průchodu locale v době publikace).
N05 – SSDP oznámení přes multicastovou skupinu (VPN / point-to-point)
Co: SSDP oznámení jsou odesílána do UPnP multicastové skupiny (239.255.255.250) namísto IP broadcast adresy. Neškodná chyba „nelze přistupovat k uvolněnému objektu“ zaznamenaná, když SSDP vyhledávací odpověď závodí s restartem serveru, je také potlačena.
Proč: na point-to-point / VPN síťových adaptérech se IP broadcast neuplatňuje – staré broadcastové odesílání selhalo s „neplatným argumentem“ a oznámení byla zmeškána, takže plugin byl pro klienty na těchto odkazech neviditelný. Oznámení správné multicastové skupině opravuje objevování přesně na těchto adaptérech.
Navigace v knihovně
Tyto funkce byly dodány v tomto forku a nejsou v původním pluginu. Pocházejí z reálného procházení výstupu pluginu skutečnými UPnP klienty.
N06 – Expozice knihovny na základě filtru
Co: záložky filtrů MusicBee (soubory .xautopf ve složce MusicBee uživatele) se stávají kořenovými UPnP kontejnery v knihovně pluginu. Skladby každého filtru jsou pak procházitelné v hierarchii AlbumArtistSort → Album → Tracks.
Proč: uživatelé s kurátorovanými filtry MusicBee (např. „5hvězdičkové skladby“, „Nedávno přidané“, „Klasika → Baroko“) očekávají, že je najdou při procházení pluginu z UPnP klienta. Původní plugin vystavoval pouze syrový strom knihovny.
N07 – Zapojení pole SortAlbumArtist
Co: plugin nyní čte MetaDataType 165 (Sort Album Artist) z MusicBee a používá jej k seskupování/řazení umělců v zobrazeních procházení.
Proč: hi-fi prohlížeče a audiofilové používají názvy umělců pro řazení („Beethoven, Ludwig van“ namísto „Ludwig van Beethoven“) k organizaci knihoven. Standardní očekávání pro vážné posluchače. Chybí v obou upstreamových verzích.
N08 – Zpracování vícehodnotového AlbumArtist
Co: když pole AlbumArtist alba obsahuje více umělců oddělených "; " (např. "yaiol; Ars Ricercata"), skladba se nyní zobrazuje pod každým umělcem v zobrazeních procházení, nikoli pod jediným Frankensteinovým umělcem kombinujícím jména.
Proč: kolaborativní alba a kompilace se musí zobrazovat pod každým spolupracovníkem. Bez toho je polovina cest k nalezení alba nefunkční.
N09 – Artwork kontejneru alba (upnp:albumArtURI)
Co: uzly kontejneru alba v odpovědích DIDL Browse nyní obsahují prvek upnp:albumArtURI ukazující na obal alba.
Proč: bez toho každé album v zobrazení procházení UPnP klienta zobrazuje generickou ikonu namísto obalu alba. Vizuální vodítko pro navigaci; očekáváno každým moderním hi-fi prohlížečem.
N10 – Řazení skladeb v albech filtru
Co: skladby uvnitř alba vystaveného filtrem jsou nyní řazeny podle čísla disku, poté podle čísla skladby.
Proč: standardní pořadí alba. Bez explicitního řazení se skladby vracely v jakémkoli pořadí, v jakém je filtr náhodou vrátil – obvykle vypadaly náhodně.
N11 – Oprava stromu složek playlistů
Co: funkce LoadLibraryPlaylists (původně od Stevena Mayalla, ~2014) nedokázala sestoupit do nově vytvořených složek playlistů. První playlist v každé složce, plus jakékoli podsložky, skončily osamocené na kořenové úrovni.
Proč: přítomno v původním pluginu jedenáct let. Viditelné do 30 sekund po otevření BubbleUPnP a kliknutí na Playlists. Opraveno v yaiol správným rekurzivním procházením nově vytvořených složek během konstrukce stromu.
N12 – Sanitizace XML-nelegálních řídicích znaků
Co: jakákoli skladba s tagem obsahujícím řídicí znak C0 (např. 0x19 z chybně provedeného kódování – UTF-8 → Latin-1 → zpětné zkrácení 0x99 na 0x19) způsobila selhání celé odpovědi Browse s Action Failed, jakmile se chybná skladba dostala do stránkované dávky.
Proč: XML 1.0 zakazuje většinu řídicích znaků C0 a XmlWriter vyhodí chybu, když je požádán o zápis jakéhokoli. Přítomno v původním pluginu. Opraveno odstraněním neplatných znaků na každém výstupním bodě Library_GetFileTags pomocí XmlConvert.IsXmlChar.
N13 – Determinismus seznamu rádií napříč stránkovaným procházením
Co: procházení kontejneru Rádio spadlo do obecné větve seznamu souborů, která při každém volání volala files.Sort(AlbumFileComparer). Položky rádia mají prázdné tagy Album/Disc/Track, takže každé porovnání vrátilo 0 – List(Of T).Sort je nestabilní a produkuje jiné pořadí při každém vyvolání. UPnP ovládací body stránkují (BubbleUPnP načte 0..15 a poté 16..konec); mezi dvěma voláními se seznam přeskupil, takže některé stanice se objevily na obou stránkách (duplikáty) a některé na žádné (chybějící) – při každém obnovení vypadaly náhodně.
Proč: přítomno v původním pluginu (jeho autor nikdy neprochází rádio přes UPnP). Zde opraveno vyhrazenou větví ContainerCategory.Radio v Browse, bez řazení na volání; radioFiles je jednou seřazeno při načítání podle názvu (stabilní). Stránkované procházení nyní vidí deterministické pořadí; stránka 1 a stránka 2 jsou disjunktní.
N14 – UPnP Search třídy alba vrací kontejnery alb
Co: UPnP Search pro dotazy třídy alba (upnp:class = "object.container.album.musicAlbum", např. „Náhodná alba“ v BubbleUPnP) vracel úplný seznam skladeb namísto kontejnerů alb, takže klient zobrazoval nula alb. Původní obsluha parsovala pouze kritéria v závorkách, poté vypsala všechny skladby bez ohledu na požadovanou třídu.
Proč: zde opraveno – dotazy třídy alba nyní enumerují odlišná alba (seskupená podle AlbumArtist+Album) a každé z nich emitují jako správný kontejner musicAlbum s obalem, adresovatelný přes virtuální ID prostor Salb<idx>, takže klient může proniknout do výsledku a přehrát jej.
N15 – Funkční, rozsahově uvědomělé UPnP vyhledávání s proklikem
Co: původní verze neoznamovala žádné vyhledávací schopnosti (GetSearchCapabilities vracelo prázdné), takže klienti odmítali vůbec posílat vyhledávání; a starý backend četl z musicFiles, trvale prázdných v éře líného stromu. Tento fork inzeruje skutečné prohledávatelné vlastnosti, implementuje vyhledávání skladeb podle názvu a alb podle názvu proti líné knihovně (HandleLazySearch), omezuje dotaz na aktuální větev klienta, když je odesláno skutečné ID kontejneru (jinak nahrazuje L:music, takže vyhledávání v horní liště nezatahuje šum z podcastů/rádia/audioknih), a umožňuje klikání na výsledky alb pomocí syntetických ID Ssrch_alb_*, které větev Browse mapuje zpět na skladby alba. (Část s výsledky třídy alba jako kontejnery je N14.)
Proč: vyhledávání v BubbleUPnP se změnilo z „Knihovna nepodporuje vyhledávání“ na vracení užitečných, rozsahově omezených a přehrávatelných výsledků. Úplný návrh + zamítnuté přístupy: SEARCH.md.
N16 – Zneplatnění mezipaměti UPnP (SystemUpdateID)
Co: původní verze vracela konstantní SystemUpdateID=0 – kontrakt UPnP ContentDirectory pro zneplatnění mezipaměti – takže klienti vyhovující specifikaci (BubbleUPnP) považovali knihovnu za neměnnou: zastaralé výsledky procházení, 404 miniatury po změně schématu URL a tanec „restartujte MusicBee dvakrát, abyste viděli změny“. Tento fork inicializuje SystemUpdateID z epoch-sekund při načítání (takže každý restart je striktně předchozí) a zvyšuje jej při každé mutaci knihovny a změně nastavení (SetLibraryDirty / ResetCache → BumpSystemUpdateId).
Proč: klienti spolehlivě zaznamenávají úpravy, nové soubory a změny nastavení při dalším procházení. Známé omezení: přihlášení klienti nejsou aktivně znovu pushováni s novou hodnotou přes GENA (parkováno jako budoucí práce); stále ji vidí při dalším procházení.
N17 – Artwork předplatného podcastu
Co: dlaždice podcastů nezobrazovaly žádné obrázky – každý požadavek /PodcastThumbnail/ vracel 404. Dvě navrstvené chyby: řetězec rozlišení nikdy nekontroloval skutečnou mezipaměť artworku MusicBee (%LocalAppData%\MusicBee\InternalCache\Subscriptions\<name>.jpg, odkud se načítá desktopové UI), a vrstva HTTP unescape+lowercase zkomolila klíč trasy URL kanálu až na jeho poslední segment cesty. Tento fork rozlišuje artwork z interní mezipaměti MB a směruje vyhledávání přes URL-bezpečný slug, který přežije vrstvu HTTP neporušený (PodcastSlug / podcastSubIdBySlug).
Proč: artwork předplatného se nyní vykresluje v zobrazeních procházení (všech 22 dříve 404-vracejících požadavků se vyřeší).
N18 – Hierarchické (oddělené) procházení tagů
Co: jakékoli pole lze na kartě Možnosti knihovny označit jako hierarchické a dát mu jednopísmenný oddělovač (výběr pole + pole oddělovače s přidáním/odebráním, trvale uloženo v nastavení pluginu). Nastavte Seskupení na / a hodnotu jako Jazz/Cool Jazz se pak prochází jako Jazz › Cool Jazz namísto jednoho plochého záznamu. Skladby označené přesně na větvi (jen Jazz) dostanou svůj vlastní uzel [Jazz], takže nic není skryto, větev s jedním dítětem se sama zhroutí a ; je odmítnut jako oddělovač, protože je to vlastní vícehodnotový oddělovač MusicBee.
Proč: hluboké taxonomie tagů, které uživatel již zakódoval do jednoho pole (stromy žánrů, hierarchie nálad, „Klasika/Baroko/Koncert“), se konečně procházejí jako strom, který tag popisuje, namísto ploché zdi řetězců oddělených lomítky, které uživatel musí číst od začátku do konce.
N19 – Jedna kořenová cesta označená svým seskupovacím polem
Co: jedna cesta procházení v kořeni je označena svým seskupovacím polem (např. „Žánr“) namísto celé krátké cesty, což odpovídá tomu, jak jsou pojmenovány sloučené skupiny prvního pole.
Proč: strom procházení se čte konzistentně – jedno pravidlo pojmenování, ať už kořenová položka stojí sama, nebo byla sloučena se sourozenci (N20) – namísto toho, aby osamělá kořenová položka zobrazovala podrobnou interní cestu, zatímco její sloučení sousedé zobrazují čistý název pole.
N20 – Sloučení cest procházení, které sdílejí první pole
Co: dvě cesty procházení, které sdílejí stejné první pole – „Žánr / Řadit podle interpreta alba“ a „Žánr / Lidé z podcastů“ – se zhroutí do jedné kořenové složky Žánr, která nejprve vypíše hodnoty žánru a poté se rozdělí na dva pohledy, namísto dvou téměř duplicitních záznamů „Žánr / …“ vedle sebe v kořeni.
Proč: uživatel s několika souvisejícími pohledy vnořenými pod společné pole viděl kořen přeplněný téměř identickými položkami nejvyšší úrovně. Jejich sloučení udržuje kořen čitelný a seskupuje související pohledy tam, kam patří – pod jejich sdílené pole.
N21 – Cesty procházení podle kategorie (Standardní / Rádio / Podcast)
Co: každá cesta procházení je typována podle kategorie – Standardní, Rádio nebo Podcast. Seznam šablon je seskupen do těchto tří sekcí, výběr pole každé šablony nabízí pouze pole, která data dané kategorie skutečně mohou poskytnout, a šablona může být aplikována pouze na odpovídající uzly ve stromu Zobrazení (nekompatibilní uzly se zašednou a nelze je zaškrtnout). Rezervované šablony Rádio a Podcasty nelze smazat, takže jejich sekce kategorie nikdy nezmizí.
Proč: bez typování by uživatel mohl vytvořit rozvržení, které by se tiše objevilo prázdné – rozhlasová stanice nemá „album“, epizoda podcastu nemá „interpreta alba“ – a zjistil by to až procházením do mrtvé složky z UPnP klienta. Omezení nabídky polí a cílů aplikace na skutečná data kategorie znemožňuje vytváření prázdných rozvržení.
N22 – Seskupování podcastů podle roku vydání
Co: datum vydání každé epizody podcastu je načteno, takže cesta procházení podcastu s úrovní Rok seskupuje epizody podle roku namísto jejich zhroucení pod jediné „Neznámé“.
Proč: velká předplatná podcastů se stávají navigovatelnými podle roku jako zbytek knihovny, namísto toho, aby každá epizoda skončila v jedné nedatované hromadě, protože plugin nikdy nekontroloval datum vydání jednotlivých epizod.
N23 – Sbalení úrovní seskupení s jedním výsledkem
Co: úroveň seskupení, která se vyřeší na jednu hodnotu – úroveň typu záznamu zobrazující pouze „LP“ pro umělce, který vydal pouze LP, nebo úroveň písmene s jedním písmenem – je automaticky přeskočena, čímž se uživatel dostane přímo k jejímu obsahu.
Proč: procházení složky, která obsahuje přesně jednu složku, je čisté tření. Sbalení úrovně s jednou volbou odstraní mrtvé kliknutí, aniž by se změnilo to, k čemu se uživatel může dostat.
N24 – Seskupování/vyhledávání podle roku proti datovému poli MusicBee
Co: podmínka roku již nehledá v celodenním poli „Rok“ MusicBee s holou čtyřcifernou hodnotou a pevně zakódované aliasování pole roku je pryč, takže každé pole pro seskupení se nyní obecně řeší z definice cesty.
Proč: pro knihovny, jejichž tag Rok obsahuje kompletní datum, seskupování nebo vyhledávání podle roku dříve nevracelo nic – čtyřciferný dotaz nikdy neodpovídal celodennímu poli. Dotazování správného pole způsobí, že seskupování a vyhledávání podle roku znovu najde skladby.
N25 – Samostatná pole pro seskupení „Rok“ a „Rok (rrrr)“
Co: seskupení alb a cesty procházení nyní vystavují obě vlastní pole roku MusicBee – Rok (tag s celým datem) a Rok (rrrr) (pouze čtyřciferný rok) – takže uživatel si může vybrat jedno z nich při definování seskupení alb nebo cesty procházení.
Proč: obě pole znamenají v MusicBee různé věci a jejich sloučení tuto odlišnost ztratilo. Zobrazení obou umožňuje uživateli shromáždit všechna vydání jednoho roku dohromady (rrrr) nebo zachovat přesné řazení podle data (tag s celým rokem), podle jejich záměru.
N32 – Připnuté filtry a playlisty seskupené podle typu v kořeni
Co: připnutý filtr se nyní zobrazuje přímo pod složkou Filtry v kořeni procházení a připnutý playlist přímo pod složkou Playlisty, namísto toho, aby se všechny připnuté položky shromažďovaly v jedné hromadě na konci kořene. Každá připnutá zkratka sedí se svým vlastním typem.
Proč: jak uživatel připíná více zkratek, jedna koncová hromada smíšených filtrů a playlistů se stává obtížněji skenovatelnou a odděluje každou zkratku od složky, do které patří. Seskupení připnutých položek pod jejich vlastní kategorií udržuje kořen čitelný a udržuje každou zkratku vedle věcí, ke kterým patří.
Dialog nastavení a balení
N26 – Sekcionovaný dialog nastavení
Co: stránka Předvolby získala rozložení s levým navigačním panelem a sekcemi: Obecné / Přehrávání / Knihovna / Profily zařízení / Diagnostika.
Proč: původní verze byla jediný dlouhý plochý seznam všech nastavení – v pořádku pro vývojáře, který ji vytvořil, ale matoucí pro všechny ostatní. Sekcionování seskupuje související možnosti a dialogové okno působí více jako moderní nastavení aplikace.
Přejmenování sestavení + pluginu (bez F-id – poznámka k balení)
Co: zkompilovaná DLL se jmenuje mb_UPnP_yaiol.dll a plugin se hlásí jako „MusicBee UPnP (yaiol)“. Odlišné od původního mb_Upnp.dll.
Proč: uživatelé mohou nainstalovat yaiol vedle původního pluginu a porovnat chování vedle sebe.
Systém odznaků – zobrazení stavu běhu (mechanismus za F40)
Co: obecný vzor UI pro zobrazení důležitých podmínek běhu jako viditelných barevných odznaků v dialogovém okně Nastavení. Aktuální instance:
- ⚠ Max Conn (N04) – spustí se, když byl limit maximálního počtu připojení dosažen alespoň jednou od spuštění MusicBee. Sticky session flag
Plugin.MaxConnectionsHit. Nastaveno uvnitřWaitOnSendBarrier, když není volný slot. - ⚠ Restart Required – spustí se, když uložené nastavení vyžaduje restart MusicBee, aby se projevilo. Sticky session flag
Plugin.RestartRequired. Nastaveno v obsluze uložení dialogového okna, když se nová trvalá hodnota liší od snímku běhu (Plugin.activeMaxConnections,Plugin.activeServerPort,Plugin.activeIpAddress). Nastavení vyžadující restart jsou omezena na ta, která se skutečně nemohou hot-reloadovat – parametry vazby HTTP serveru a SemaphoreSlim vytvořené jednou při inicializaci.
Proč: soubor protokolu pluginu je v pořádku pro technické uživatele ladění, ale netechnický uživatel, který se dívá na „zařízení zní špatně“ nebo „přehrávání je pomalé“, nikdy neotevře Diagnostika → Zobrazit protokol. Odznaky zachycují případy, kdy uživatel potřebuje vědět, že se něco stalo, a zobrazí to při příštím otevření pluginu – zjistitelné bez čtení čehokoli.
Znovu použitelné pro budoucnost:
- Detekována neshoda profilu (uživatelský agent zařízení se nikdy neshodoval s žádným profilem, vrátil se k Generic).
- Spuštěn NextURI backoff (F13 – bezmezné přehrávání zakázáno pro relaci na nestabilním zařízení).
- Skenování knihovny selhalo / částečné.
- Připojení rendereru ztraceno uprostřed relace.
- Jakákoli jiná podmínka, kde „stalo se jednou, uživatel by měl vědět“ vítězí nad „tiše zaznamenáno mezi 1000 dalšími řádky“.
Konvence implementace:
- Popisky odznaků žijí na úrovni dialogového okna (ne uvnitř žádného panelu), takže jsou viditelné bez ohledu na to, v jaké sekci se uživatel nachází.
- Umístěny podél spodního řádku poblíž Uložit/Zrušit (aktuální: y=410 horizontálně naskládané).
- Každý odznak má odpovídající sticky session flag v
Plugin, který se přepne na True, když nastane podmínka, a resetuje se pouze při restartu MusicBee. - Zdroje:
<Condition>Badge(text popisku, předpona s ⚠) +<Condition>BadgeTip(tooltip vysvětlující příčinu + nápravu). - Pro odznaky „uložené nastavení vyžaduje restart“ vezměte snímek běhu při
Plugin.Initialise()a porovnejte sSettings.*poSettings.SaveSettings()v obsluze uložení dialogového okna.
N27 – Zrušit zahodí úpravy cest/šablon
Co: úpravy provedené v cestách a šablonách v dialogovém okně nastavení jsou nyní zahozeny, když uživatel klikne na Zrušit, namísto tichého zachování, a jakákoli rezervovaná šablona odstraněná během relace je znovu vytvořena. (Šablony se jinak ukládají živě, jak jsou upravovány – na kartě Cesty není samostatné tlačítko Uložit.)
Proč: Zrušit by mělo znamenat zrušit. Dříve uživatel, který experimentoval se změnami cest/šablon a vrátil se zpět, zjistil, že změny jsou již potvrzeny, bez možnosti je vrátit zpět jinak než ručním přepracováním každé z nich.
N28 – Doslovné ampersandy v menu výběru pole
Co: pole, jehož název obsahuje „&“ – např. „Nálada & Kontext“ – vykresluje ampersand doslovně v menu výběru pole namísto jeho pohlcení jako předpony Alt-mnemonic.
Proč: názvy polí s ampersandem se zobrazovaly špatně (znak zmizel a další písmeno se stalo akcelerátorem), což ztěžovalo rozpoznání položky menu.
N29 – Stabilní, nepřeložený název okna nastavení
Co: název okna nastavení je pevně nastaven na řetězec značky „MusicBee UPnP Plugin“ a již se nemění s jazykem rozhraní; řetězec DialogTitle pro jednotlivé jazyky byl odstraněn z každého balíčku locale.
Proč: název okna, který měnil znění podle jazyka, byl přeložitelný povrch bez přínosu – název je značka. Jeho upevnění jej udržuje stabilní a konzistentní všude.
Lokalizace
Původní plugin je pouze v angličtině. Tento fork je plně lokalizovatelný – každý uživatelsky viditelný řetězec prochází balíčkem zdrojů a plugin automaticky detekuje vlastní jazyk UI MusicBee.
N30 – Vícejazyčné UI (překlady čekají)
Co: lokalizační mechanismus je kompletní a dodává se. Localisation.vb čte vybraný jazyk MusicBee z MusicBee3Settings.ini (endonym <SystemLanguage>) a aplikuje odpovídající .NET kulturu na vlákno, takže My.Resources.Resources.* vrací lokalizovaný řetězec. Každý uživatelsky viditelný popisek/tlačítko/zpráva je propojen s klíčem zdroje (ovládací prvky návrháře přes ApplyDesignerExtras + sync-en-locale.js; řetězce běhu jako WarnPortInUse ručně přidány). Co není ještě hotovo, je samotný překlad: existuje pouze anglický zdrojový balíček (Resources.resx) – satelitní balíčky pro ostatní jazyky se vytvářejí v jedné dávce, když je plugin kompletní (překládání po částech, zatímco se řetězce stále mění, je plýtvání úsilím).
Cílové jazyky (sada, kterou nabízí samotný MusicBee, shodná 1:1 s endonymToCulture, takže plugin automaticky sleduje jazyk MusicBee):
Arabština (ar) |
Čeština (cs) |
Němčina (de) |
Řečtina (el) |
Španělština (es) |
Francouzština (fr) |
Maďarština (hu) |
Italština (it) |
Korejština (ko) |
Holandština (nl) |
Norština (nb) |
Polština (pl) |
Portugalština BR (pt-BR) |
Portugalština PT (pt-PT) |
Švédština (sv) |
Turečtina (tr) |
Ukrajinština (uk) |
Ruština (ru) |
Japonština (ja) |
Zjednodušená čínština (zh-CN) |
Tradiční čínština (zh-TW) |
Angličtina (en, zdroj) |
Politika variant (podle pravidla locale pracovního prostoru): PT a ZH jsou rozděleny do odlišných balíčků, protože slovní zásoba/skript se skutečně liší (pt-BR/pt-PT, zh-CN/zh-TW). EN je jediný balíček – „English(US)“ MusicBee (en-US) se vrací k en přes řetězec kultury .NET, takže se nevytváří samostatný balíček US. ES a FR jsou rovněž jednolokální.
Proč: nastavení UPnP pluginu („nepoužívat raw PCM“, „vynutit little-endian PCM“, varování o fallbacku portu) jsou dostatečně kryptická v rodném jazyce. Sledování vlastního jazyka UI MusicBee – namísto vynucování angličtiny – je rozdíl mezi nástrojem, který si uživatel, který nemluví anglicky, může nakonfigurovat, a nástrojem, který nemůže. Žádný upstream se o to nepokusil.
N31 – Odkaz nápovědy se otevírá v plném jazyce rozhraní
Co: otevření odkazu nápovědy z pluginu respektuje kompletní jazyk rozhraní uživatele (např. pt-BR, zh-CN) namísto zhroucení na základní jazyk a odesílá jasnější identifikátor kontroly aktualizací.
Proč: uživatel, který používá MusicBee v regionální variantě (brazilská portugalština, zjednodušená čínština), byl přesměrován na stránku nápovědy v základním jazyce. Přenášení plné kultury je přivede na stránku nápovědy v přesném jazyce, který používají.
Opravy a vylepšení původního pluginu
Základní protokol a přehrávání
F01 – Aktualizované výchozí profily zařízení DLNA
Co: dodává nové výchozí profily pro PlayStation 4, Xbox 360/One a moderní BubbleUPnP, s příznaky schopností (vzorkovací frekvence, bitové hloubky, kodeky), které odrážejí to, co tato zařízení dnes skutečně podporují.
Proč: výchozí nastavení původního pluginu bylo zmrazeno kolem roku 2014. PS4/Xbox/BubbleUPnP od té doby získaly podporu hi-res zvuku. Po vybalení z krabice nová instalace hraje na těchto zařízeních nejlépe ve své třídě, aniž by uživatel musel měnit nastavení profilu zařízení.
F02 – Ovládací zařízení, která inzerují MediaRenderer:3
Co: plugin zkoumá popis služby UPnP rendereru, aby rozhodl, zda jej MusicBee může ovládat. Původní verze odpovídala pouze urn:schemas-upnp-org:device:MediaRenderer:1. Moderní zařízení inzerují :2 nebo :3. F02 rozšiřuje shodu.
Proč: bez toho se nedávné jednotky Sonos / WiiM / Eversolo jednoduše nezobrazí jako cíle v seznamu zařízení „Přehrát do“ MusicBee – i když mluví stejným protokolem. Jednoduchá oprava shody předpony řetězce odemyká celou moderní generaci zařízení.
F03 – Možnost „Vynutit nativní stream“ pro každý profil (výchozí ZAPNUTO)
Co: po zaškrtnutí plugin odešle původní bajty souboru do zařízení bez transkódování, bez DSP, bez zpracování ReplayGain. Jen syrový soubor, který uživatel vybral, bajt po bajtu (s výjimkou HTTP rámování).
Proč: podle svědectví z fóra je to největší přínos pro kvalitu přehrávání. Hi-fi uživatelé kupující drahé renderery explicitně chtějí bit-perfect výstup; jakýkoli dotyk DSP ruší smysl. Výchozí ZAPNUTO, protože většina moderních zařízení zvládne jakýkoli kodek, který jim uživatel hodil, a ReplayGain/EQ by mělo být volitelné. Je to pro každý profil, takže můžete zachovat transkódování pro starý Xbox a zároveň odesílat nativní do hi-fi DAC.
F04 – „Vynutit transkódování“ pro každý profil
Co: přepsání pro každý profil, které vynutí každý stream do tohoto zařízení přes transkodér, bez ohledu na podporu nativního kodeku. Opak F03 (ForceNativeStream). Vzájemně se vylučuje s F03 – UI automaticky odškrtne druhé, když je jedno z nich zapnuto.
Proč: jediný globální přepínač by byl v rozporu s ForceNativeStream pro každý profil (F03). Reálný případ: zařízení A je hi-fi DAC, které chce bit-perfect nativní streamy; zařízení B je starý AV přijímač, který se dusí na FLAC. S globálním přepínačem si uživatel musí vybrat – na úkor druhého zařízení. S profilem pro každé zařízení získá správnou odpověď.
Implementace:
StreamingProfile.ForceTranscoding As Boolean = False.- Schéma persistence zvýšeno na v9. Soubory před v9 načtou jednou starou globální hodnotu a zkopírují ji do všech profilů, čímž zachovají staré chování během upgradu.
- UI: odstraněno z panelu Diagnostika, přidáno do sekce Profily zařízení vedle ForceNativeStream. Obousměrné obsluhy vzájemného vyloučení (
CheckedChangedna každém odhlásí druhé před přepnutím, aby se zabránilo nekonečné smyčce). - Místo rozhodnutí:
Settings.ForceTranscoding→streamingProfile.ForceTranscodingvWriteAudioFileDIDL.
F05 – „Vynutit little-endian PCM“ pro každý profil
Co: PCM streamy (L16/L24 mime typy) jsou podle specifikace big-endian. Některá zařízení chybně očekávají little-endian a přehrávají bílý šum, když dostanou správná big-endian data. F05 přepíná pořadí bajtů pro každý profil.
Proč: bez toho některá zařízení vydávají stěnu statického šumu. Symptom je dramatický a příčina neviditelná bez znalosti kódování PCM – přepínač dává uživatelům opravu metodou pokus-omyl.
F06 – „Nepoužívat Raw PCM“ pro každý profil
Co: když zařízení tvrdí, že podporuje raw PCM, plugin to použije. Některá zařízení lžou – přijmou SOAP handshake, ale zkomolí skutečná raw PCM data, zatímco správně zpracovávají PCM zabalené v kontejneru WAVE. F06 vynutí PCM-over-Wave bez ohledu na to, co zařízení inzeruje.
Proč: konkrétně některé modely Marantz – inzerují raw PCM, ale funguje pouze WAVE. Bez toho jsou raw PCM streamy zkreslené, bez chybové zprávy, která by na to poukázala.
F07 – „Délka obsahu“ pro každý profil
Co: jakou hodnotu odeslat v HTTP hlavičce Content-Length. Čtyři možnosti:
- Výchozí – skutečný počet bajtů, pokud je znám, jinak vynechat.
- Žádné – nikdy neodesílat hlavičku (pouze chunked encoding).
- Pouze PCM – odesílat pouze pro raw PCM; pro vše ostatní vynechat.
- Pevné – odeslat
UInt32.MaxValue - 8192(sentinel pro „obrovskou neznámou délku“).
Proč: UPnP/DLNA zařízení se divoce liší v tom, jak reagují na Content-Length. Některá potřebují přesné číslo, některá to nenávidí u streamů, některá potřebují sentinel „opravdu velkou“ hodnotu, aby udržela bufferování. To bylo později rozšířeno z pouze PCM na všechny výstupní formáty, protože stejné problémy se objevily u transkódovaných MP3/AAC streamů.
F08 – „Nevymazávat NextURI“ pro každý profil
Co: normálně plugin vymaže zařízení zařazené NextURI, když se fronta vyprázdní (odesláním SetNextAVTransportURI s prázdnou URL). Některá zařízení (zejména Denon) interpretují prázdné NextURI jako „zastavit vše“ a okamžitě zastaví přehrávání. F08 zabraňuje pluginu v jeho vymazání.
Proč: bez toho majitelé Denonu zažívají, že zařízení přeruší uprostřed skladby, když se fronta vyprázdní. S F08 zaškrtnutým zařízením udržuje zastaralé NextURI v paměti (neškodné – jen se přepíše příště, když se něco zařadí do fronty).
F09 – FLAC jako výstupní formát transkódování
Co: rozbalovací nabídka formátu transkódování v profilech zařízení nyní nabízí FLAC vedle PCM 16/24, MP3, AAC, Ogg. Výběrem se BASS kodér směruje přes standardní příkazový řádek pro převod FLAC MusicBee (stejný mechanismus, který již používají MP3/AAC/Ogg).
Proč: pro zařízení, která dobře zpracovávají FLAC, ale nedokážou dekódovat zdrojový kodek (např. Eversolo přijímající knihovnu WMA MusicBee převedenou na FLAC), to zachovává bezztrátovou kvalitu, kde by MP3/AAC zahodily zvuková data. Odblokuje N02 (ovládání downmixu 5.1), které nemohlo být řešeno bez bezztrátové možnosti transkódování.
Implementace: jednořádkový doplněk do bloku Select Case Codec v Encoder.StartEncode – FLAC se připojuje k MP3/AAC/Ogg ve větvi řízené příkazovým řádkem. Rozbalovací nabídka UI dostane „FLAC“ jako 6. možnost. Mapování načítání/ukládání v SettingsDialog se rozšiřuje tak, aby rozpoznalo FileCodec.Flac ↔ SelectedIndex = 5. Mime, typ DLNA a funkce kódování byly již zapojeny v ItemManager.GetMimes / GetDlnaType / GetEncodeFeature z dřívější práce (F21, F26).
Bezmezné přehrávání (SetNextAVTransportURI)
F10 – SetNextAVTransportURI / NextURI jádro
Co: skutečné bezmezné přehrávání. Když zařízení inzeruje podporu SetNextAVTransportURI ve svém popisu služby UPnP, plugin předem zařadí další skladbu do fronty na zařízení, než skončí aktuální. Zařízení interně přechází bez slyšitelné mezery mezi skladbami – to, co slyšíte na CD přehrávači. Toto není hack „nepřetržitého streamu“ (který zřetězí vše do jednoho dlouhého streamu a ztratí metadata pro jednotlivé skladby).
Proč: vlajková funkce Tier-2. Alba nahraná jako nepřetržité živé vystoupení (živé nahrávky, klasické skladby, DJ sety) zní špatně, když je mezi skladbami půlsekundové ticho. Řešení tohoto problému správně je vlajková funkce, nyní v tomto forku.
Poznámky: zařazený zvuk je obsluhován přes HTTP server pluginu pomocí streamHandle=0 (režim načítání knihovny), což znamená, že zvukový engine MusicBee není zapojen do zařazené skladby. Kompromis: efekty ReplayGain/DSP/EQ se nevztahují na další skladbu. Přijatelné, když je zapnuto „vynutit nativní stream“ (výchozí).
F11 – „Zakázat podporu NextURI“ pro každý profil
Co: i když zařízení inzeruje SetNextAVTransportURI, toto zaškrtávací políčko nutí plugin ignorovat tuto reklamu a vrátit se k přehrávání jedné skladby po druhé.
Proč: některá zařízení inzerují NextURI, ale mají chybnou implementaci (pády, poloviční přechody, zamrzání). Namísto reverzního inženýrství každého rozbitého zařízení uživatel dostane přepínač „prostě to zde vypni“.
F12 – Životní cyklus NextURI v seznamu právě přehrávaných
Co: když MusicBee spustí NowPlayingListChanged, plugin znovu vyhodnotí, co by mělo být zařazeno pro bezmezné přechody. Požádá MusicBee o novou „další“ skladbu přes NowPlayingList_GetNextIndex(1) + NowPlayingList_GetListFileUrl, porovná s tím, co je aktuálně zařazeno na zařízení (sledováno přes nové pole nextPlaySourceUrl), a znovu zařadí, pokud se změnilo (nebo vymaže frontu, pokud MusicBee říká, že není žádná další skladba).
Proč: bez F12 zařízení pokračovalo v přehrávání zastaralého NextURI, když uživatel odstranil/přeskupil zařazenou skladbu. To historicky trvalo několik iterací, protože každá mutace seznamu vyžaduje odlišné zpracování – my jsme to zjednodušili tím, že jsme důvěřovali NowPlayingList_GetNextIndex (který již respektuje náhodné přehrávání a opakování všech), takže všechny varianty procházejí stejným porovnáním.
Implementace:
- Nové pole
nextPlaySourceUrlukládá URL knihovny MusicBee toho, co je zařazeno (streamovací URL s příponou handle není srovnatelná s cestou knihovny). - Nová
Public Sub RefreshQueuedNextUri()naMediaRendererDevice. Tři výsledky: žádné NextURI zařazeno → no-op; zařazeno odpovídá novému „dalšímu“ → no-op; zařazeno se liší → zavolatQueueNexts novou URL (neboQueueNext("")pro vymazání – což respektuje F08 DoNotClearNextUri). - Zapojeno v
Plugin.ReceiveNotificationpodNotificationType.NowPlayingListChanged.
F13 – NextURI selhání backoff
Co: po 4 po sobě jdoucích selháních SetNextAVTransportURI na stejném zařízení plugin zakáže bezmezné přehrávání pro toto zařízení, dokud se MusicBee nerestartuje.
Proč: pokud je zařízení skutečně rozbité pro NextURI (přerušované SOAP chyby, síťové závady), plugin by jinak pokračoval v opakování u každé skladby. F13 zastaví šum a tiše se vrátí k přehrávání jedné skladby po druhé.
F14 – Integrace režimu opakování + NextURI
Co: F14 se dělí na dva případy zpracované detektorem přechodu F15 v OnAvTransportStatusCheck:
- Opakovat vše: MusicBee sám předá správnou URL „wrap“ (skladba 1 na konci seznamu) do
Plugin.QueueNext. Není potřeba žádná speciální logika pluginu – zařízení na ni přejde a detektor F15 zavoláPlayer_PlayNextTrackjako obvykle, což vrátí index NPL MusicBee zpět na 0. - Opakovat jednu: MusicBee předá STEJNOU URL skladby do
Plugin.QueueNext. Zařízení na ni přejde (nový stream handle, stejný zdroj). Detektor F15 nyní dotazujePlayer_GetRepeat()– pokud je toRepeatMode.One, přeskočí voláníPlayer_PlayNextTrack, takže MusicBee neposune index NPL pryč od opakující se skladby.
Proč: bez přeskočení Repeat-One by volání Player_PlayNextTrack při bezmezné přechodu posunulo MusicBee na další skladbu v seznamu (Repeat-One ovlivňuje pouze chování automatického posunu na konci skladby v UI přehrávače – Další skladba se vždy posune vpřed), což by bylo v rozporu s tím, co znamená Repeat-One.
Upozornění na počet přehrání: v režimu Repeat-One závisí inkrement počtu přehrání na tom, zda MusicBee 3.7.9563+ zaznamená opakované přehrávání. Starší verze MusicBee přehrávají bezmezné opakování správně, ale chybí jim zvýšení počtu přehrání. Dokumentováno; neblokující.
F15 – Stavový automat detekce přechodu skladby
Co: když zařízení interně přechází z aktuální skladby na NextURI, plugin to musí zaznamenat a říct MusicBee, aby posunul svůj index právě přehrávaných skladeb. Jinak si MusicBee myslí, že je stále na předchozí skladbě a počty přehrání / UI / scrobbling se rozcházejí.
Implementace: dotazuje GetPositionInfo.TrackURI při každém tiknutí časovače stavu. Když nahlášené URI odpovídá tomu, co jsme zařadili přes NextURI, zavoláme Player_PlayNextTrack na MusicBee a nastavíme suppressNextSoapCall, aby výsledné PlayToDevice znovu neodeslalo SetAVTransportURI (což by přerušilo bezmezné přehrávání).
Proč: bez F15 zařízení přehrává další skladbu, ale UI MusicBee říká, že je stále na předchozí. Matoucí, narušuje scrobbling, narušuje sledování počtu přehrání. Detekce přechodu skladby vyžaduje dlouhou iteraci pro každý renderer, protože každá značka rendereru má své vlastní zvláštnosti v tom, kdy hlásí změnu URI (některé hlásí nejprve TRANSITIONING, některé přeskočí přímo na PLAYING s novým URI, některé mají krátké STOPPED mezi tím).
Poznámky: náš první návrh funguje na rendereru BubbleUPnP. Okrajové případy pro jednotlivá zařízení zůstávají v B6.
F16 – Oprava praskání při bezmezné přechodu
Co: praskání nastává, když se zdrojový formát (vzorkovací frekvence / kanály / kodek) zařazené skladby liší od aktuálně přehrávané skladby, což nutí DAC zařízení znovu se uzamknout při přechodu. F16 přidává diagnostiku NextUri:FormatChange, která se spustí v době zařazení, kdykoli se formáty liší, a pojmenuje obě strany – takže uživatelé slyšící praskání mohou korelovat.
Diagnostika také ukazuje na řešení: zaškrtněte ForceTranscoding v profilu zařízení. To homogenizuje každou skladbu na jeden transkódovací kodek/vzorkovací frekvenci/bitovou hloubku, čímž zcela eliminuje rozdíl ve zdrojovém formátu.
Proč odloženo pro skutečnou opravu transkódování pro shodu: strukturální oprava (transkódování zařazené skladby tak, aby odpovídala formátu přehrávané skladby) vyžaduje změny schématu URL HTTP serveru pluginu – aktuálně /encode/{id}0.{ext} obsluhuje zařazený soubor nativně. Budoucí verze F16 by přidala trasy /encode/{id}0_{rate}_{depth}.{ext} pro jednotlivé formáty a zapojila je přes kodér. To je větší architektonická změna, kterou stojí za to provést, pokud skutečné zařízení vykazuje praskání poté, co ForceTranscoding nestačí.
Implementace dnes:
- Pole
lastSourceUrlsleduje aktuálně přehrávanou zdrojovou URL. QueueNextčteFilePropertyType.SampleRate/Channels/Kindpro aktuální i zařazené skladby a zaznamenáváNextUri:FormatChangepři neshodě.
F17 – Resynchronizace ukazatele průběhu po vyhledávání
Co: funkce Seek() již volala GetPlayPositionInformation() po úspěšném Seek SOAP, což opravuje případ „žádná resynchronizace vůbec“. F17 uzavírá zbývající drift až 1s způsobený 1sekundovou kvantizací RelTime UPnP: když se nahlášená pozice zařízení zaokrouhlí na 1 sekundu od uživatelem požadovaného cíle, plugin nyní důvěřuje uživatelově subsekundově přesné hodnotě namísto zkrácení zařízení. Pouze když zařízení hlásí něco dramaticky odlišného (>1s mimo), použijeme jeho hodnotu (vyhledávání přistálo jinde, než bylo požadováno, např. přichycení k klíčovému snímku u některých kodeků).
Proč: bez toho by vyhledávání na 2:30.500 ukotvené proti hlášení zařízení „2:30“ způsobilo, že by ukazatel průběhu ukazoval ~500ms za realitou. Po F17 se ukazatel shoduje s uživatelským záměrem pro běžný případ posouvání uvnitř skladby a stále respektuje hlášení zařízení pro odlehlý případ přichycení k klíčovému snímku.
F18 – Propojení nepřetržitého streamu / NextURI
Co: nyní jsou zavedeny dvě propojení:
- Běh:
QueueNextse vrátíFalsedříve, když je zapnutoSettings.ContinuousOutput. Nepřetržitý stream je jeho vlastní bezmezový mechanismus (jeden dlouhý zřetězený stream); odesíláníSetNextAVTransportURInavrch mate zařízení ohledně toho, zda je každá skladba diskrétní URI nebo součástí nepřetržitého toku. - UI: když uživatel zaškrtne globální zaškrtávací políčko nepřetržitého streamu,
forceNativeStreamaktuálně zobrazeného profilu se automaticky odškrtne. Nepřetržitý stream vždy transkóduje, takže force-native je v kombinaci bezvýznamné.
Proč: zabraňuje uživateli povolit dva konfliktní bezmezové mechanismy současně. Bez F18 by zařízení přijímalo jak URI nepřetržitého streamu, tak NextURI pro každou následující skladbu, s nedefinovaným chováním v závislosti na rendereru.
F19 – Ignorování chyb prázdného NextURI
Co: když je SetNextAVTransportURI voláno s prázdnou URL (např. poslední skladba v seznamu), některá zařízení vrátí chybu SOAP. F19 tyto chyby tiše potlačuje – zaznamenány, ale nešířeny jako chyby.
Proč: stav „žádná další skladba“ je normální, nikoli chyba. Považování za fatální znečišťuje protokol a (v některých tocích) spouští bouře opakování.
Typy mime a metadata DLNA
F20 – MP3 mime → audio/mpeg
Co: standardům vyhovující MP3 mime typ je audio/mpeg, nikoli audio/mp3. Druhý je běžný nesprávný název, který většina zařízení toleruje, ale přísnější renderery jej odmítají.
Proč: tiše opravuje přehrávání na přísnějších zařízeních, která dodržují standard. Kódová základna yaiol to již měla správně; žádná změna nebyla potřeba.
F21 – Pořadí mime typů: nejprve varianta bez x-
Co: když zařízení inzeruje audio/flac i audio/x-flac, plugin vrátí nejprve variantu bez x-. Totéž platí pro jakýkoli kodek se standardními i experimentálními mime typy.
Proč: předpona x- označuje experimentální/neoficiální mime typy. Některé renderery se lépe chovají se standardní formou. Malé přeřazení, reálný dopad.
F22 – Podpora mime typu Opus
Co: rozpoznává Opus jako streamovatelný zvukový kodek; odesílá audio/opus mime při obsluze skladeb Opus.
Proč: Opus je nyní běžný (moderní kompromisní kodek pro řeč/hudbu). Bez F22 by plugin odmítl streamovat soubory Opus i do zařízení, která je zpracovávají.
F23 – Podpora zdrojových souborů Monkey Audio (APE)
Co: rozpoznává soubory .ape jako platný zdrojový kodek pro streamování/transkódování.
Proč: APE je bezztrátový formát s úzkou, ale loajální uživatelskou základnou. Jeho přidání stojí málo a odemyká knihovnu pro tyto uživatele.
F24 – AAC / ALAC mime fallback
Co: pokud zařízení podporuje AAC nebo ALAC, ale explicitně je neinzeruje ve svém popisu služby UPnP, plugin je přesto nabídne jako fallback.
Proč: několik zařízení, která AAC dobře zpracovávají, zapomnělo je uvést ve svém XML schopností. Bez F24 se plugin ani nepokusí, což vynutí transkódování. S F24 se plugin pokusí a nechá zařízení, aby to zpracovalo nativně, pokud to dokáže.
F25 – Příznak typu DLNA pro nativní + kódované WAV streamy
Co: příznak typu DLNA (identifikátor profilu jako LPCM, WAVE, MP3) musí odpovídat tomu, co zařízení přijímá. F25 zajišťuje, že nativní streamy a kódované WAV streamy jsou správně označeny.
Proč: neshodný typ DLNA způsobuje, že některá zařízení zcela odmítnou přehrávání nebo použijí nesprávný dekodér.
F26 – DLNA hlavička pro soubory FLAC
Co: FLAC streamy dostávají správný identifikátor profilu DLNA ve svých hlavičkách.
Proč: bez něj některá zařízení, která podporují FLAC, stream jako takový nerozpoznají.
F27 – Oprava výpočtu bitrate v metadatech
Co: res@bitrate nepřetržitého streamu bylo počítáno jako (sampleRate * channels * bitsPerSample) / 1000 – kbps, s chybou faktoru ~125 oproti specifikaci UPnP DIDL, která definuje atribut jako bajty za sekundu. Nyní se dělí 8 namísto 1000.
Proč: špatné zobrazení bitrate na zařízení – kosmetické na většině rendererů, ale některé alokují streamovací buffery z hodnoty a zadrhávají se u streamů, které vypadají ~125× menší, než jsou. Cesta zdrojového souboru bez nepřetržitého streamu to již měla správně ((bitrate_kbps * 1000) \ 8 = bajty/s); špatná byla pouze cesta nepřetržitého streamu.
F28 – Oprava formátu času metadat (Marantz)
Co: res@duration v DIDL bylo formátováno jako H:MM:SS (např. 0:03:42). Specifikace UPnP DIDL definuje formát jako H+:MM:SS[.F+] – striktně s volitelnými, ale doporučenými zlomkovými sekundami; některá zařízení Marantz považují holou formu za neplatnou a nechávají zobrazení délky prázdné. Nyní formátováno jako H:MM:SS.fff (např. 0:03:42.000).
Proč: problém zobrazení specifický pro značku; konformní formát ve stylu ISO se zlomkovými sekundami to opravuje, aniž by ovlivnil jakékoli jiné zařízení. Aplikováno na obou místech emise DIDL (cesta zdrojového souboru + cesta kódovaného streamu v WriteAudioFileDIDL).
Bonusová oprava ve stejném průchodu: pv:addedTime a pv:lastPlayedTime používaly hh (12hodinový formát) ve svých formátovacích řetězcích DateTime namísto HH (24hodinový). Jakákoli skladba přidaná nebo přehrávaná mezi 13:00 a 23:59 by se zobrazila s chybnou hodinou (např. 17:42 → „05:42“) na zařízeních, která pole zobrazují. Nyní používá HH.
F29 – Podpora vyhledávání v kódovaném MP3 (CBR)
Co: transkódované MP3 streamy nyní inzerují DLNA.ORG_OP=11 (vyhledávání podle bajtů i času) namísto DLNA.ORG_OP=10 (pouze podle bajtů). Zařízení, která dříve odmítala vyhledávání podle času u transkódovaných MP3, nyní mohou normálně ovládat svůj ukazatel průběhu/UI vyhledávání.
Proč: transkodér MusicBee produkuje MP3 s konstantním bitrate při předvolbě HighQuality, takže mapování bajtů ↔ času je lineární – zařízení může převést požadavek na vyhledávání podle času na HTTP Range vyhledávání podle bajtů samo, bez jakékoli podpory na straně kodéru. Inzerování OP=11 odemyká toto UI na zařízení. Bez F29 uživatelé, kteří vyhledávali uvnitř transkódovaného MP3, buď měli vyhledávání tiše ignorováno, nebo byli přesměrováni na začátek skladby.
Implementace: restrukturováno GetEncodeFeature v ItemManager.vb tak, aby se inline If rozdělilo na čitelný řetězec If/ElseIf/Else. MP3 dostane explicitně OP=11; ostatní non-PCM kodeky si ponechají OP=10. Žádná změna pro AAC/FLAC/atd. – ty by vyžadovaly ověření CBR-ness specifické pro kodek, což MusicBee nezaručuje.
F30 – Zpracování přípony souboru .mpeg
Co: soubory s příponou .mpeg (a ještě vzácnější .mpe) jsou nyní rozpoznány jako FileCodec.Mp3 v GetCodec. Před F30 vracely FileCodec.Unknown a byly tiše odmítány z knihovny / nemohly být zdrojem transkódování.
Proč: staré archivy MPEG-1 Layer 3 někdy používaly .mpeg namísto .mp3 (specifikace povoluje obojí). Několik souborů v knihovně o 300k je dost na to, aby se uživatel cítil „MusicBee je ukazuje, ale plugin ne“ – matoucí pro uživatele.
Chování přehrávání
F31 – Rádiové streamy automaticky používají nepřetržitý režim
Co: WriteAudioFileDIDL nyní zkoumá vlastnost Kind zdrojové URL přes Library_GetFileProperty a považuje jakýkoli soubor, jehož Kind končí na „Stream“ (MusicBee hlásí „MP3 Stream“, „Internet Stream“ atd. pro rádio), za nepřetržitý bez ohledu na globální přepínač Settings.ContinuousOutput. Používá se větev DIDL pro nepřetržitý stream (Název: „Nepřetržitý stream“, id="continuousstream", pevný výstup PCM/Wave); zařízení vidí jeden stream nekonečného typu.
Proč: rádiové streamy nemají hranice skladeb, pevnou délku, ani vyhledávání. Zacházení s nimi jako s diskrétními soubory v DIDL způsobilo, že plugin inzeroval rozsahy bajtů a délky, které neexistují. Automatické přepínání, když nám MusicBee již řekl „toto je stream“, odstraňuje past, o které by uživatel neměl přemýšlet.
Rozsah: platí pouze, když MusicBee řídí přehrávání (musicBeePlayToMode). Cesta načítání knihovny (procházení klientem UPnP) je beze změny – URL rádií jsou tam vzácné a chování pro uživatele by se nemělo měnit bez explicitního testování.
F32 – Fallback inzerce kodeku
Co: pokud zařízení neinzeruje určité kodeky (nebo plugin nemůže parsovat XML schopností zařízení), plugin stream okamžitě neodmítne. Místo toho se pokusí jej obsloužit a nechá zařízení rozhodnout.
Proč: mnoho zařízení má neúplné nebo nečitelné XML schopností, ale ve skutečnosti kodek zpracovávají v pořádku. F32 vyměňuje malé „nejlepší odhad a zkusit“ za přímé odmítnutí.
F33 – Zlepšení synchronizace ukazatele průběhu
Co: pozice mezi dotazy je již extrapolována z jednoho kotvícího bodu (currentPlayStartTicks), takže ukazatel průběhu se aktualizuje plynule s subsekundovou rychlostí. Zbývajícím zdrojem chvění byl počáteční kotvící bod pro čerstvě spuštěnou skladbu: předchozí kód předpokládal position=0 v okamžiku, kdy časovač stavu poprvé zaznamenal, že stav přešel na Přehrávání, ale do té doby mohlo zařízení hrát 100-500ms (jeden interval dotazování). Ukazatel průběhu MusicBee by začal na 0, pak by skočil dopředu, když se realita dohnala.
Oprava F33: při prvním přechodu do Přehrávání na nové skladbě (currentPlayStartTimeEstimated=True) zavolejte GetPlayPositionInformation(), abyste získali skutečnou aktuální pozici zařízení, a poté se proti ní ukotvěte. UPnP hlásí pouze rozlišení 1 sekundy, takže kotvící bod je stále kvantizován, ale je mnohem blíže pravdě než předpokládat 0.
Proč: plynulejší + přesnější zobrazení průběhu, zejména hned po změně skladby. Není možné obejít samotné rozlišení hlášení UPnP 1 sekundy – to je specifikace.
F34 – Chvění ukazatele průběhu po změně skladby
Co: když je PlayToDevice voláno pro novou skladbu, plugin dříve ponechával currentPlayPositionMs a currentPlayStartTicks na jejich hodnotách z předchozí skladby po dobu ~100ms okna mezi SOAP-Play a prvním dotazem časovače stavu detekujícím nový stav Přehrávání. Ukazatel průběhu MusicBee by krátce zobrazil konec předchozí skladby, pak by se vrátil na 0, pak by se zvedl. F34 vynuluje obě při vstupu do PlayToDevice – v okamžiku, kdy víme, že dochází ke změně skladby, před jakoukoli prací SOAP.
Proč: vizuální chyba při rychlém přeskakování (ruční další nebo bezmezový přechod). Nyní první dotaz MusicBee na PlayPositionMs po Play vrátí čistě 0, pak F33's GetPlayPositionInformation upřesní na skutečnou pozici zařízení při prvním tiknutí změny stavu.
Implementace: čtyři řádky na začátku PlayToDevice, spárované s přesným ukotvením F33 v době přechodu.
F35 – Chyba „Vynutit transkódování“
Co: vynucené transkódování mohlo v určitých kombinacích stále přeskočit transkódování. Po přepracování F04 pro jednotlivé profily byly utěsněny dvě specifické mezery:
- Priorita s ForceNativeStream. Když byly obě True (což se může stát při migraci schématu nebo částečném souboru nastavení), ForceTranscoding nyní jednoznačně vyhrává (
If streamingProfile.ForceTranscoding Then forceEncode = True ElseIf streamingProfile.ForceNativeStream Then forceEncode = False). Vzájemné vyloučení UI zabraňuje uživateli zaškrtnout obě, ale runtime ochrana řeší jakýkoli stav, který se načetl nekonzistentně z disku. - Logika bypassTranscodeDecision. Dříve:
streamingProfile.ForceNativeStream AndAlso Not Settings.ForceTranscoding. Nyní:streamingProfile.ForceNativeStream AndAlso Not streamingProfile.ForceTranscoding– stejné pravidlo priority, ale ve stejném rozsahu pro jednotlivé profily.
Proč: „vynutit“ by mělo znamenat vynutit. Pokud uživatel explicitně povolil ForceTranscoding pro zařízení, plugin nikdy nesmí tiše přejít na nativní streamování, bez ohledu na to, jak se ostatní příznaky náhodou zkombinují.
F36 – Výjimka rendereru uzavřeného
Co: zabalil Plugin.ReceiveNotification do Try/Catch nejvyšší úrovně, který zaznamenává jakoukoli nezachycenou výjimku namísto toho, aby ji nechal šířit zpět do notifikační pumpy MusicBee.
Proč: oznámení z MusicBee (PlayStateChanged, VolumeMuteChanged atd.) se odesílají do ControlPointManager, který komunikuje s rendererem přes SOAP. Jednotlivá místa volání již měla Try/Catch kolem svých volání SOAP, ale dostatečně zvláštní časový případ (např. renderer umírající mezi dvěma voláními SOAP ve stejném obslužném programu oznámení) mohl stále uniknout. Wrapper nejvyšší úrovně je poslední záchranná síť, takže uživatel nikdy neuvidí obecné vyskakovací okno „TargetInvocationException“ z MusicBee.
Implementace: přejmenoval stávající tělo na ReceiveNotificationInternal a přidal tenký wrapper ReceiveNotification, který provádí Try { ReceiveNotificationInternal(...) } Catch { LogError(...) }. Již existující infrastruktura Try/Catch pro jednotlivé metody uvnitř ControlPointManager (kolem každého volání PostSoapRequest) zůstává – F36 je pás + kšandy.
F37 – Vyhledávání dlouhých skladeb spouštějící falešný přechod
Co: vyhledávání uvnitř dlouhé skladby může na některých rendererech vyvolat krátký cyklus Stopped→Playing. Bez rozlišení ProcessNewPlayState.Stopped to považuje za přirozený konec skladby a volá Player_PlayNextTrack, čímž posune MusicBee, když uživatel chtěl pouze posunout. F37 označí lastUserInitiatedSeek v Seek() a přidá 5sekundovou ochranu v obsluze Stopped (zrcadlící existující okno lastUserInitiatedStop).
Proč: tiché přeskočení na další skladbu během vyhledávání je jednou z těch chyb, u kterých nikdo nemůže uhodnout příčinu – uživatel si myslí „divné, zkusil jsem posunout vpřed a teď hraje další píseň“. Oprava je mechanická: stejný vzor jako již zavedené rozlišení uživatelského zastavení.
F38 – Vylepšené zpracování vyhledávání pro kodeky náchylné k pádům
Co: pád BubbleUPnP při vyhledávání MP3 byl kanonickým symptomem. Po auditu stávající kód vyhledávání yaiol již dělá správné věci – nativní cesta správně zpracovává HTTP Range (206, Content-Range, AcceptRanges), kódovaná cesta inzeruje X-AvailableSeekRange a parsuje příchozí hlavičky timeSeekRange.dlna.org / npt, příznaky DLNA.ORG_OP odrážejí skutečné možnosti streamu (s DisablePcmTimeSeek opt-out pro problémová zařízení Platinum). Uživatelsky testováno na aktuálním BubbleUPnP 4.6.4: žádné pády nebyly pozorovány.
Proč: pád BubbleUPnP při vyhledávání MP3 byl hlášen kolem roku 2024 a aplikace od té doby prošla ~16 měsíci oprav. F29 (kódované MP3 OP=11) byla nová proměnná, která by to mohla znovu odhalit; na testovaných verzích se tak nestalo.
Pokud se pád vrátí: tvar opravy by byl přepínač „omezené vyhledávání“ pro každý profil, který vynutí DLNA.ORG_OP=10 (pouze bajty) na označených kodecích – zrcadlící, jak DisablePcmTimeSeek již funguje pro PCM. Přidat pak, ne preventivně.
UI a logování
F39 – Tlačítko „Přidat“ vybere nový profil
Co: kliknutí na „Přidat“ v seznamu profilů zařízení vytvoří nový profil A automaticky jej vybere, takže uživatel může okamžitě upravovat pole. Naše refaktorování sekcionovaného dialogu to již dělá – jak přímá cesta Přidat, tak cesta z šablony končí Me.activeStreamingProfiles.SelectedIndex = Me.activeStreamingProfiles.Items.Count - 1. Kontrola potvrdila, že náš fork to již zpracovává – nic se nemění.
Proč: malá UX nepříjemnost, která se zde ukázala jako již ne nepříjemnost.
F40 – Větší maximální počet připojení + varovný záznam
Co: limit souběžných streamů pluginu (SemaphoreSlim kolem Sockets_Stream_File / Sockets_Encoder_Start) byl pevně nastaven na 4. F40 jej činí uživatelsky konfigurovatelným na stránce Obecná nastavení (výchozí 16, rozsah 1-256), přidává řádek protokolu MaxConnections, když požadavek musí čekat na slot, A zobrazuje červený odznak ⚠ Max Conn v levém dolním rohu dialogového okna nastavení, pokud byl limit dosažen alespoň jednou od spuštění MusicBee.
Proč: když zařízení spouští paralelní požadavky (některé Marantz/Linn během skenování artworku, metadata sondy BubbleUPnP vedle aktivního přehrávání), další požadavky byly tiše blokovány za semaforem – uživatel viděl „zařízení pomalé“ bez viditelné příčiny. Řádek protokolu je dobrý pro technické ladění, ale netechničtí uživatelé protokoly nikdy nečtou. Viditelný odznak v dialogovém okně nastavení činí stav dosažení limitu zjistitelným pro každého, kdo otevře preference pluginu.
Implementace:
- Centralizováno čekání v
WaitOnSendBarrier(logTag)vMusicBeeUpnp.vb; obě místa volání (MediaServerDevice.GetFile,Encoder.StartEncode) jej používají. Settings.MaxConnectionstrvale uloženo ve v8 schématu nastavení.Plugin.MaxConnectionsHitje sticky session flag nastavený uvnitřWaitOnSendBarrier; resetuje se pouze při restartu MusicBee.SettingsDialog.maxConnectionsBadgeje červený tučný popisek na(16, 410), který se zobrazí pouze, když jePlugin.MaxConnectionsHitTrue. Má tooltip vysvětlující příčinu a nápravu.- Semafor je inicializován jednou při načtení typu, takže změna nastavení vyžaduje restart MusicBee (uvedeno v popisku pole).
F41 – Záznam „kódování kvůli ReplayGain/DSP“
Co: namísto samostatných řádků protokolu „kódování pro RG“ / „kódování pro DSP“ obsahuje jediný řádek StreamDecision z F42 MB-DSP/EQ, MB-ReplayGain, Profile-DSP/EQ, Profile-ReplayGain jako kumulované důvody. Stejná diagnostická hodnota, méně šumu.
Proč: uživatelé vidí všechny důvody, proč dochází k transkódování pro danou skladbu, na jednom řádku protokolu, nikoli rozptýlené. Úplné podrobnosti viz F42.
F42 – Záznam „renderer nepodporuje zdrojový kodek“
Co: přidán řádek protokolu StreamDecision pro každou skladbu přehrávanou do zařízení, který říká buď „nativní KODEK“ nebo „transkód KODEK→KODEK důvod=…“. Pole důvodu kumuluje všechny podmínky, které spustily transkódování: MB-DSP/EQ, MB-ReplayGain, Profile-DSP/EQ, Profile-ReplayGain, WebFile, VirtualFile, ForceTranscoding(global), SampleRate<min/SampleRate>max, DownmixToStereo, DeviceLacksCodec(X), BandwidthConstrained.
Proč: uživatelé byli zmateni neočekávanými špičkami CPU u souborů, které očekávali, že budou streamovat nativně. Jeden řádek protokolu pro každou skladbu jim přesně řekne, která podmínka způsobila transkódování – a pokud pole ukazuje DeviceLacksCodec(Flac), okamžitě vědí, že informace o protokolu zařízení byly neúplné a možná budou chtít, aby se spustil fallback F32.
Implementace: jediný akumulátorový řetězec sestavovaný postupně v rozhodovacím řetězci; zaznamenán jednou na konci. Omezeno na Settings.LogDebugInfo, aby se zabránilo šumu v protokolu v produkci.
F43 – Protokol SetNextAVTransport zobrazuje zdrojovou URL
Co: záznamy protokolu QueueNext nyní obsahují source=<cesta knihovny MusicBee> vedle stream=<HTTP streamovací URL>. Stejná změna aplikována na cestu úspěchu i cestu selhání (QueueNext:Failed).
Proč: při ladění problému se zařazenou skladbou je streamovací URL (/encode/aabbccdd0.flac) sama o sobě neprůhledná – stejná pro každou skladbu. Zdrojová URL je lidsky vyhledatelná cesta knihovny, která vám přesně řekne, který soubor se MusicBee pokusil zařadit.
F44 – Lepší logování chyb mime-typu
Co: dva nové záznamy protokolu během Activate:
Activate:MimeUnverified– spustí se pro každou chybně formátovanou položku v odpovědiGetProtocolInfozařízení, pojmenovává, kterou položku nelze parsovat (takže uživatel může vidět např. „Marantz vrátilhttp-get:*::*pro nějaký kodek – schopnost je neověřená, fallback F32 bude hádat“).Activate:NoSinkInfo– spustí se jednou, pokud zařízení nevrátilo žádný prvek<Sink>. Znamená, žeSupportedMimeTypeszůstává Nothing aIsCodecSupportedse degraduje na „předpokládejme, že vše funguje“ – užitečný kontext, když se později objeví chyby „zařízení odmítlo stream“.
Proč: před F44 tyto tiché propady schopností nechávaly uživatele hádat, proč byly jejich skladby buď transkódovány proti očekávání, nebo odmítnuty zařízením. Nyní jediný grep pro Activate: ukazuje, zda byly informace o schopnostech zařízení použitelné.
F45 – Lepší logování chyb metadat
Co: záznam výjimek Browse v ContentDirectoryService.vb byl již obohacen v dřívější práci yaiol (sezení s chybou Alia Vox) o ObjectID a stack trace. F45 jej dále rozšiřuje o BrowseFlag (metadata vs. děti), Filter (které atributy klient požadoval), sortCriteria a partialResultLength (kolik bajtů DIDL bylo vyprodukováno před selháním – ukazuje, jak daleko v dávce se nachází chybná skladba).
Proč: když se něco pokazí uprostřed DIDL, hodnota partial-length vám řekne, zda k selhání došlo u první skladby dávky (partial=0) nebo v průběhu (partial=N) – v kombinaci s startingIndex dávky můžete identifikovat index chybné skladby. Filter a BrowseFlag vysvětlují, jaký druh procházení klient chtěl; někdy procházení pouze metadat selže tam, kde procházení dětí pro stejné ID uspěje.
Sítě
F46 – Automatický režim inzeruje pouze na adaptérech skutečné sítě
Co: v režimu rozhraní Automaticky plugin dříve oznamoval sám sebe (SSDP) na každém funkčním IPv4 adaptéru. Na stroji, který také provozuje VPN tunel (NordLynx) nebo virtuální přepínač (Hyper-V / WSL / Docker), byla stejná knihovna oznamována i na každém z těchto adaptérů, takže ovládací bod, ze kterého jste vysílali, objevil server dvakrát nebo třikrát a uvedl knihovnu jako duplicitní kopie. Automatický režim nyní ponechává pouze adaptéry, které mají skutečnou výchozí bránu IPv4 (HasIPv4Gateway) – což tunelové a virtuální přepínačové adaptéry nemají – takže tyto jsou z oznamovacího seznamu vyřazeny. Uživatelem připnutá adresa stále jednoznačně vyhrává (oznamuje se pouze na tomto rozhraní), a pokud žádný adaptér nehlásí bránu, selektor se vrátí na každý adaptér, takže seznam inzerovaných adres nikdy není prázdný a plugin se nemůže stát neviditelným.
Proč: duplikát není způsoben „být na VPN“ – je způsoben oznamováním na LAN adaptéru a tunelovém/virtuálním adaptéru současně, takže jeden ovládací bod vidí stejný server na dvou adresách. Spotřebitelská VPN (NordVPN/NordLynx) tuneluje pouze internetový provoz; DLNA renderer žije na LAN a lokální síťový provoz obchází tunel, takže tunelový adaptér stejně nikdy nedosáhne rendereru – jeho vyřazení odstraní fantomovou kopii, nikdy funkční cestu. Test brány je levný, spolehlivý signál, který odděluje skutečný LAN/Wi-Fi adaptér od tunelu nebo virtuálního přepínače. Doplňuje N05 (který opravil jak se oznámení posílají na takových odkazech – multicast namísto broadcastu); F46 řídí které adaptéry se vůbec oznamují.
Známé omezení: mesh / vzdálený přístup VPN (Tailscale, ZeroTier, WireGuard-to-home), jehož renderery skutečně žijí přes tunel, obvykle představuje adaptér bez výchozí brány, takže automatický režim jej také vyřadí. Tito uživatelé místo toho připnou VPN adresu, která má přednost před filtrem brány.