Hva er nytt
2.0.2 - 2026-07-20
- En mal kan ikke lenger slettes mens en node følger den – sletteknappen forblir deaktivert, slik at en node aldri kan bli foreldreløs. Hver malrad viser nå et live (n) antall av sine følgere, noe som forklarer en deaktivert sletting med et øyekast; sletting av en ubrukt mal vedvarer nå, i stedet for at de leverte standardinnstillingene stille dukker opp igjen ved neste lasting.
- En ny trakt-knapp ved siden av visningstreet viser nøyaktig hvilke noder som følger en mal: den filtrerer treet til kun følgerne av den valgte malen, filtrerer på nytt når du velger andre maler, og gjenoppretter hele treet når den slås av.
- Radio- og Podcasts-nodene er nå permanent paret med malen for sin kategori – omform malen på fanen Stier, og noden følger av seg selv; det er ingenting å bruke, så Bruk-knappen er deaktivert for dem. Mallisten gjenspeiler dette med to bånd, Standard (der alle nye maler opprettes) og Reservert (Radio + Podcasts).
2.0.1 - 2026-07-20
- Malstier er nå direkte-koblet til nodene som bruker dem. Ved å bruke en mal får noden den til å følge den: rediger malen senere, og hver node som følger den, omformes umiddelbart – du slipper å lete den opp og bruke den på nytt node for node. Visningstreet viser hvilken mal hver node følger rett etter navnet, en omdøping vises der umiddelbart, og sletting av en mal forteller deg først hvor mange noder som følger den (de beholder sin nåværende layout og slutter ganske enkelt å følge noe).
- Å bruke en mal på en skjult node gjør den også synlig igjen – å bruke er gesten "vis meg dette, formet slik", mens skjuling forblir med avkrysningsboksen
Synlig. Den reserverte "Skjult"-malen som dette erstatter, er borte. - Visningstreet mister ikke lenger plassen din: avkrysningsbokser, utvidede mapper og rulleposisjon overlever alle bruk av maler og andre oppdateringer.
2.0.0 - 2026-06-16
Dette er den første offentlige utgivelsen av den åpen kildekode yaiol-forken av MusicBee UPnP-plugin-modulen. Den presenteres i to deler: alt som er nytt i denne forken, deretter feilrettingene og forbedringene som er gjort i den originale plugin-modulen. Hvert element beholder Hva / Hvorfor-formen fra prosjektets interne funksjonskatalog, slik at begrunnelsen bak hver endring er på siden, ikke bare endringen.
Nytt i denne forken
MediaRenderer – spill til MusicBee
N01 – MusicBee som en avspillingsmottaker (renderer)
Hva: normalt fungerer denne plugin-modulen én vei: en telefon eller en annen enhet blar gjennom MusicBees bibliotek og spiller av musikken på seg selv. Denne funksjonen legger til den motsatte retningen – den lar MusicBee være avspilleren. Fra en kontrollerapp på telefonen din (som BubbleUPnP) kan du velge din stasjonære MusicBee som enheten som spiller av, og deretter styre den fra hånden din: spill av, pause, stopp, hopp fremover eller bakover, hopp til et punkt i sporet, og endre volum eller demp.
Hvorfor: det gjør telefonen din til en fjernkontroll for musikken som allerede er på PC-en din. Sitt på sofaen, bla gjennom biblioteket ditt på telefonen, trykk på et spor, og det kommer ut av høyttalerne som er koblet til skrivebordet ditt – med full kontroll fra der du sitter. Den originale plugin-modulen leverte aldri dette som en fungerende funksjon.
Slå den på: den er av som standard, fordi å slå den på lar alt på hjemmenettverket ditt starte avspilling på PC-en din. Du aktiverer den med en avkrysningsboks på innstillingsdialogens Generelt-fane. Plugin-modulens tre roller har hver sin avkrysningsboks der – del biblioteket mitt (Server), la andre spille til meg (Renderer), og spill til andre enheter (Kontrollpunkt) – og dialogen viser bare innstillingsfanene som rollene du slo på faktisk trenger, slik at du aldri blir møtt med alternativer som ikke gjelder for deg.
Skille maskinene dine fra hverandre: du kan gi mottakeren hvilket som helst navn du ønsker (det starter som "MusicBee (yaiol)"). Det navnet er det som vises i telefonens liste over avspillingsmål, så når mer enn én PC kjører MusicBee kan du se hvilken som er hvilken. En navneendring trer i kraft umiddelbart, uten omstart.
Best mulig lyd når den spiller til seg selv: når du blar gjennom MusicBees eget bibliotek fra telefonen din og sender et spor tilbake til den samme MusicBee, gjenkjenner plugin-modulen at den blir bedt om å spille av en av sine egne filer og spiller den ganske enkelt direkte fra disken din. Resultatet er nøyaktig og øyeblikkelig – bit-perfekt, med MusicBees egen equalizer og volumnivellering brukt – i stedet for meningsløst å sende lyden ut på nettverket og rett tilbake til seg selv.
Kjøre den privat: de tre rollene fungerer uavhengig, slik at du kan slå på mottakeren mens du lar bibliotekdeling være av. I dette "kun mottaker"-oppsettet forblir biblioteket ditt fullstendig skjult fra nettverket – bare avspillingsmålet blir annonsert – og MusicBee vil aldri tilby å spille til seg selv.
Avspillingsatferd
N02 – 5.1 FLAC blir ikke automatisk nedmikset
Hva: kanaltallbegrensningen i MediaServerDevice.GetEncodedFile var If StereoOnly OrElse Not isPcmData Then channelCount = 2. Klausulen Not isPcmData nedmikset stille hver ikke-PCM-transkoding (FLAC, MP3, AAC, Ogg) til stereo uavhengig av kildens kanaltall, noe som gjorde 5.1-kompatible mottakere ubrukelige når kilden var 5.1 FLAC. Nå ekskluderer den andre klausulen FLAC: Not isPcmData AndAlso encoder.Codec <> FileCodec.Flac. FLAC 5.1 passerer gjennom; MP3/AAC/Ogg tvinges fortsatt til stereo fordi MusicBees kommandolinjekodere for disse formatene forventer 2-kanals inndata.
Hvorfor: hele poenget med å transkode en 5.1 FLAC-kilde til FLAC-utdata er å bevare flerkanalsmiksen. Stille nedmiksing gjorde FLAC-transkodingsalternativet ubrukelig for surroundlytting. Med N02 gjør den det riktige.
Arkitektur
Den strukturelle endringen som gjør forken levedyktig på et stort bibliotek – fraværende fra den originale plugin-modulen.
N03 – Lat (on-demand) bla-tre
Hva: den originale plugin-modulen bygde hele bla-treet ved MusicBee-oppstart – enumererte hvert spor, full Library_GetFileTags per fil, samlet hele containerhierarkiet – før HTTP-porten ble åpnet. På et ekte bibliotek (50k+ spor, 5400 podcastepisoder, hundrevis av stasjoner) er det minutter med kaldstart, og treet forblir i RAM for alltid, inkludert grener ingen klient noen gang åpner. Denne forken bygger ingenting på forhånd: roten eksponerer én L:-prefikset plassholder per endepunkt (L:music, L:podcast, L:filter:…); hvert nivå beregnes bare når en klient blar inn i det (LazyBrowse → EnsureLazyEndpointInMemory → hurtigbuffere per nivå), og bibliotekendringsvarsler tømmer hurtigbufferne (SetLibraryDirty).
Hvorfor: kaldstart er i hovedsak øyeblikkelig – HTTP-porten er åpen når MusicBee er ferdig med plugin-initialisering – og minnet forblir proporsjonalt med det som er blitt bladd gjennom, ikke med bibliotekstørrelsen. Avveining: den første bla-operasjonen inn i et endepunkt betaler sin lastkostnad; gjeninntreden er hurtigbufret til neste bibliotekendring. Dette er grunnlaget alt annet avhenger av. Fullstendige notater: FIXES.md.
Nettverk og robusthet
Forbedring av HTTP-serverens bindingsbane. Den originale plugin-modulen dør stille når porten er utilgjengelig.
N04 – Selvreparerende HTTP-portbinding
Hva: plugin-modulens HTTP-server dør ikke lenger når den konfigurerte porten er utilgjengelig. Tre sammenkoblede endringer:
- Automatisk tilbakefall ved bindingsfeil.
HttpServer.Startprøver den konfigurerte porten, og vedSocketExceptionskanner den oppover opptil 20 porter etter den første ledige. Den faktisk bundne porten registreres i en nyPlugin.boundServerPort, og alt som annonserer serveren – SSDPLOCATION-URL-er (NOTIFY + M-SEARCH-svar), enhets-URL-en (PrimaryHostUrl), ruterens portvideresending, og SSDP/kontrollpunkt-selvfiltrene – leser nåboundServerPorti stedet forSettings.ServerPort. UPnP-klienter oppdager den virkelige porten via SSDP, så en flyttet port er transparent for mottakere. - Brukervarsling. Når et tilbakefall skjer (den lagrede porten er ikke den som er i bruk), forteller en lokalisert
MessageBox(WarnPortInUse) brukeren hvilken port som faktisk serverer og at enheter fortsatt vil finne den – fordi plugin-modulen kjører hodeløst og en melding i dialogboksen ville bare blitt sett av noen som allerede mistenkte et problem. - Omstartsgjenoppretting.
RestartServer(innstillingslagrings-omstartsbanen) pleide å derefererePlugin.controller/Plugin.serverblindt. Hvis den førsteInitialisekastet en feil før de ble opprettet (nøyaktig hva en mislykket binding forårsaket), ville neste innstillingslagring treffe enNullReferenceException– og etterlate en halvdød plugin-modul. Den gjenskaper-og-starter dem nå nårNothing, slik at lagring av en fungerende port gjenoppliver plugin-modulen uten en full MusicBee-omstart.
Hvorfor: utløseren var en reell brukerhendelse. Den gamle standardporten 49382 ligger i Windows' dynamiske område (49152-65535), hvor Hyper-V/WSL2/Docker/WinNAT reserverer store blokker som skifter ved hver oppstart – så bindingen mislyktes med WSAEACCES ("tilgang nektet") på en maskin der den hadde fungert i måneder. Endring av standardporten til en ledig port kolliderte deretter med Serviio (en separat DLNA-server som allerede var på den nye porten), og mislyktes med WSAEADDRINUSE. Hver feil ble svelget i Initialise, noe som etterlot plugin-modulen stille død og deretter NRE-ing ved neste innstillingslagring. Etter N04 selvreparerer en portkollisjon seg – serveren fortsetter å kjøre på neste ledige port, brukeren blir informert, og klienter gjenoppdager den – i stedet for å ta ned hele plugin-modulen.
Implementering:
- Standardport flyttet
49382→9779(under det dynamiske området, så Windows reserverer den aldri automatisk; ikke en kjent standard for medieservere) i alle treServerPort-deklarasjonene + tilbakefallet ved innstillingsanalysefeil. Plugin.boundServerPort(nytt delt felt) holder den aktive lytteporten;activeServerPortforblir det konfigurerte øyeblikksbildet slik at "Omstart påkrevd"-merkelogikken ikke utløses feilaktig ved et tilbakefall.HttpServer.PortScanRange = 20; skanningen stopper ved den første vellykkedeTcpListener.Start()og kaster den siste unntaket bare hvis alle forsøk mislykkes.- Ny EN ressursnøkkel
WarnPortInUse(oversettelser følger lokaliseringspasset ved publisering).
N05 – SSDP-kunngjøringer over multikastgruppen (VPN / punkt-til-punkt)
Hva: SSDP-kunngjøringer sendes til UPnP-multikastgruppen (239.255.255.250) i stedet for en IP-kringkastingsadresse. Den ufarlige "kan ikke få tilgang til et frigjort objekt"-feilen som logges når et SSDP-søkerespons konkurrerer med en serveromstart, undertrykkes også.
Hvorfor: på punkt-til-punkt / VPN-nettverksadaptere gjelder ikke IP-kringkasting – den gamle kringkastingssendingen mislyktes med "ugyldig argument" og kunngjøringer ble savnet, så plugin-modulen var usynlig for klienter på disse koblingene. Kunngjøring til riktig multikastgruppe fikser oppdagelse på akkurat disse adapterne.
Biblioteknavigasjon
Disse ble levert i denne forken og er ikke i den originale plugin-modulen. De kom fra faktisk å bla gjennom plugin-modulens egen utdata fra ekte UPnP-klienter.
N06 – Filterbasert bibliotekeksponering
Hva: MusicBees filterfaner (.xautopf-filer i brukerens MusicBee-mappe) blir UPnP-rotbeholdere i plugin-modulens bibliotek. Hvert filters spor kan deretter bladd gjennom i et hierarki av AlbumArtistSort → Album → Spor.
Hvorfor: brukere med kuraterte MusicBee-filtre (f.eks. "5-stjerners spor", "Nylig lagt til", "Klassisk → Barokk") forventer å finne dem når de blar gjennom plugin-modulen fra en UPnP-klient. Original plugin-modul eksponerte bare det rå bibliotektreet.
N07 – SortAlbumArtist-feltkobling
Hva: plugin-modulen leser nå MusicBees MetaDataType 165 (Sorter albumartist) og bruker det til å gruppere/sortere artister i bla-visninger.
Hvorfor: hi-fi-nettlesere og audiofile bruker sorteringsartistnavn ("Beethoven, Ludwig van" i stedet for "Ludwig van Beethoven") for å organisere biblioteker. Standard forventning for seriøse lyttere. Mangler fra begge oppstrøms.
N08 – Håndtering av flerverdi AlbumArtist
Hva: når et albums AlbumArtist-felt inneholder flere artister adskilt av "; " (f.eks. "yaiol; Ars Ricercata"), vises sporet nå under hver artist i bla-visninger, ikke under en enkelt Frankenstein-artist som kombinerer navnene.
Hvorfor: samarbeidsalbum og samlealbum må vises under hver samarbeidspartner. Uten dette er halvparten av søkebanene for å finne albumet ødelagt.
N09 – Albumbeholder-kunstverk (upnp:albumArtURI)
Hva: albumbeholder-noder i DIDL Browse-svar inkluderer nå et upnp:albumArtURI-element som peker på albumomslaget.
Hvorfor: uten dette viser hvert album i en UPnP-klientens bla-visning et generisk ikon i stedet for albumomslaget. Visuelt signal for navigasjon; forventet av hver moderne hi-fi-nettleser.
N10 – Sporrekkefølge i filteralbum
Hva: spor inne i et filtereksponert album sorteres nå etter platenummer, deretter spornummer.
Hvorfor: standard albumrekkefølge. Uten eksplisitt sortering kom spor tilbake i den rekkefølgen filteret tilfeldigvis returnerte dem – vanligvis tilfeldig utseende.
N11 – Feilretting for spillelistemappe-tre
Hva: LoadLibraryPlaylists-funksjonen (opprinnelig av Steven Mayall, ~2014) klarte ikke å gå ned i nyopprettede spillelistemapper. Den første spillelisten i hver mappe, pluss eventuelle undermapper, endte opp som foreldreløse på rotnivå.
Hvorfor: til stede i den originale plugin-modulen i elleve år. Synlig innen 30 sekunder etter å ha åpnet BubbleUPnP og klikket på Spillelister. Fikset i yaiol ved å korrekt rekursere inn i nyopprettede mapper under trekonstruksjon.
N12 – Sanitering av XML-ulovlige kontrolltegn
Hva: ethvert spor med en tagg som inneholder et C0-kontrolltegn (f.eks. 0x19 fra en dårlig koding – UTF-8 → Latin-1 → tilbake trunkering av 0x99 til 0x19) førte til at hele Browse-svaret mislyktes med Action Failed når det dårlige sporet kom inn i en paginert batch.
Hvorfor: XML 1.0 forbyr de fleste C0-kontrolltegn, og XmlWriter kaster en feil når den blir bedt om å skrive noen. Til stede i den originale plugin-modulen. Fikset ved å fjerne ugyldige tegn ved hvert Library_GetFileTags-utgangspunkt via XmlConvert.IsXmlChar.
N13 – Radioliste deterministisk over paginert Bla
Hva: Bla for Radio-beholderen falt inn i den generiske filliste-grenen, som kalte files.Sort(AlbumFileComparer) ved hvert kall. Radiooppføringer har tomme Album/Disc/Track-tagger, så hver sammenligning returnerte 0 – List(Of T).Sort er ustabil, og produserer en annen rekkefølge ved hver påkalling. UPnP-kontrollpunkter paginerer (BubbleUPnP henter 0..15 deretter 16..slutt); mellom de to kallene ble listen omorganisert, slik at noen stasjoner dukket opp på begge sidene (duplikater) og noen på ingen (manglende) – og så tilfeldig ut ved hver oppdatering.
Hvorfor: til stede i den originale plugin-modulen (dens forfatter blar aldri radio via UPnP). Fikset her med en dedikert ContainerCategory.Radio-gren i Browse, ingen sortering per kall; radioFiles sorteres én gang ved lasting etter Tittel (stabil). Paginert bla ser nå en deterministisk rekkefølge; side 1 og side 2 er disjunkte.
N14 – UPnP-søk albumklasse returnerer albumbeholdere
Hva: UPnP-søk for albumklasse-spørringer (upnp:class = "object.container.album.musicAlbum", f.eks. BubbleUPnPs "Tilfeldige album") returnerte hele sporlisten i stedet for albumbeholdere, så klienten viste null album. Den originale håndtereren analyserte bare parentesiserte kriterier, og dumpet deretter alle spor uavhengig av den forespurte klassen.
Hvorfor: fikset her – albumklasse-spørringer enumererer nå distinkte album (gruppert etter AlbumArtist+Album) og sender ut hvert som en riktig musicAlbum-beholder med omslagskunst, adresserbar via Salb<idx> virtuell-ID-plass slik at klienten kan drille inn i et resultat og spille det av.
N15 – Fungerende, omfang-bevisst UPnP-søk med klikk-gjennom
Hva: originalen annonserte ingen søkefunksjoner (GetSearchCapabilities returnerte tom), så klienter nektet å sende et søk; og den gamle backend leste fra musicFiles, permanent tom i den late-tre-æraen. Denne forken annonserer de virkelige søkbare egenskapene, implementerer spor-etter-tittel og album-etter-tittel mot det late biblioteket (HandleLazySearch), omfanget spørringen til klientens nåværende gren når en ekte container-ID sendes (ellers erstatter L:music slik at topplinjesøk ikke drar inn podcast/radio/lydbokstøy), og gjør albumresultater klikkbare via syntetiske Ssrch_alb_*-ID-er som en Browse tidlig-gren mapper tilbake til albumets spor. (Albumklasse-resultater-som-beholdere-delen er N14.)
Hvorfor: søk i BubbleUPnP gikk fra "Biblioteket støtter ikke søk" til å returnere nyttige, omfangsbestemte, spillbare resultater. Full design + avviste tilnærminger: SEARCH.md.
N16 – UPnP-hurtigbufferinvalidering (SystemUpdateID)
Hva: originalen returnerte en konstant SystemUpdateID=0 – UPnP ContentDirectory-hurtigbufferinvalideringskontrakten – så spesifikasjonskompatible klienter (BubbleUPnP) behandlet biblioteket som uforanderlig: utdaterte bla-resultater, 404-miniatyrbilder etter en URL-skjemaendring, og "start MusicBee to ganger for å se endringer"-dansen. Denne forken sår SystemUpdateID fra epoke-sekunder ved lasting (så hver omstart er strengt tatt foran den forrige) og øker den ved hver bibliotekmutasjon og innstillingsendring (SetLibraryDirty / ResetCache → BumpSystemUpdateId).
Hvorfor: klienter plukker pålitelig opp redigeringer, nye filer og innstillingsendringer ved neste bla. Kjent begrensning: abonnerte klienter blir ikke aktivt presset den nye verdien via GENA (parkert som fremtidig arbeid); de ser den fortsatt ved neste bla.
N17 – Podcastabonnement-kunstverk
Hva: podcastfliser viste ingen bilder – hver /PodcastThumbnail/-forespørsel returnerte 404. To stablede feil: oppløsningskjeden sjekket aldri MusicBees faktiske kunstverk-hurtigbuffer (%LocalAppData%\MusicBee\InternalCache\Subscriptions\<name>.jpg, der skrivebordsgrensesnittet laster fra), og HTTP-lagets unescape+lowercase ødela feed-URL-rutnøkkelen ned til dens siste banesegment. Denne forken løser kunstverk fra MBs InternalCache og ruter oppslag via en URL-sikker slug som overlever HTTP-laget intakt (PodcastSlug / podcastSubIdBySlug).
Hvorfor: abonnement-kunstverk gjengis nå i bla-visninger (alle 22 tidligere 404-forespørsler løses).
N18 – Hierarkisk (avgrenset) tagg-blaing
Hva: ethvert felt kan merkes som hierarkisk på Bibliotekalternativer-fanen og gis en ett-tegns avgrenser (en feltvelger + avgrenserboks med legg til/fjern, lagret i plugin-innstillingene). Sett Gruppering til / og en verdi som Jazz/Cool Jazz blar deretter som Jazz › Cool Jazz i stedet for en flat oppføring. Spor tagget nøyaktig ved en gren (bare Jazz) får sin egen [Jazz]-node slik at ingenting er skjult, en gren med et enkelt barn kollapser av seg selv, og ; nektes som avgrenser fordi det er MusicBees egen flerverdi-separator.
Hvorfor: dype tagg-taksonomier en bruker allerede har kodet i et enkelt felt (sjanger-trær, stemningshierarkier, "Klassisk/Barokk/Konsert") blar endelig som treet taggen beskriver, i stedet for en flat vegg av skråstrek-separerte strenger brukeren må lese fra ende til annen.
N19 – Enkelt rotbane merket med sitt grupperingsfelt
Hva: en enkelt bla-bane ved roten er merket med sitt grupperingsfelt (f.eks. "Sjanger") i stedet for sin fulle korte bane, som samsvarer med hvordan sammenslåtte førstefeltgrupper navngis.
Hvorfor: bla-treet leses konsekvent – én navngivningsregel enten en rotpost står alene eller ble slått sammen med søsken (N20) – i stedet for en enslig rotpost som viser en detaljert intern bane mens dens sammenslåtte naboer viser et rent feltnavn.
N20 – Slå sammen bla-baner som deler et første felt
Hva: to bla-baner som deler det samme første feltet – "Sjanger / Sorter albumartist" og "Sjanger / Podcastpersoner" – kollapser til en enkelt Sjanger-rotmappe som først lister opp sjangerverdiene og deretter deler seg inn i de to visningene, i stedet for to nesten-dupliserte "Sjanger / …"-oppføringer side om side ved roten.
Hvorfor: en bruker med flere relaterte visninger nestet under et felles felt så roten rotete med nesten identiske toppnivåoppføringer. Sammenslåing av dem holder roten lesbar og grupperer de relaterte visningene der de hører hjemme – under deres delte felt.
N21 – Kategoritypede bla-baner (Standard / Radio / Podcast)
Hva: hver bla-bane er typet etter kategori – Standard, Radio eller Podcast. Mal-listen er gruppert i disse tre seksjonene, hver mals feltvelger tilbyr bare feltene som kategoriens data faktisk kan levere, og en mal kan bare brukes på matchende noder i visningstreet (inkompatible noder blir grået ut og kan ikke velges). De reserverte Radio- og Podcast-malene kan ikke slettes, så deres kategoriseksjon forsvinner aldri.
Hvorfor: uten typingen kunne en bruker bygge et oppsett som stille kom opp tomt – en radiostasjon har ingen "album", en podcastepisode har ingen "albumartist" – og bare oppdage det ved å bla til en død mappe fra en UPnP-klient. Å begrense feltmenyen og anvendelsesmålene til kategoriens virkelige data gjør tomme oppsett umulige å bygge.
N22 – Grupper podcaster etter publiseringsår
Hva: hver podcastepisodes publiseringsdato leses inn, slik at en podcast-bla-bane med et År-nivå bøtter episoder etter år i stedet for å kollapse dem under en enkelt "Ukjent".
Hvorfor: store podcastabonnementer blir navigerbare etter år som resten av biblioteket, i stedet for at hver episode lander i en udaterte haug fordi plugin-modulen aldri så på publiseringsdatoen per episode.
N23 – Kollaps enkeltresultat-grupperingsnivåer
Hva: et grupperingsnivå som løses til en enkelt verdi – et Opptakstype-nivå som bare viser "LP" for en artist som bare laget LP-er, eller et bokstavnivå med en enkelt bokstav – hoppes over automatisk, og slipper brukeren rett inn i innholdet.
Hvorfor: å bla gjennom en mappe som inneholder nøyaktig én mappe er ren friksjon. Å kollapse enkeltvalgsnivået fjerner det døde klikket uten å endre hva brukeren kan nå.
N24 – Årsgruppering/søk mot MusicBees datofelt
Hva: årsvilkåret spør ikke lenger MusicBees full-dato "År"-felt med en bar firesifret verdi, og den hardkodede år-felt-aliasingen er borte slik at hvert grupperingsfelt nå løses generisk fra banedefinisjonen.
Hvorfor: for biblioteker der År-taggen inneholder en komplett dato, returnerte gruppering eller søk etter år tidligere ingenting – den firesifrede spørringen matchet aldri full-dato-feltet. Spørring av riktig felt gjør at årsgruppering og søk finner sporene igjen.
N25 – Separate "År" og "År (åååå)" grupperingsfelt
Hva: albumgruppering og bla-baner eksponerer nå begge MusicBees egne årsfelt – År (hele dato-taggen) og År (åååå) (bare det firesifrede året) – slik at brukeren kan velge enten når de definerer en albumgruppering eller en bla-bane.
Hvorfor: de to feltene betyr forskjellige ting i MusicBee, og å slå dem sammen mistet den distinksjonen. Å vise begge lar en bruker samle alle utgivelser fra et år sammen (åååå) eller beholde eksakt-dato-rekkefølge (full År-tagg), som de ønsker.
N32 - Festede filtre og spillelister gruppert etter type i roten
Hva: et festet filter vises nå direkte under Filtre-mappen i rotmappen, og en festet spilleliste direkte under Spillelister-mappen, i stedet for at alle festede elementer samles i én klump nederst i roten. Hver festet snarvei står sammen med sin egen type.
Hvorfor: etter hvert som du fester flere snarveier, blir en enkelt klump av blandede filtre og spillelister på slutten vanskeligere å skanne, og den skiller hver snarvei fra mappen den tilhører. Å gruppere festede elementer under sin egen kategori holder roten lesbar og hver snarvei ved siden av det den hører sammen med.
Innstillingsdialog og pakking
N26 – Seksjonert innstillingsdialog
Hva: Innstillinger-siden fikk et venstre-navigasjonslayout med seksjoner: Generelt / Avspilling / Bibliotek / Enhetsprofiler / Diagnostikk.
Hvorfor: originalen var en enkelt høy, flat liste over alle innstillinger – greit for utvikleren som bygde den, forvirrende for alle andre. Seksjonering grupperer relaterte alternativer og får dialogen til å føles mer som moderne appinnstillinger.
Assembly + plugin-navneendring (ingen F-ID – pakkenotat)
Hva: den kompilerte DLL-en heter mb_UPnP_yaiol.dll og plugin-modulen rapporterer seg selv som "MusicBee UPnP (yaiol)". Forskjellig fra den originale mb_Upnp.dll.
Hvorfor: brukere kan installere yaiol sammen med den originale plugin-modulen og sammenligne atferd side om side.
Merkesystem – viser kjøretidsstatus (mekanisme bak F40)
Hva: et generisk UI-mønster for å vise viktige kjøretidsforhold som synlige fargede merker i Innstillinger-dialogen. Nåværende forekomster:
- ⚠ Maks tilkoblinger (N04) – utløses når grensen for maksimale tilkoblinger ble nådd minst én gang siden MusicBee startet. Klebrig sesjonsflagg
Plugin.MaxConnectionsHit. Satt inne iWaitOnSendBarriernår ingen plass er ledig. - ⚠ Omstart påkrevd – utløses når en lagret innstilling krever en MusicBee-omstart for å tre i kraft. Klebrig sesjonsflagg
Plugin.RestartRequired. Satt i dialogens Lagre-håndterer når den nye vedvarende verdien avviker fra kjøretidsøyeblikksbildet (Plugin.activeMaxConnections,Plugin.activeServerPort,Plugin.activeIpAddress). Innstillinger som krever omstart er begrenset til de som genuint ikke kan varm-lastes – HTTP-serverbindingsparametere og SemaphoreSlim bygget én gang ved Initialise.
Hvorfor: plugin-modulens loggfil er fin for tekniske brukere som feilsøker, men en ikke-teknisk bruker som stirrer på "enheten høres feil ut" eller "avspillingen er treg" vil aldri åpne Diagnostikk → Vis logg. Merker fanger opp tilfellene der brukeren trenger å vite at noe skjedde og viser det neste gang de åpner plugin-modulen – oppdagbart uten å lese noe.
Gjenbrukbar for fremtiden:
- Profilavvik oppdaget (enhetens brukeragent matchet aldri noen profil, falt tilbake til Generisk).
- NextURI-tilbakekobling utløst (F13 – gapless deaktivert for sesjonen på en ustabil enhet).
- Bibliotekskanning mislyktes / delvis.
- Mottakerforbindelse tapt midt i sesjonen.
- Enhver annen tilstand der "skjedde én gang, brukeren bør vite" slår "logget stille blant 1000 andre linjer".
Implementeringskonvensjoner:
- Merkelapper lever på dialognivå (ikke inne i noe panel) slik at de er synlige uavhengig av hvilken seksjon brukeren er på.
- Plassert langs nederste rad nær Lagre/Avbryt (nåværende: y=410 horisontalt stablet).
- Hvert merke har et tilsvarende klebrig sesjonsflagg i
Pluginsom blir Sann når tilstanden oppstår og nullstilles bare ved MusicBee-omstart. - Ressurser:
<Tilstand>Merke(etiketttekst, prefiks med ⚠) +<Tilstand>Merketips(verktøytips som forklarer årsak + løsning). - For "lagret innstilling krever omstart"-merker, ta et kjøretidsøyeblikksbilde ved
Plugin.Initialise()og sammenlign medSettings.*etterSettings.SaveSettings()i dialogens Lagre-håndterer.
N27 – Avbryt forkaster bane-/malredigeringer
Hva: redigeringer gjort på baner og maler inne i innstillingsdialogen forkastes nå når brukeren klikker Avbryt, i stedet for å stille forbli anvendt, og eventuelle reserverte maler som ble fjernet under sesjonen, gjenskapes. (Maler lagres ellers direkte mens de redigeres – det er ingen egen Lagre-knapp på Baner-fanen.)
Hvorfor: Avbryt skal bety avbryt. Tidligere fant en bruker som eksperimenterte med bane-/malendringer og trakk seg, at endringene allerede var forpliktet, uten mulighet til å angre dem annet enn å gjøre hver enkelt manuelt.
N28 – Bokstavelige ampersander i feltvelger-menyen
Hva: et felt hvis navn inneholder "&" – f.eks. "Stemning & Kontekst" – gjengir ampersanden bokstavelig i feltvelger-menyen i stedet for å svelge den som et Alt-mnemonisk prefiks.
Hvorfor: feltnavn med en ampersand ble vist feil (tegnet forsvant og neste bokstav ble en akselerator), noe som gjorde menyoppføringen vanskelig å gjenkjenne.
N29 – Stabil, uoversatt innstillingsvindutittel
Hva: innstillingsvindutittelen er fastsatt til merkevarestrengen "MusicBee UPnP Plugin" og varierer ikke lenger med grensesnittspråket; den språkspesifikke DialogTitle-strengen ble fjernet fra hver lokaliseringspakke.
Hvorfor: en vindutittel som endret ordlyd per språk var en oversettbar overflate uten fordel – tittelen er et varemerke. Å feste den holder den stabil og konsekvent overalt.
Lokalisering
Den originale plugin-modulen er kun på engelsk. Denne forken er fullt lokaliserbar – hver brukerrettede streng flyter gjennom en ressursbunke, og plugin-modulen oppdager automatisk MusicBees eget UI-språk.
N30 – Flerspråklig UI (oversettelser venter)
Hva: lokaliseringsmaskineriet er komplett og sendes. Localisation.vb leser MusicBees valgte språk fra MusicBee3Settings.ini (<SystemLanguage> endonym) og bruker den matchende .NET-kulturen på tråden, slik at My.Resources.Resources.* returnerer den lokaliserte strengen. Hver brukerrettede etikett/knapp/melding er koblet til en ressursnøkkel (designer-kontroller via ApplyDesignerExtras + sync-en-locale.js; kjøretidsstrenger som WarnPortInUse er manuelt lagt til). Det som ikke er gjort ennå er selve oversettelsen: bare den engelske kildebunten (Resources.resx) eksisterer – satellittbuntene for de andre språkene produseres i én batch-pass når plugin-modulen er funksjonskomplett (å oversette stykkevis mens strenger fortsatt endres, er bortkastet innsats).
Målspråk (settet MusicBee selv tilbyr, matchet 1:1 av endonymToCulture slik at plugin-modulen følger MusicBees språk automatisk):
Arabic (ar) |
Czech (cs) |
Deutsch (de) |
Greek (el) |
Español (es) |
Français (fr) |
Hungarian (hu) |
Italiano (it) |
Korean (ko) |
Nederlands (nl) |
Norsk (nb) |
Polski (pl) |
Português BR (pt-BR) |
Português PT (pt-PT) |
Svenska (sv) |
Turkish (tr) |
Ukrainian (uk) |
Русский (ru) |
日本語 (ja) |
简体中文 (zh-CN) |
繁体中文 (zh-TW) |
English (en, source) |
Variantpolicy (per arbeidsområdets lokaleregel): PT og ZH er delt inn i distinkte pakker fordi vokabular/skript genuint avviker (pt-BR/pt-PT, zh-CN/zh-TW). EN er en enkelt pakke – MusicBees "English(US)" (en-US) faller tilbake til en via .NETs kulturkjede, så ingen separat amerikansk pakke produseres. ES og FR er likeledes enkeltlokale.
Hvorfor: innstillingene til en UPnP-plugin-modul ("ikke bruk rå PCM", "tving little-endian PCM", port-tilbakefallsvarsler) er kryptiske nok på ens morsmål. Å følge MusicBees eget UI-språk – i stedet for å tvinge engelsk – er forskjellen mellom et verktøy en ikke-engelsk bruker kan konfigurere og et de ikke kan.
N31 – Hjelpelink åpnes i fullt grensesnittspråk
Hva: å åpne hjelpelinken fra plugin-modulen respekterer brukerens komplette grensesnittspråk (f.eks. pt-BR, zh-CN) i stedet for å kollapse til grunnleggende språk, og sender en klarere oppdateringskontroll-identifikator.
Hvorfor: en bruker som kjører MusicBee i en regional variant (brasiliansk portugisisk, forenklet kinesisk) ble sendt til hjelpesiden på grunnleggende språk. Å bære den fulle kulturen lander dem på hjelpesiden i nøyaktig det språket de bruker.
Feilrettinger og forbedringer i den originale plugin-modulen
Kjerneprotokoll og avspilling
F01 – Oppdaterte standard DLNA-enhetsprofiler
Hva: leverer ferske standardprofiler for PlayStation 4, Xbox 360/One og moderne BubbleUPnP, med kapasitetsflagg (samplingsfrekvenser, bitdybder, kodeker) som gjenspeiler hva disse enhetene faktisk støtter i dag.
Hvorfor: den originale plugin-modulens standardinnstillinger ble frosset rundt 2014. PS4/Xbox/BubbleUPnP har siden fått støtte for høyoppløselig lyd. Ut av esken spiller en ny installasjon best-i-klassen på disse enhetene uten at brukeren trenger å røre enhetsprofilinnstillingene.
F02 – Kontroller enheter som annonserer MediaRenderer:3
Hva: plugin-modulen undersøker en mottakers UPnP-tjenestebeskrivelse for å avgjøre om MusicBee kan drive den. Originalen matchet bare urn:schemas-upnp-org:device:MediaRenderer:1. Moderne enheter annonserer :2 eller :3. F02 utvider matchen.
Hvorfor: uten dette vises nylige Sonos / WiiM / Eversolo-enheter rett og slett ikke som mål i MusicBees "Spill til"-enhetsliste – selv om de snakker samme protokoll. En enkelt streng-prefiks match-fiksering låser opp hele den moderne enhetsgenerasjonen.
F03 – "Tving native strøm" per-profil alternativ (standard PÅ)
Hva: når avkrysset, sender plugin-modulen de originale filbytene til enheten med ingen transkoding, ingen DSP, ingen ReplayGain-behandling anvendt. Bare den rå filen brukeren valgte, byte for byte (modulo HTTP-innramming).
Hvorfor: ifølge forumvitnesbyrd er dette den største gevinsten for avspillingskvalitet. Hi-fi-brukere som kjøper dyre mottakere ønsker eksplisitt bit-perfekt utdata; enhver DSP-berøring ødelegger poenget. Standard PÅ fordi de fleste moderne enheter håndterer hvilken som helst kodek brukeren kastet på dem, og ReplayGain/EQ bør være opt-in. Det er per-profil slik at du kan fortsette å transkode for en gammel Xbox mens du sender native til en hi-fi DAC.
F04 – "Tving transkoding" per-profil
Hva: per-profil overstyring som tvinger hver strøm til denne enheten gjennom transkoderen, uavhengig av native-kodekstøtte. Det motsatte av F03 (ForceNativeStream). Gjensidig utelukkende med F03 – UI-en fjerner automatisk avkryssingen fra den andre når en av dem er slått på.
Hvorfor: en enkelt global veksling ville være motstridende med per-profil ForceNativeStream (F03). Virkelig tilfelle: enhet A er en hi-fi DAC som ønsker bit-perfekte native strømmer; enhet B er en gammel AV-mottaker som kveles av FLAC. Med en global veksling må brukeren velge – på bekostning av den andre enheten. Med per-profil får hver enhet det riktige svaret.
Implementering:
StreamingProfile.ForceTranscoding As Boolean = False.- Vedvarende skjema oppgradert til v9. Filer før v9 laster den eldre globale verdien én gang og kopierer den til alle profiler, og bevarer den gamle atferden gjennom oppgraderingen.
- UI: fjernet fra Diagnostikk-panelet, lagt til Enhetsprofiler-seksjonen ved siden av ForceNativeStream. Toveis gjensidig utelukkende håndterere (
CheckedChangedpå hver avmelder den andre før den vippes, for å unngå en uendelig løkke). - Beslutningssted:
Settings.ForceTranscoding→streamingProfile.ForceTranscodingiWriteAudioFileDIDL.
F05 – "Tving little-endian PCM" per-profil
Hva: PCM-strømmer (L16/L24 mime-typer) er big-endian ifølge spesifikasjonen. Noen enheter forventer feilaktig little-endian og spiller av hvit støy når de får riktige big-endian-data. F05 veksler byte-rekkefølgen per-profil.
Hvorfor: uten dette produserer visse enheter en vegg av statisk støy. Symptomet er dramatisk og årsaken usynlig uten kunnskap om PCM-koding – vekslingen gir brukerne en gjett-og-sjekk-løsning.
F06 – "Ikke bruk rå PCM" per-profil
Hva: når enheten hevder den støtter rå PCM, bruker plugin-modulen det. Noen enheter lyver – de aksepterer SOAP-håndtrykket, men forvrenger faktiske rå PCM-data, mens de håndterer PCM pakket i en WAVE-beholder riktig. F06 tvinger PCM-over-Wave uavhengig av hva enheten annonserer.
Hvorfor: spesifikt visse Marantz-modeller – de annonserer rå PCM, men bare WAVE fungerer. Uten dette kommer rå PCM-strømmer ut forvrengt, uten feilmelding å peke på.
F07 – "Innholdslengde" per-profil
Hva: hvilken verdi som skal sendes i HTTP Content-Length-headeren. Fire alternativer:
- Standard – faktisk byte-antall når kjent, utelat når ukjent.
- Ingen – send aldri headeren (kun chunked koding).
- Kun PCM – send kun for rå PCM; utelat for alt annet.
- Fast – send
UInt32.MaxValue - 8192(en markør for "stor ukjent lengde").
Hvorfor: UPnP/DLNA-enheter varierer vilt i hvordan de reagerer på Content-Length. Noen trenger et eksakt tall, noen hater det på strømmer, noen trenger en markør "virkelig stor" verdi for å fortsette bufring. Dette ble senere utvidet fra kun PCM til alle utdataformater fordi de samme problemene dukket opp i transkodede MP3/AAC-strømmer.
F08 – "Ikke tøm NextURI" per-profil
Hva: normalt tømmer plugin-modulen enhetens køede NextURI når køen tømmes (sender SetNextAVTransportURI med en tom URL). Noen enheter (spesielt Denon) tolker en tom NextURI som "stopp alt" og stopper avspillingen umiddelbart. F08 forhindrer plugin-modulen fra å tømme den.
Hvorfor: uten dette opplever Denon-eiere at enheten kutter av midt i sporet når køen tømmes. Med F08 avkrysset, beholder enheten den utdaterte NextURI i minnet (ufarlig – den blir bare overskrevet neste gang noe legges i kø).
F09 – FLAC som transkodingsutdataformat
Hva: nedtrekksmenyen for transkodingsformat i Enhetsprofiler tilbyr nå FLAC sammen med PCM 16/24, MP3, AAC, Ogg. Å velge det ruter BASS-enkoderen gjennom MusicBees standard FLAC-konverteringskommandolinje (samme mekanisme som MP3/AAC/Ogg allerede bruker).
Hvorfor: for enheter som håndterer FLAC godt, men ikke kan dekode kildekodeken (f.eks. en Eversolo som mottar MusicBees WMA-bibliotek konvertert til FLAC), bevarer dette tapsfri kvalitet der MP3/AAC ville kastet bort lyddata. Frigjør N02 (5.1 nedmikskontroll), som ikke kunne adresseres uten et tapsfritt transkodingsalternativ.
Implementering: en-linjes tillegg til Encoder.StartEncodes Select Case Codec-blokk – FLAC slutter seg til MP3/AAC/Ogg i den kommandolinjedrevne grenen. UI-nedtrekksmenyen får "FLAC" som et 6. alternativ. Last/lagre-mapping i SettingsDialog utvides til å gjenkjenne FileCodec.Flac ↔ SelectedIndex = 5. Mime, DLNA-type og kodekfunksjon var allerede koblet i ItemManager.GetMimes / GetDlnaType / GetEncodeFeature fra tidligere arbeid (F21, F26).
Gapless (SetNextAVTransportURI)
F10 – SetNextAVTransportURI / NextURI kjerne
Hva: ekte gapless avspilling. Når enheten annonserer støtte for SetNextAVTransportURI i sin UPnP-tjenestebeskrivelse, forhåndskøer plugin-modulen neste spor på enheten før det nåværende sporet slutter. Enheten overgår internt uten hørbar pause mellom sporene – det du hører på en CD-spiller. Dette er ikke "kontinuerlig strøm"-hacken (som sammenføyer alt til én lang strøm og mister metadata per spor).
Hvorfor: flaggskipet Tier-2-funksjonen. Album innspilt som en kontinuerlig liveopptreden (liveopptak, klassiske satser, DJ-sett) høres feil ut når det er en halv sekunds stillhet mellom sporene. Å løse dette riktig er en flaggskipfunksjon, nå i denne forken.
Merknader: den køede lyden serveres via plugin-modulens HTTP-server ved hjelp av streamHandle=0 (bibliotek-hentemodus), noe som betyr at MusicBees lydmotor ikke er involvert for det køede sporet. Avveining: ReplayGain/DSP/EQ-effekter gjelder ikke for neste spor. Akseptabelt når "tving native strøm" er på (standard).
F11 – "Deaktiver NextURI-støtte" per-profil
Hva: selv om en enhet annonserer SetNextAVTransportURI, tvinger denne avkrysningsboksen plugin-modulen til å ignorere den annonseringen og falle tilbake til avspilling ett spor om gangen.
Hvorfor: noen enheter annonserer NextURI, men har en buggy implementasjon (krasjer, halvoverganger, henger). I stedet for å reversere-ingeniør hver ødelagte enhet, får brukeren en "bare slå den av her"-veksling.
F12 – NextURI-livssyklus på nå-spiller-listen
Hva: når MusicBee utløser NowPlayingListChanged, revurderer plugin-modulen hva som skal køes for gapless overgang. Den spør MusicBee om det nye "neste" sporet via NowPlayingList_GetNextIndex(1) + NowPlayingList_GetListFileUrl, sammenligner med det som er køet på enheten (sporet via det nye nextPlaySourceUrl-feltet), og køer på nytt hvis det endret seg (eller tømmer køen hvis MusicBee sier det ikke er noe neste spor).
Hvorfor: uten F12 fortsatte enheten å spille en utdatert NextURI når brukeren fjernet/omorganiserte det køede sporet. Dette tok historisk sett flere iterasjoner fordi hver liste-mutasjon trenger forskjellig håndtering – vi forenklet ved å stole på NowPlayingList_GetNextIndex (som allerede respekterer blanding og gjenta-alt-omslag), slik at alle varianter kanaliseres gjennom den samme sammenligningen.
Implementering:
- Nytt
nextPlaySourceUrl-felt lagrer MusicBee-bibliotek-URL-en for det som er køet (strømme-URL-en med håndtakssuffiks er ikke sammenlignbar med en bibliotekbane). - Ny
Public Sub RefreshQueuedNextUri()påMediaRendererDevice. Tre utfall: ingen NextURI køet → ingen operasjon; køet samsvarer med ny "neste" → ingen operasjon; køet avviker → kallQueueNextmed den nye URL-en (ellerQueueNext("")for å tømme – som respekterer F08 DoNotClearNextUri). - Koblet i
Plugin.ReceiveNotificationunderNotificationType.NowPlayingListChanged.
F13 – NextURI-feil tilbakekobling
Hva: etter 4 påfølgende SetNextAVTransportURI-feil på samme enhet, deaktiverer plugin-modulen gapless for den enheten til MusicBee starter på nytt.
Hvorfor: hvis en enhet er genuint ødelagt for NextURI (intermitterende SOAP-feil, nettverksfeil), ville plugin-modulen ellers fortsette å prøve på nytt for hvert spor. F13 stopper støyen og faller tilbake til ett-spor-om-gangen stille.
F14 – Gjenta-modus + NextURI-integrasjon
Hva: F14 deler seg i to tilfeller håndtert av F15-overgangsdetektoren i OnAvTransportStatusCheck:
- Gjenta-Alle: MusicBee sender den korrekte "wrap"-URL-en (spor 1 ved slutten av listen) til
Plugin.QueueNextselv. Ingen spesiell plugin-logikk er nødvendig – enheten overgår til den og F15-detektoren kallerPlayer_PlayNextTracksom vanlig, som pakker MusicBees NPL-indeks tilbake til 0. - Gjenta-Én: MusicBee sender den SAMME spor-URL-en til
Plugin.QueueNext. Enheten overgår til den (ny strømhåndtak, samme kilde). F15-detektoren spør nåPlayer_GetRepeat()– hvis det erRepeatMode.One, hopper den overPlayer_PlayNextTrack-kallet slik at MusicBee ikke flytter NPL-indeksen bort fra det gjentakende sporet.
Hvorfor: uten Gjenta-Én-hoppet ville et kall til Player_PlayNextTrack ved gapless overgang flytte MusicBee til neste spor i listen (Gjenta-Én påvirker bare automatisk fremdrift ved slutten av sporet i spillerens UI – Neste spor beveger seg alltid fremover), noe som motsier hva Gjenta-Én betyr.
Advarsel om avspillingsteller: i Gjenta-Én avhenger økningen av avspillingstelleren av at MusicBee 3.7.9563+ merker den gjentatte avspillingen. Eldre MusicBee-versjoner spiller den gapless gjentakelsen riktig, men går glipp av økningen i avspillingstelleren. Dokumentert; ikke blokkerende.
F15 – Sporovergangsdeteksjonstilstandsmaskin
Hva: når enheten internt overgår fra nåværende spor til NextURI, må plugin-modulen merke det og fortelle MusicBee å flytte sin nå-spiller-indeks. Ellers tror MusicBee at den fortsatt er på forrige spor, og avspillingsteller / UI / scrobbling driver ut av synk.
Implementering: spør GetPositionInfo.TrackURI ved hver status-timer-tick. Når den rapporterte URI-en samsvarer med den vi køet via NextURI, kaller vi Player_PlayNextTrack på MusicBee og setter suppressNextSoapCall slik at den resulterende PlayToDevice ikke sender SetAVTransportURI på nytt (noe som ville avbryte den gapless avspillingen).
Hvorfor: uten F15 spiller enheten av neste spor, men MusicBees UI sier at den fortsatt er på forrige. Forvirrende, bryter scrobbling, bryter avspillingsteller-sporing. Sporovergangsdeteksjon krever lang, per-mottaker-iterasjon fordi hvert mottakermerke har sine egne særegenheter i når det rapporterer URI-endringen (noen rapporterer TRANSITIONING først, noen hopper rett til PLAYING med ny URI, noen har en kort STOPPED imellom).
Merknader: vårt første utkast fungerer på BubbleUPnP-mottaker. Kanttilfeller per enhet forblir i B6.
F16 – Pop-ved-gapless-overgang-fiksering
Hva: poppen skjer når kildeformatet (samplingsfrekvens / kanaler / kodek) for det køede sporet avviker fra det nåværende sporet, noe som tvinger enhetens DAC til å låse seg på nytt ved overgangen. F16 legger til en NextUri:FormatChange-diagnostikk som utløses ved køtid når formatene avviker, og navngir begge sider – slik at brukere som hører popp kan korrelere.
Diagnostikken peker også på avbøtningen: kryss av Tving transkoding på enhetsprofilen. Det homogeniserer hvert spor til en enkelt transkodingskodek/samplingsfrekvens/bitdybde, og eliminerer kildeformatforskjellen fullstendig.
Hvorfor utsatt for den faktiske transkode-til-match-fiksen: den strukturelle fiksen (transkode det køede sporet for å matche det spillende sporets format) krever endringer i plugin-modulens HTTP-server URL-skjema – for øyeblikket serverer /encode/{id}0.{ext} den køede filen natively. En fremtidig v2 av F16 ville legge til per-format /encode/{id}0_{rate}_{depth}.{ext}-ruter og koble dem gjennom enkoderen. Det er en større arkitektonisk endring verdt å gjøre hvis en ekte enhet viser poppen etter at ForceTranscoding ikke er tilstrekkelig.
Implementering i dag:
lastSourceUrl-feltet sporer den nåværende avspillende kilde-URL-en.QueueNextleserFilePropertyType.SampleRate/Channels/Kindfor både nåværende og køede spor og loggerNextUri:FormatChangeved avvik.
F17 – Fremdriftslinje-resynkronisering etter søk
Hva: Seek()-funksjonen kalte allerede GetPlayPositionInformation() etter en vellykket Seek SOAP, noe som fikser "ingen resynkronisering i det hele tatt"-tilfellet. F17 lukker den gjenværende opptil 1s-driften forårsaket av UPnPs 1-sekunds RelTime-kvantisering: når enhetens rapporterte posisjon runder til innenfor 1 sekund av brukerens forespurte mål, stoler plugin-modulen nå på brukerens sub-sekund-nøyaktige verdi i stedet for enhetens avkorting. Bare når enheten rapporterer noe dramatisk annerledes (>1s avvik) bruker vi dens verdi (søket landet et annet sted enn spurt, f.eks. snap-to-keyframe på noen kodeker).
Hvorfor: uten dette ville et søk til 2:30.500 forankret mot enhetens "2:30"-rapport fått fremdriftslinjen til å vise ~500ms bak virkeligheten. Etter F17 samsvarer linjen med brukerens intensjon for det vanlige in-track-skrubbetilfellet, og respekterer fortsatt enhetens rapport for snap-to-keyframe-avviket.
F18 – Kontinuerlig strøm / NextURI-sperre
Hva: to sperrer er nå på plass:
- Kjøretid:
QueueNextreturnerer tidligFalsenårSettings.ContinuousOutputer på. Kontinuerlig strøm er sin egen gapless mekanisme (én lang sammenkoblet strøm); å sendeSetNextAVTransportURIpå toppen av det forvirrer enheten om hvorvidt hvert spor er en diskret URI eller en del av den kontinuerlige flyten. - UI: når brukeren krysser av den globale kontinuerlig-strøm-avmerkingsboksen, blir den nåværende viste profilens
forceNativeStreamautomatisk avkrysset. Kontinuerlig strøm transkoder alltid, så force-native er meningsløst i kombinasjon.
Hvorfor: forhindrer brukeren fra å aktivere to motstridende gapless mekanismer samtidig. Uten F18 ville enheten motta både en kontinuerlig strøm-URI OG en NextURI for hvert påfølgende spor, med udefinert atferd avhengig av mottakeren.
F19 – Tomme NextURI-feil ignoreres
Hva: når SetNextAVTransportURI kalles med en tom URL (f.eks. siste spor i listen), returnerer noen enheter en SOAP-feil. F19 svelger disse stille – logget, men ikke propagert som feil.
Hvorfor: "ingen neste spor"-tilstanden er normal, ikke en feil. Å behandle det som fatalt forurenser loggen og (i noen flyter) utløser gjentatte forsøk.
Mime-typer og DLNA-metadata
F20 – MP3 mime → audio/mpeg
Hva: den standardkonforme MP3 mime-typen er audio/mpeg, ikke audio/mp3. Sistnevnte er en vanlig feilbetegnelse de fleste enheter tolererer, men strengere mottakere avviser den.
Hvorfor: fikser stille avspilling på strengere enheter som følger standarden. Yaiol-kodebasen hadde dette allerede riktig; ingen endring nødvendig.
F21 – Mime-type rekkefølge: ikke-x- variant først
Hva: når en enhet annonserer både audio/flac og audio/x-flac, returnerer plugin-modulen den ikke-x--varianten først. Samme for enhver kodek med både standard og eksperimentelle mimes.
Hvorfor: x--prefiks markerer eksperimentelle/uoffisielle mimes. Noen mottakere oppfører seg bedre med standardformen. Liten omorganisering, reell innvirkning.
F22 – Opus mime-type støtte
Hva: gjenkjenner Opus som en strømbar lydkodek; sender audio/opus mime når den serverer Opus-spor.
Hvorfor: Opus er nå vanlig (moderne tale-/musikk-kompromisskodek). Uten F22 ville plugin-modulen nekte å strømme Opus-filer selv til enheter som håndterer dem.
F23 – Monkey Audio (APE) kilde-filstøtte
Hva: gjenkjenner .ape-filer som en gyldig kildekodek for strømming/transkoding.
Hvorfor: APE er et tapsfritt format med en nisje, men lojal brukerbase. Å legge det til koster lite og låser opp biblioteket for disse brukerne.
F24 – AAC / ALAC mime-tilbakefall
Hva: hvis en enhet støtter AAC eller ALAC, men ikke eksplisitt annonserer dem i sin UPnP-tjenestebeskrivelse, tilbyr plugin-modulen dem likevel som et tilbakefall.
Hvorfor: flere enheter som håndterer AAC fint, glemte å liste det i sin kapasitets-XML. Uten F24 vil plugin-modulen ikke engang prøve, og tvinger transkoding. Med F24 prøver plugin-modulen og lar enheten håndtere det natively hvis den kan.
F25 – DLNA typeflagg for native + kodede WAV-strømmer
Hva: DLNA-typeflagget (en profilidentifikator som LPCM, WAVE, MP3) må samsvare med det enheten mottar. F25 sikrer at native strømmer og kodede WAV-strømmer flagges riktig.
Hvorfor: feil DLNA-type fører til at noen enheter nekter avspilling helt eller bruker feil dekoder.
F26 – DLNA-header for FLAC-filer
Hva: FLAC-strømmer får den riktige DLNA-profilidentifikatoren i sine headere.
Hvorfor: uten det, gjenkjenner ikke noen enheter som støtter FLAC strømmen som sådan.
F27 – Bitrate-beregningsfiksering i metadata
Hva: den kontinuerlige strømmens res@bitrate ble beregnet som (sampleRate * channels * bitsPerSample) / 1000 – kbps, avvikende med en faktor på ~125 fra UPnP DIDL-spesifikasjonen som definerer attributtet som bytes per sekund. Deler nå på 8 i stedet for 1000.
Hvorfor: feil bitrate-visning på enheten – kosmetisk på de fleste mottakere, men noen allokerer strømmebuffere fra verdien og hakker på strømmer som ser ~125× mindre ut enn de er. Den ikke-kontinuerlige kilde-filbanen hadde dette allerede riktig ((bitrate_kbps * 1000) \ 8 = bytes/sek); bare den kontinuerlige strømbanen var feil.
F28 – Metadata tidsformatfiksering (Marantz)
Hva: res@duration i DIDL var formatert som H:MM:SS (f.eks. 0:03:42). UPnP DIDL-spesifikasjonen definerer formatet som H+:MM:SS[.F+] – strengt tatt med brøkdeler av sekunder valgfritt, men anbefalt; noen Marantz-enheter behandler den bare formen som ugyldig og lar varighetsvisningen være tom. Nå formatert som H:MM:SS.fff (f.eks. 0:03:42.000).
Hvorfor: visningsproblem spesifikt for et merke; konformt ISO-stilformat med brøkdeler av sekunder fikser det uten å påvirke noen annen enhet. Anvendt på begge DIDL-utslippssteder (kilde-filbane + kodet-strøm-bane i WriteAudioFileDIDL).
Bonusfiksering i samme pass: pv:addedTime og pv:lastPlayedTime brukte hh (12-timers klokke) i sine DateTime-formatstrenger i stedet for HH (24-timers). Ethvert spor lagt til eller spilt mellom 13:00 og 23:59 ville gjengis med feil time (f.eks. 17:42 → "05:42") på enheter som viser feltet. Bruker nå HH.
F29 – Kodet MP3-søkestøtte (CBR)
Hva: transkodede MP3-strømmer annonserer nå DLNA.ORG_OP=11 (både byte- og tids-søk) i stedet for DLNA.ORG_OP=10 (kun byte). Enheter som tidligere nektet tids-søk på transkodede MP3 kan nå drive sin fremdriftslinje/søk-UI normalt.
Hvorfor: MusicBees transkoder produserer konstant-bitrate MP3 ved HighQuality-forhåndsinnstillingen, så byte ↔ tid-mapping er lineær – enheten kan konvertere en tids-søkeforespørsel til et HTTP Range byte-søk selv uten noen enkoder-side-støtte. Annonsering av OP=11 låser opp den UI-en på enheten. Uten F29 ble brukere som søkte i en transkodet MP3 enten ignorert stille eller ble droppet til sporstart.
Implementering: omstrukturert GetEncodeFeature i ItemManager.vb for å bryte den inline If inn i en lesbar If/ElseIf/Else-kjede. MP3 får OP=11 eksplisitt; andre ikke-PCM-kodeker beholder OP=10. Ingen endring for AAC/FLAC/etc. – de ville trenge kodek-spesifikk verifisering av CBR-het som MusicBee ikke garanterer.
F30 – .mpeg-filutvidelse håndteres
Hva: filer med .mpeg (og den enda sjeldnere .mpe)-utvidelsen gjenkjennes nå som FileCodec.Mp3 i GetCodec. Før F30 returnerte de FileCodec.Unknown og ble stille avvist fra biblioteket / ute av stand til å være transkodingskilder.
Hvorfor: gamle MPEG-1 Layer 3-arkiver brukte noen ganger .mpeg i stedet for .mp3 (spesifikasjonen tillater begge). En håndfull filer i et 300k-bibliotek er nok til å føle "MusicBee viser dem, men plugin-modulen gjør det ikke" – forvirrende for brukeren.
Avspillingsatferd
F31 – Radiostrømmer bruker automatisk kontinuerlig modus
Hva: WriteAudioFileDIDL undersøker nå kilde-URL-ens Kind-egenskap via Library_GetFileProperty og behandler enhver fil hvis Kind slutter med "Stream" (MusicBee rapporterer "MP3 Stream", "Internet Stream", osv. for radio) som kontinuerlig uavhengig av den globale Settings.ContinuousOutput-vekslingen. Den kontinuerlige strøm-DIDL-grenen (Tittel: "Kontinuerlig strøm", id="continuousstream", fast PCM/Wave-utdata) brukes; enheten ser en enkelt uendelig-stil strøm.
Hvorfor: radiostrømmer har ingen spor-grenser, ingen fast lengde, ingen søk. Å behandle dem som diskrete filer i DIDL førte til at plugin-modulen annonserte byte-områder og varigheter som ikke eksisterer. Automatisk veksling når MusicBee allerede fortalte oss "dette er en strøm" fjerner en fallgruve brukeren ikke burde måtte tenke på.
Omfang: gjelder bare når MusicBee driver avspilling (musicBeePlayToMode). Bibliotek-hentingsbanen (UPnP-klient som blar) er uendret – radio-URL-er der er sjeldne, og brukerrettet atferd bør ikke endres uten eksplisitt testing.
F32 – Kodek-annonsering tilbakefall
Hva: hvis en enhet ikke annonserer visse kodeker (eller plugin-modulen ikke kan analysere enhetens kapasitets-XML), avviser plugin-modulen ikke strømmen umiddelbart. I stedet prøver den å servere den og lar enheten bestemme.
Hvorfor: mange enheter har ufullstendig eller uleselig kapasitets-XML, men håndterer faktisk kodeken fint. F32 bytter et lite "best-gjetning og prøv" mot et direkte avslag.
F33 – Forbedring av fremdriftslinje-synkronisering
Hva: posisjonen mellom avstemningene er allerede veggklokke-ekstrapolert fra et enkelt anker (currentPlayStartTicks), slik at fremdriftslinjen oppdateres jevnt med sub-sekund hastighet. Den gjenværende jitterkilden var det initiale ankeret for et nystartet spor: den tidligere koden antok position=0 i det øyeblikket status-timeren først merket at tilstanden gikk til Playing, men da kan enheten ha spilt i 100-500ms (ett avstemningsintervall). MusicBees fremdriftslinje ville starte på 0, deretter hoppe fremover når virkeligheten tok igjen.
F33-fiksering: når du overgår til Playing for første gang på et nytt spor (currentPlayStartTimeEstimated=True), kall GetPlayPositionInformation() for å få enhetens faktiske nåværende posisjon, og forankre deretter mot det. UPnP rapporterer bare 1-sekunds oppløsning, så ankeret er fortsatt kvantisert, men det er mye nærmere sannheten enn å anta 0.
Hvorfor: jevnere + mer nøyaktig fremdriftsvisning, spesielt rett etter sporbytte. Ingen vei rundt selve 1-sekunds UPnP-rapporteringsoppløsningen – det er spesifikasjonen.
F34 – Fremdriftslinje-jitter etter sporbytte
Hva: når PlayToDevice kalles for et nytt spor, pleide plugin-modulen å la currentPlayPositionMs og currentPlayStartTicks stå på sine forrige-spor-verdier i ~100ms-vinduet mellom SOAP-Play og den første status-timer-avstemningen som oppdaget den nye Playing-tilstanden. MusicBees fremdriftslinje ville kort vise slutten av forrige spor, deretter hoppe tilbake til 0, deretter klatre. F34 nullstiller begge ved PlayToDevice-inngangen – i det øyeblikket vi vet at et sporbytte skjer, før noe av SOAP-arbeidet.
Hvorfor: visuell feil ved raske hopp-brukstilfeller (manuelt neste eller gapless overgang). Nå returnerer MusicBees første PlayPositionMs-spørring etter Play 0 rent, deretter forbedrer F33s GetPlayPositionInformation den til enhetens faktiske posisjon ved første tilstandsendringstikk.
Implementering: fire linjer øverst i PlayToDevice, sammenkoblet med F33s overgangstid-nøyaktige forankring.
F35 – "Tving transkoding"-feil
Hva: tvungen transkoding kunne fortsatt hoppe over transkoding i visse kombinasjoner. Etter F04 per-profil-omarbeidelsen ble to spesifikke hull forseglet:
- Prioritet med ForceNativeStream. Når begge var Sann (noe som kan skje ved en skjema-migrering eller en delvis innstillingsfil), vinner ForceTranscoding nå direkte (
If streamingProfile.ForceTranscoding Then forceEncode = True ElseIf streamingProfile.ForceNativeStream Then forceEncode = False). UI gjensidig utelukkelse forhindrer brukeren fra å krysse av begge, men kjøretidsvakten håndterer enhver tilstand som ble lastet inkonsekvent fra disk. - bypassTranscodeDecision-logikk. Tidligere:
streamingProfile.ForceNativeStream AndAlso Not Settings.ForceTranscoding. Nå:streamingProfile.ForceNativeStream AndAlso Not streamingProfile.ForceTranscoding– samme prioriteringsregel, men på samme per-profil-omfang.
Hvorfor: "tving" skal bety tving. Hvis brukeren eksplisitt aktiverte ForceTranscoding for enhet, må plugin-modulen aldri stille falle gjennom til native strømming, uavhengig av hvordan andre flagg tilfeldigvis kombineres.
F36 – Mottaker-lukket unntak
Hva: pakket Plugin.ReceiveNotification inn i en toppnivå Try/Catch som logger eventuelle ufanget unntak i stedet for å la det forplante seg tilbake til MusicBees varslingspumpe.
Hvorfor: varsler fra MusicBee (PlayStateChanged, VolumeMuteChanged, osv.) sendes til ControlPointManager som kommuniserer med mottakeren over SOAP. Individuelle kallesteder hadde allerede Try/Catch rundt sine SOAP-kall, men et tilstrekkelig merkelig tidstilfelle (f.eks. mottakeren dør mellom to SOAP-kall i samme varslingshåndterer) kunne fortsatt unnslippe. Toppnivå-wrapperen er det siste sikkerhetsnettet slik at brukeren aldri ser en generisk "TargetInvocationException"-popup fra MusicBee.
Implementering: omdøpte den eksisterende kroppen til ReceiveNotificationInternal og la til en tynn wrapper ReceiveNotification som utfører Try { ReceiveNotificationInternal(...) } Catch { LogError(...) }. Den eksisterende per-metode Try/Catch-infrastrukturen inne i ControlPointManager (rundt hvert PostSoapRequest-kall) forblir – F36 er belte + bukseseler.
F37 – Langt-spor-søk utløser falsk overgang
Hva: søk inne i et langt spor kan produsere en kort Stopped→Playing-syklus på noen mottakere. Uten diskriminering behandler ProcessNewPlayState.Stopped det som naturlig spor-slutt og kaller Player_PlayNextTrack, og flytter MusicBee fremover når brukeren bare ønsket å skrubbe. F37 stempler lastUserInitiatedSeek i Seek() og legger til en 5-sekunders vakt i Stopped-håndtereren (som speiler det eksisterende lastUserInitiatedStop-vinduet).
Hvorfor: stille hopp-til-neste-spor under et søk er en av de feilene ingen kan gjette årsaken til – brukeren tenker "rart, jeg prøvde å skrubbe fremover og nå spiller den neste sang". Fiksen er mekanisk: samme mønster som bruker-stopp-diskrimineringen som allerede er på plass.
F38 – Forbedret søkehåndtering for krasjutsatte kodeker
Hva: BubbleUPnP som krasjet ved MP3-søk var det kanoniske symptomet. Etter revisjon gjør den nåværende yaiol-søkekoden allerede de riktige tingene – native bane håndterer HTTP Range korrekt (206, Content-Range, AcceptRanges), kodet bane annonserer X-AvailableSeekRange og analyserer innkommende timeSeekRange.dlna.org / npt-headere, DLNA.ORG_OP-flagg reflekterer de faktiske strømmekapasitetene (med DisablePcmTimeSeek opt-out for problematiske Platinum-enheter). Brukertestet på nåværende BubbleUPnP 4.6.4: ingen krasjer observert.
Hvorfor: BubbleUPnP MP3-søkekrasjen ble rapportert rundt 2024, og appen har hatt ~16 måneder med fikser siden. F29 (kodet MP3 OP=11) var den nye variabelen som kunne ha re-eksponert den; gjør det ikke, på testede versjoner.
Hvis en krasj returnerer: fikseformen ville være en per-profil "begrenset søk"-veksling som tvinger DLNA.ORG_OP=10 (kun byte) på flaggede kodeker – som speiler hvordan DisablePcmTimeSeek allerede fungerer for PCM. Legg til da, ikke forebyggende.
UI og logging
F39 – "Legg til"-knappen velger den nye profilen
Hva: å klikke "Legg til" i enhetsprofillisten oppretter en ny profil OG velger den automatisk slik at brukeren umiddelbart kan redigere felt. Vår seksjonerte dialog-refaktorering gjør allerede dette – både den direkte Legg til-banen og fra-mal-banen ender med Me.activeStreamingProfiles.SelectedIndex = Me.activeStreamingProfiles.Items.Count - 1. En sjekk bekreftet at vår fork allerede håndterer dette – ingenting å endre.
Hvorfor: liten UX-irritasjon som viste seg å allerede ikke være en irritasjon her.
F40 – Større maks-tilkoblinger + advarselslogg
Hva: plugin-modulens samtidige strømgrense (SemaphoreSlim rundt Sockets_Stream_File / Sockets_Encoder_Start) var hardkodet til 4. F40 gjør den brukerkonfigurerbar på Generelt-innstillingssiden (standard 16, område 1-256), legger til en MaxConnections-logglinje når en forespørsel må vente på en plass, OG viser et rødt ⚠ Maks tilkoblinger-merke nederst til venstre i innstillingsdialogen hvis grensen ble nådd minst én gang siden MusicBee startet.
Hvorfor: når en enhet sender parallelle forespørsler (noen Marantz/Linn under kunstverk-skanninger, BubbleUPnPs metadata-sonderinger sammen med aktiv avspilling), ble ytterligere forespørsler blokkert stille bak semaforen – brukeren så "enheten treg" uten synlig årsak. Logglinjen er bra for teknisk feilsøking, men ikke-tekniske brukere leser aldri logger. Det synlige merket i innstillingsdialogen gjør tilstanden med nådd grense oppdagbar for alle som åpner plugin-modulens preferanser.
Implementering:
- Sentraliserte ventingen i
WaitOnSendBarrier(logTag)iMusicBeeUpnp.vb; begge kallesteder (MediaServerDevice.GetFile,Encoder.StartEncode) bruker den. Settings.MaxConnectionslagret i v8 av innstillingsskjemaet.Plugin.MaxConnectionsHiter et klebrig sesjonsflagg satt inne iWaitOnSendBarrier; nullstilles bare ved MusicBee-omstart.SettingsDialog.maxConnectionsBadgeer en rød fet etikett på(16, 410)som bare vises nårPlugin.MaxConnectionsHiter Sann. Har et verktøytips som forklarer årsak og løsning.- Semaforen initialiseres én gang ved type-lasting, så endring av innstillingen krever en MusicBee-omstart (merket i feltetiketten).
F41 – Logg "koding på grunn av ReplayGain/DSP"
Hva: i stedet for separate "koding for RG" / "koding for DSP" logglinjer, inkluderer den enkelte StreamDecision-linjen fra F42 MB-DSP/EQ, MB-ReplayGain, Profile-DSP/EQ, Profile-ReplayGain som akkumulerte årsaker. Samme diagnostiske verdi, mindre støy.
Hvorfor: brukere ser alle årsakene til at transkoding skjer for et gitt spor på én logglinje, ikke spredt. Se F42 for fullstendige detaljer.
F42 – Logg "mottaker støtter ikke kildekodek"
Hva: la til en StreamDecision-logglinje per spill-til-enhet-spor som sier enten "native CODEC" eller "transkode CODEC→CODEC årsak=…". Årsaksfeltet akkumulerer hver betingelse som utløste transkoding: MB-DSP/EQ, MB-ReplayGain, Profile-DSP/EQ, Profile-ReplayGain, WebFile, VirtualFile, ForceTranscoding(global), SampleRate<min/SampleRate>max, DownmixToStereo, DeviceLacksCodec(X), BandwidthConstrained.
Hvorfor: brukere ble forvirret av uventede CPU-topper på filer de forventet å strømme natively. Én logglinje per spor forteller dem nøyaktig hvilken betingelse som forårsaket transkoding – og hvis feltet viser DeviceLacksCodec(Flac), vet de umiddelbart at enhetens protokollinformasjon var ufullstendig og kanskje ønsker at F32s tilbakefall skal tre i kraft.
Implementering: enkelt akkumulatorstreng bygget trinnvis gjennom beslutningskjeden; logget én gang på slutten. Begrenset av Settings.LogDebugInfo for å unngå loggstøy i produksjon.
F43 – SetNextAVTransport-logg viser kilde-URL
Hva: QueueNext-loggoppføringer inkluderer nå source=<MusicBee library path> sammen med stream=<HTTP streaming URL>. Samme endring anvendt på suksessbanen og feilbanen (QueueNext:Failed).
Hvorfor: når du feilsøker et køet-spor-problem, er strømme-URL-en (/encode/aabbccdd0.flac) ugjennomsiktig alene – samme for hvert spor. Kilde-URL-en er den menneske-grep-bare bibliotekbanen som forteller deg nøyaktig hvilken fil MusicBee prøvde å køe.
F44 – Bedre mime-type feillogging
Hva: to nye loggoppføringer under Aktiver:
Aktiver:MimeUbekreftet– utløses per feilformet oppføring i enhetensGetProtocolInfo-svar, og navngir hvilken oppføring som ikke kunne analyseres (slik at brukeren kan se f.eks. "Marantz returnertehttp-get:*::*for en kodek – kapasiteten er ubekreftet, F32s tilbakefall vil gjette").Aktiver:IngenSinkInfo– utløses én gang hvis enheten ikke returnerte noe<Sink>-element i det hele tatt. Betyr atSupportedMimeTypesforblir Nothing ogIsCodecSupporteddegraderes til "antar at alt fungerer" – nyttig kontekst når senere "enhet nektet strøm"-feil vises.
Hvorfor: før F44 etterlot disse stille kapasitets-gjennomfallene brukere som gjettet hvorfor sporene deres enten ble transkodet mot forventningene eller nektet av enheten. Nå viser et enkelt grep etter Aktiver: om enhetens kapasitetsinformasjon var brukbar.
F45 – Bedre metadata feillogging
Hva: Browse-unntaksloggen i ContentDirectoryService.vb var allerede beriket i tidligere yaiol-arbeid (Alia Vox-feilsesjonen) med ObjectID og stakksporing. F45 utvider den ytterligere med BrowseFlag (metadata vs barn), Filter (hvilke attributter klienten ba om), sortCriteria, og partialResultLength (hvor mange bytes av DIDL ble produsert før feilen – peker på hvor langt inn i batchen det dårlige sporet sitter).
Hvorfor: når noe går galt midt i DIDL, forteller delvis-lengde-verdien deg om feilen var på det første sporet i batchen (delvis=0) eller et stykke inn (delvis=N) – kombinert med batchens startingIndex, kan du identifisere den fornærmende sporindeksen. Filter og BrowseFlag forklarer hvilken type bla klienten ønsket; noen ganger mislykkes et metadata-kun-bla der et barn-bla for samme ID lykkes.
Nettverk
F46 - Automatisk modus annonserer kun på ekte nettverkskort
Hva: i grensesnittmodusen Automatisk annonserte programtillegget seg tidligere (SSDP) på alle operative IPv4-kort. På en maskin som også kjører en VPN-tunnel (NordLynx) eller en virtuell svitsj (Hyper-V / WSL / Docker), ble det samme biblioteket annonsert på hvert av disse kortene også, slik at kontrollpunktet du strømmer fra oppdaget serveren to eller tre ganger og listet biblioteket som duplikater. Automatisk modus beholder nå bare kort som har en ekte IPv4-standardgateway (HasIPv4Gateway) - noe tunnel- og virtuelle svitsjekort ikke har - så de fjernes fra annonseringslisten. En adresse festet av brukeren vinner fortsatt uansett (annonsering kun på det grensesnittet), og hvis ingen kort rapporterer en gateway, faller velgeren tilbake til alle kort, slik at listen over annonserte adresser aldri er tom og programtillegget ikke kan bli usynlig.
Hvorfor: duplikatet skyldes ikke at du «er på VPN» - det skyldes annonsering på LAN-kortet og tunnel-/virtuelt kort samtidig, slik at ett kontrollpunkt ser samme server på to adresser. En forbruker-VPN (NordVPN/NordLynx) tunnelerer bare internettrettet trafikk; DLNA-rendereren bor på LAN-et, og lokal subnett-trafikk går utenom tunnelen, så tunnelkortet når uansett aldri en renderer - å fjerne det fjerner en fantomkopi, aldri en fungerende vei. Gateway-testen er det billige, pålitelige signalet som skiller et ekte LAN/Wi-Fi-kort fra en tunnel eller virtuell svitsj. Utfyller N05 (som fikset hvordan annonseringer sendes på slike lenker - multicast i stedet for broadcast); F46 styrer hvilke kort det i det hele tatt annonseres på.
Kjent begrensning: en mesh- / fjernaksess-VPN (Tailscale, ZeroTier, WireGuard hjem) hvis renderere faktisk bor på andre siden av tunnelen, viser vanligvis et kort uten standardgateway, så Automatisk modus forkaster det også. Disse brukerne fester i stedet VPN-adressen, som har forrang over gateway-filteret.