[vlc-devel] [PATCH] macosx: Display internal track titles from cue/m3u files in playqueue

Astrom xifengcun at hotmail.com
Sun Jun 1 10:17:11 UTC 2025


From: Astrom Cheng <xifengcun at hotmail.com>

This commit enhances the macOS playqueue UI to properly display track-specific
titles from cue sheets and m3u playlists instead of showing generic file names.

Key changes:
- **VLCPlayQueueTableCellView**: Enhanced title display logic to prioritize
  `inputItem.title` over generic `item.title` when available, with optional
  track number prefixing (format: "Track# · Title")
- **VLCPlayQueueController**: Improved `playQueueUpdatedForIndex` to safely
  replace items using current playlist state rather than potentially stale
  callback data, preventing crashes during rapid updates
- **VLCPlayQueueModel**: Added `replaceItemAtIndex:withItem:` method for
  atomic item replacement in the queue array

This allows users to see meaningful track titles like "03 · Song Name" instead
of just the cue/m3u filename for each track, significantly improving the user
experience when playing cuesheets or structured playlists.

Addresses playlist metadata display issues where individual tracks from
cue sheets and m3u files were showing generic filenames rather than their
embedded track titles and numbers.
---
 .../macosx/playqueue/VLCPlayQueueController.m    | 14 +++++++++++---
 modules/gui/macosx/playqueue/VLCPlayQueueModel.h |  2 +-
 modules/gui/macosx/playqueue/VLCPlayQueueModel.m |  7 ++++++-
 .../macosx/playqueue/VLCPlayQueueTableCellView.m | 16 ++++++++++++++--
 4 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/modules/gui/macosx/playqueue/VLCPlayQueueController.m b/modules/gui/macosx/playqueue/VLCPlayQueueController.m
index 5a96e19922..4c3936132f 100644
--- a/modules/gui/macosx/playqueue/VLCPlayQueueController.m
+++ b/modules/gui/macosx/playqueue/VLCPlayQueueController.m
@@ -337,11 +337,19 @@ - (void)playQueueRemovedItemsAtIndex:(size_t)index count:(size_t)numberOfItems
 
 - (void)playQueueUpdatedForIndex:(size_t)firstUpdatedIndex items:(vlc_playlist_item_t *const *)items count:(size_t)numberOfItems
 {
-    VLC_UNUSED(items);
-    for (size_t i = firstUpdatedIndex; i < firstUpdatedIndex + numberOfItems; i++) {
-        [_playQueueModel updateItemAtIndex:i];
+    vlc_playlist_Lock(_p_playlist);
+    for (size_t i = 0; i < numberOfItems; i++) {
+        size_t replaceIndex = firstUpdatedIndex + i;
+        if (replaceIndex < vlc_playlist_Count(_p_playlist)) {
+            vlc_playlist_item_t *currentItem = vlc_playlist_Get(_p_playlist, replaceIndex);
+            VLCPlayQueueItem *newItem = [[VLCPlayQueueItem alloc] initWithPlaylistItem:currentItem];
+            [_playQueueModel replaceItemAtIndex:replaceIndex withItem:newItem];
+        }
     }
+    vlc_playlist_Unlock(_p_playlist);
+
     [_playQueueDataSource playQueueUpdated];
+
 }
 
 - (void)playQueuePlaybackRepeatUpdated:(enum vlc_playlist_playback_repeat)currentRepeatMode
diff --git a/modules/gui/macosx/playqueue/VLCPlayQueueModel.h b/modules/gui/macosx/playqueue/VLCPlayQueueModel.h
index 4e94aa6ecc..1f5da8e3bf 100644
--- a/modules/gui/macosx/playqueue/VLCPlayQueueModel.h
+++ b/modules/gui/macosx/playqueue/VLCPlayQueueModel.h
@@ -40,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
 - (void)moveItemAtIndex:(size_t)index toTarget:(size_t)target;
 - (void)removeItemsInRange:(NSRange)range;
 - (void)updateItemAtIndex:(size_t)index;
-
+- (void)replaceItemAtIndex:(size_t)index withItem:(VLCPlayQueueItem *)newItem;
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/modules/gui/macosx/playqueue/VLCPlayQueueModel.m b/modules/gui/macosx/playqueue/VLCPlayQueueModel.m
index b596f87511..5430e5c226 100644
--- a/modules/gui/macosx/playqueue/VLCPlayQueueModel.m
+++ b/modules/gui/macosx/playqueue/VLCPlayQueueModel.m
@@ -90,5 +90,10 @@ - (void)updateItemAtIndex:(size_t)index
     VLCPlayQueueItem * const item = _playQueueArray[index];
     [item updateRepresentation];
 }
-
+- (void)replaceItemAtIndex:(size_t)index withItem:(VLCPlayQueueItem *)newItem
+{
+    if (index < _playQueueArray.count) {
+        [_playQueueArray replaceObjectAtIndex:index withObject:newItem];
+    }
+}
 @end
diff --git a/modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m b/modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m
index b97c7e9b62..ef0e69380b 100644
--- a/modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m
+++ b/modules/gui/macosx/playqueue/VLCPlayQueueTableCellView.m
@@ -28,6 +28,7 @@
 #import "extensions/NSString+Helpers.h"
 
 #import "library/VLCLibraryImageCache.h"
+#import "library/VLCInputItem.h"
 
 #import "main/VLCMain.h"
 
@@ -35,6 +36,7 @@
 
 #import "views/VLCImageView.h"
 
+#import <vlc_common.h>
 #import <vlc_configuration.h>
 
 @implementation VLCPlayQueueTableCellView
@@ -91,6 +93,16 @@ - (void)setRepresentedPlayQueueItem:(VLCPlayQueueItem *)item
 
     const BOOL validArtistString = item.artistName && item.artistName.length > 0;
     const BOOL validAlbumString = item.albumName && item.albumName.length > 0;
+    const BOOL validTitleString = item.inputItem && item.inputItem.title && (item.inputItem.title.length > 0);
+
+    NSString *playTitle = item.title;
+    if (validTitleString) {
+        if (item.inputItem.trackNumber && item.inputItem.trackNumber.length >0) {
+            playTitle = [NSString stringWithFormat:@"%@ · %@", item.inputItem.trackNumber, item.inputItem.title];
+        } else {
+            playTitle = item.inputItem.title;
+        }
+    }
 
     NSString *songDetailString = @"";
 
@@ -104,7 +116,7 @@ - (void)setRepresentedPlayQueueItem:(VLCPlayQueueItem *)item
         self.mediaTitleTextField.hidden = YES;
         self.secondaryMediaTitleTextField.hidden = NO;
         self.artistTextField.hidden = NO;
-        self.secondaryMediaTitleTextField.stringValue = item.title;
+        self.secondaryMediaTitleTextField.stringValue = playTitle;
         self.artistTextField.stringValue = songDetailString;
         self.audioMediaTypeIndicator.hidden = NO;
 
@@ -114,7 +126,7 @@ - (void)setRepresentedPlayQueueItem:(VLCPlayQueueItem *)item
         self.mediaTitleTextField.hidden = NO;
         self.secondaryMediaTitleTextField.hidden = YES;
         self.artistTextField.hidden = YES;
-        self.mediaTitleTextField.stringValue = item.title;
+        self.mediaTitleTextField.stringValue = playTitle;
         self.audioMediaTypeIndicator.hidden = YES;
 
         self.audioArtworkImageView.hidden = YES;
-- 
2.39.5 (Apple Git-154)



More information about the vlc-devel mailing list