@@ -2,6 +2,7 @@ import { CommandResult, emptyCommand, response } from './commandTypes';
22import { parseNumberPart , splitUrl } from './commandUtils' ;
33import { getZoneById , sendCommandToZone } from '../../backend/zone/zonemanager' ;
44import { getMediaProvider } from '../../backend/provider/factory' ;
5+ import { toPlaylistCommandUri } from '../../backend/provider/musicAssistant/utils' ;
56import logger from '../../utils/troxorlogger' ;
67import { MediaFolderItem , PlaylistItem } from '../../backend/provider/types' ;
78import { FileType } from '../../backend/zone/loxoneTypes' ;
@@ -632,6 +633,18 @@ export async function audioPlayUrl(url: string): Promise<CommandResult> {
632633 } ;
633634 addPlaylistCandidate ( playlistIdFromQuery ) ;
634635 addPlaylistCandidate ( decodedBasePath ) ;
636+ // LEGACY(current): older client encodes playlist info under /parentpath or /parentid.
637+ for ( let i = 0 ; i < meta . length ; i ++ ) {
638+ const token = meta [ i ] ?. toLowerCase ( ) ;
639+ if ( token === 'parentpath' || token === 'parentid' ) {
640+ const candidate = meta [ i + 1 ] ;
641+ if ( candidate ) {
642+ addPlaylistCandidate ( decodeURIComponent ( candidate ) ) ;
643+ }
644+ i ++ ;
645+ continue ;
646+ }
647+ }
635648
636649 let resolvedPlaylist : PlaylistItem | undefined ;
637650 if ( provider . resolvePlaylist ) {
@@ -757,21 +770,55 @@ export async function audioPlayUrl(url: string): Promise<CommandResult> {
757770
758771 const providerHint =
759772 resolved ?. provider ?? ( decodedUri . includes ( ':' ) ? decodedUri . split ( ':' ) [ 0 ] : undefined ) ?? 'external' ;
760- const sanitizedAudiopath = decodedUri . replace ( / \/ (?: n o ) ? s h u f f l e $ / i, '' ) ;
773+ const sanitizedAudiopath = decodedBasePath . replace ( / \/ (?: n o ) ? s h u f f l e $ / i, '' ) ;
774+ const localTrackMatch = decodedUri . match ( / ^ l i b r a r y : l o c a l : t r a c k : ( [ ^ : ] + ) : / i) ;
775+ const providerFromPath = localTrackMatch ? localTrackMatch [ 1 ] : undefined ;
761776 const trackPayload : Record < string , unknown > = {
762777 id : resolved ?. id ?? decodedUri ,
763778 name : resolved ?. title ?? resolved ?. name ?? decodedUri ,
764779 audiopath : sanitizedAudiopath ,
765780 coverurl : resolved ?. coverurl ?? '' ,
766781 type : resolved ?. type ?? FileType . File ,
767- provider : resolved ?. provider ?? providerHint ,
768- providerInstanceId : resolved ?. providerInstanceId ,
782+ provider : resolved ?. provider ?? providerFromPath ?? providerHint ,
783+ providerInstanceId : resolved ?. providerInstanceId ?? providerFromPath ,
769784 album : resolved ?. album ,
770785 artist : resolved ?. artist ,
771786 title : resolved ?. title ?? resolved ?. name ,
772787 uniqueId : resolved ?. id ?? decodedUri ,
773788 } ;
774789
790+ const playlistCommandUri =
791+ resolvedPlaylist ?. playlistCommandUri ??
792+ playlistContext ?. playlistCommandUri ??
793+ playlistRawCommand ??
794+ playlistIdFromQuery ??
795+ undefined ;
796+ if ( playlistCommandUri ) {
797+ // LEGACY(current): queue UI requires playlist ids even when /playurl kicked off playback.
798+ const normalizedPlaylist = toPlaylistCommandUri ( playlistCommandUri , playlistContext ?. playlistProviderInstanceId , playlistContext ?. rawId ) ;
799+ trackPayload . playlistCommandUri = normalizedPlaylist ;
800+ trackPayload . playlistId = normalizedPlaylist ;
801+ }
802+ if ( playlistContext ?. playlistProviderInstanceId ?? resolvedPlaylist ?. playlistProviderInstanceId ?? resolvedPlaylist ?. providerInstanceId ) {
803+ trackPayload . playlistProviderInstanceId =
804+ resolvedPlaylist ?. playlistProviderInstanceId ??
805+ resolvedPlaylist ?. providerInstanceId ??
806+ playlistContext ?. playlistProviderInstanceId ;
807+ }
808+ if ( playlistContext ?. playlistCover ?? resolvedPlaylist ?. playlistCover ) {
809+ trackPayload . playlistCover = resolvedPlaylist ?. playlistCover ?? playlistContext ?. playlistCover ;
810+ }
811+ if ( playlistContext ?. playlistStartItem ?? resolvedPlaylist ?. playlistStartItem ?? startItemParam ?? originalStartItemParam ) {
812+ trackPayload . playlistStartItem =
813+ resolvedPlaylist ?. playlistStartItem ??
814+ playlistContext ?. playlistStartItem ??
815+ startItemParam ??
816+ originalStartItemParam ;
817+ }
818+ if ( playlistContext ?. playlistName ?? resolvedPlaylist ?. playlistName ) {
819+ trackPayload . playlistName = resolvedPlaylist ?. playlistName ?? playlistContext ?. playlistName ;
820+ }
821+
775822 if ( shuffle !== undefined ) {
776823 trackPayload . shuffle = shuffle ? 1 : 0 ;
777824 }
@@ -834,13 +881,7 @@ function buildEmptyQueue(url: string, zoneId: number): CommandResult {
834881}
835882
836883function ensurePlaylistCommandUri ( value : string ) : string {
837- const trimmed = ( value || '' ) . trim ( ) ;
838- if ( ! trimmed ) return '' ;
839- const lower = trimmed . toLowerCase ( ) ;
840- if ( lower . includes ( '://' ) || lower . startsWith ( 'playlist:' ) ) {
841- return trimmed ;
842- }
843- return `playlist:${ trimmed } ` ;
884+ return toPlaylistCommandUri ( value ) ;
844885}
845886
846887function buildFriendlyPlaylistPath ( rawId : string ) : string {
0 commit comments