Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
b3d51b45 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Publicly expose getMediaLibrary
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
d7199341 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Add VLCPlayQueueController methods to create a playlist from current
playqueue items
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
e2a3d9d8 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Add menu item to create a playlist from playqueue
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
5135c687 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Indicate whether media library items are file-backed or not
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
c303f8d7 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Differentiate between file and non-file backed playlists, perform
different trashing procedures
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
4a374d1b by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Update "move to trash" button depending on file-backed state
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
8a088770 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Specify array types in playqueue model
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
45558b1d by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Expose playqueue model's items in readonly array property
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
c7609f22 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Move playlist creation handling to library controller class
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
a64451e0 by Claudio Cambra at 2025-08-28T11:41:46+00:00
macosx: Add main menu entry to create playlist from playqueue
Signed-off-by: Claudio Cambra <develo...@claudiocambra.com>
- - - - -
12 changed files:
- modules/gui/macosx/UI/MainMenu.xib
- modules/gui/macosx/library/VLCLibraryController.h
- modules/gui/macosx/library/VLCLibraryController.m
- modules/gui/macosx/library/VLCLibraryDataTypes.h
- modules/gui/macosx/library/VLCLibraryDataTypes.m
- modules/gui/macosx/library/VLCLibraryMenuController.m
- modules/gui/macosx/menus/VLCMainMenu.h
- modules/gui/macosx/menus/VLCMainMenu.m
- modules/gui/macosx/playqueue/VLCPlayQueueController.m
- modules/gui/macosx/playqueue/VLCPlayQueueMenuController.m
- modules/gui/macosx/playqueue/VLCPlayQueueModel.h
- modules/gui/macosx/playqueue/VLCPlayQueueModel.m
Changes:
=====================================
modules/gui/macosx/UI/MainMenu.xib
=====================================
@@ -111,6 +111,7 @@
<outlet property="rendererNoneItem" destination="eE8-qf-9x9"
id="Ol2-yz-0eF"/>
<outlet property="repeat" destination="5143" id="ulG-wD-gtG"/>
<outlet property="revealInFinder" destination="3945"
id="z7n-A2-K5o"/>
+ <outlet property="savePlayqueueToLibrary"
destination="24V-9x-Aqt" id="fic-89-xZr"/>
<outlet property="save_playlist" destination="1599"
id="spC-pk-6W4"/>
<outlet property="screen" destination="1016" id="VFv-ey-gJR"/>
<outlet property="screenMenu" destination="1015"
id="l5t-0E-DfG"/>
@@ -335,6 +336,12 @@
<action selector="savePlaylist:"
target="-2" id="iHV-3W-w6Z"/>
</connections>
</menuItem>
+ <menuItem title="Save Play Queue to Library..."
keyEquivalent="s" id="24V-9x-Aqt">
+ <modifierMask key="keyEquivalentModifierMask"
option="YES" command="YES"/>
+ <connections>
+ <action selector="savePlayQueueToLibrary:"
target="-2" id="UzJ-9r-vul"/>
+ </connections>
+ </menuItem>
</items>
</menu>
</menuItem>
=====================================
modules/gui/macosx/library/VLCLibraryController.h
=====================================
@@ -27,6 +27,7 @@
@class VLCInputItem;
@class VLCLibraryModel;
@class VLCMediaLibraryMediaItem;
+@class VLCPlayQueueItem;
NS_ASSUME_NONNULL_BEGIN
@@ -48,6 +49,9 @@ NS_ASSUME_NONNULL_BEGIN
- (int)clearHistory;
+- (void)showCreatePlaylistDialogForPlayQueue;
+- (void)showCreatePlaylistDialogForPlayQueueItems:(NSArray<VLCPlayQueueItem *>
*)items;
+
/**
* Sort the entire library representation based on:
* @param sortCriteria the criteria used for sorting
=====================================
modules/gui/macosx/library/VLCLibraryController.m
=====================================
@@ -22,6 +22,8 @@
#import "VLCLibraryController.h"
+#import "extensions/NSString+Helpers.h"
+
#import "main/VLCMain.h"
#import "playqueue/VLCPlayQueueController.h"
@@ -32,6 +34,9 @@
#import "library/VLCLibraryDataTypes.h"
#import "library/VLCMediaLibraryFolderObserver.h"
+#import "playqueue/VLCPlayQueueItem.h"
+#import "playqueue/VLCPlayQueueModel.h"
+
#import <vlc_media_library.h>
typedef int (*folder_action_f)(vlc_medialibrary_t*, const char*);
@@ -213,6 +218,87 @@ typedef int (*folder_action_f)(vlc_medialibrary_t*, const
char*);
return vlc_ml_clear_history(_p_libraryInstance,
VLC_ML_HISTORY_TYPE_GLOBAL);
}
+- (void)showCreatePlaylistDialogForPlayQueue
+{
+ VLCPlayQueueController * const playQueueController =
VLCMain.sharedInstance.playQueueController;
+ NSArray<VLCPlayQueueItem *> * const items =
playQueueController.playQueueModel.playQueueItems;
+ [self showCreatePlaylistDialogForPlayQueueItems:items];
+}
+
+- (void)showCreatePlaylistDialogForPlayQueueItems:(NSArray<VLCPlayQueueItem *>
*)items
+{
+ if (!items || items.count == 0) {
+ return;
+ }
+
+ NSAlert * const alert = [[NSAlert alloc] init];
+ alert.messageText = _NS("Create New Playlist");
+ alert.informativeText = _NS("Enter a name for the new playlist:");
+ [alert addButtonWithTitle:_NS("Create")];
+ [alert addButtonWithTitle:_NS("Cancel")];
+
+ NSTextField * const input = [[NSTextField alloc]
initWithFrame:NSMakeRect(0, 0, 300, 24)];
+ input.placeholderString = _NS("Playlist Name");
+ alert.accessoryView = input;
+
+ alert.window.initialFirstResponder = input;
+
+ const NSModalResponse response = [alert runModal];
+ if (response != NSAlertFirstButtonReturn) {
+ return;
+ }
+
+ NSString * const playlistName = input.stringValue;
+ if (playlistName.length == 0) {
+ return;
+ }
+
+ const BOOL success = [self createPlaylistWithName:playlistName
fromItems:items];
+ if (success) {
+ return;
+ }
+
+ NSAlert * const errorAlert = [[NSAlert alloc] init];
+ errorAlert.messageText = _NS("Failed to Create Playlist");
+ errorAlert.informativeText = _NS("The playlist could not be created.
Please try again.");
+ errorAlert.alertStyle = NSAlertStyleWarning;
+ [errorAlert addButtonWithTitle:_NS("OK")];
+ [errorAlert runModal];
+}
+
+- (BOOL)createPlaylistWithName:(NSString *)playlistName
fromItems:(NSArray<VLCPlayQueueItem *> *)items
+{
+ if (!_p_libraryInstance || !playlistName || playlistName.length == 0) {
+ return NO;
+ }
+
+ vlc_ml_playlist_t * const playlist =
vlc_ml_playlist_create(_p_libraryInstance, playlistName.UTF8String);
+ if (!playlist) {
+ msg_Err(getIntf(), "Failed to create playlist with name: %s",
playlistName.UTF8String);
+ return NO;
+ }
+
+ const int64_t playlistId = playlist->i_id;
+ vlc_ml_playlist_release(playlist);
+
+ for (VLCPlayQueueItem * const item in items) {
+ VLCMediaLibraryMediaItem * const mediaLibraryItem =
item.mediaLibraryItem;
+
+ if (!mediaLibraryItem) {
+ msg_Warn(getIntf(), "No media library item found for playqueue
item with name '%s'", item.title.UTF8String);
+ continue;
+ }
+
+ const int64_t mediaId = mediaLibraryItem.libraryID;
+ const int result = vlc_ml_playlist_append(_p_libraryInstance,
playlistId, &mediaId, 1);
+ if (result != VLC_SUCCESS) {
+ msg_Warn(getIntf(), "Failed to add media library item %lld to
playlist", mediaLibraryItem.libraryID);
+ }
+ }
+
+ return YES;
+}
+
- (void)sortByCriteria:(enum vlc_ml_sorting_criteria_t)sortCriteria
andDescending:(bool)descending
{
_unsorted = NO;
=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.h
=====================================
@@ -40,6 +40,8 @@ extern const CGFloat VLCMediaLibrary720pWidth;
extern const CGFloat VLCMediaLibrary720pHeight;
extern const long long int VLCMediaLibraryMediaItemDurationDenominator;
+vlc_medialibrary_t * _Nullable getMediaLibrary(void);
+
typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType) {
VLCMediaLibraryParentGroupTypeUnknown = VLC_ML_PARENT_UNKNOWN,
VLCMediaLibraryParentGroupTypeAlbum = VLC_ML_PARENT_ALBUM,
@@ -122,6 +124,7 @@ typedef NS_ENUM(NSUInteger, VLCMediaLibraryParentGroupType)
{
@property (readonly) BOOL smallArtworkGenerated;
@property (readonly) NSString *smallArtworkMRL;
@property (readonly) NSString *displayString;
+@property (readonly) BOOL isFileBacked;
@property (readonly) NSString *primaryDetailString;
@property (readonly) NSString *secondaryDetailString;
@property (readonly) NSString *durationString;
=====================================
modules/gui/macosx/library/VLCLibraryDataTypes.m
=====================================
@@ -46,9 +46,9 @@ typedef vlc_ml_album_list_t*
(*library_album_list_fetch_f)(vlc_medialibrary_t*,
typedef vlc_ml_artist_list_t*
(*library_artist_list_fetch_f)(vlc_medialibrary_t*, const
vlc_ml_query_params_t*, int64_t);
typedef int (*library_item_set_favorite_f)(vlc_medialibrary_t*, int64_t, bool);
-static vlc_medialibrary_t *getMediaLibrary(void)
+vlc_medialibrary_t * _Nullable getMediaLibrary(void)
{
- intf_thread_t *p_intf = getIntf();
+ intf_thread_t * const p_intf = getIntf();
if (!p_intf) {
return nil;
}
@@ -319,6 +319,11 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return nil;
}
+- (BOOL)isFileBacked
+{
+ return YES;
+}
+
- (id<VLCMediaLibraryItemProtocol>)primaryActionableDetailLibraryItem
{
[self doesNotRecognizeSelector:_cmd];
@@ -996,13 +1001,63 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
return self.mediaItems.firstObject;
}
-- (void)moveToTrash
+- (BOOL)isFileBacked
{
- NSFileManager * const fileManager = NSFileManager.defaultManager;
+ if (_MRL == nil || _MRL.length == 0) {
+ return NO;
+ }
+
NSURL * const URL = [NSURL URLWithString:_MRL];
- [fileManager trashItemAtURL:URL
- resultingItemURL:nil
- error:nil];
+ if (URL == nil || !URL.isFileURL) {
+ return NO;
+ }
+
+ return [NSFileManager.defaultManager fileExistsAtPath:URL.path];
+}
+
+- (void)moveToTrash
+{
+ // First check if this playlist has a valid file MRL (e.g., .m3u file)
+ if (_MRL != nil && _MRL.length > 0) {
+ NSURL * const URL = [NSURL URLWithString:_MRL];
+ if (URL == nil || !URL.isFileURL) {
+ NSLog(@"Playlist %@ is not file-backed or is a dir (?)",
self.displayString);
+ return;
+ }
+ NSFileManager * const fileManager = NSFileManager.defaultManager;
+ const BOOL fileExists = [fileManager fileExistsAtPath:URL.path];
+
+ if (!fileExists) {
+ NSLog(@"Playlist file does not exist: %@", URL.path);
+ return;
+ }
+
+ // This is a file-based playlist, move the file to trash
+ NSError *error = nil;
+ [fileManager trashItemAtURL:URL
+ resultingItemURL:nil
+ error:&error];
+ if (error) {
+ NSLog(@"Failed to move playlist file to trash: %@", error);
+ } else {
+ NSLog(@"Successfully moved playlist file %@ to trash",
URL.lastPathComponent);
+ return;
+ }
+ }
+
+ // If no valid file MRL or file doesn't exist, delete from media library
+ vlc_medialibrary_t * const p_ml = getMediaLibrary();
+ if (p_ml == NULL) {
+ NSLog(@"Could not get media library to delete playlist %@",
self.displayString);
+ return;
+ }
+
+ const int result = vlc_ml_playlist_delete(p_ml, self.libraryID);
+ if (result != VLC_SUCCESS) {
+ NSLog(@"Failed to delete playlist %@ with ID %lld from media library",
self.displayString, self.libraryID);
+ } else {
+ NSLog(@"Successfully deleted playlist %@ with ID %lld from media
library", self.displayString, self.libraryID);
+ }
}
- (void)revealInFinder
@@ -1053,6 +1108,7 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
@synthesize primaryActionableDetailLibraryItem =
_primaryActionableDetailLibraryItem;
@synthesize secondaryActionableDetailLibraryItem =
_secondaryActionableDetailLibraryItem;
@synthesize favorited = _favorited;
+@synthesize isFileBacked = _isFileBacked;
#pragma mark - initialization
@@ -1150,6 +1206,7 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
_progress = p_mediaItem->f_progress;
_favorited = p_mediaItem->b_is_favorite;
_title = toNSStr(p_mediaItem->psz_title);
+ _isFileBacked = YES;
switch (p_mediaItem->i_subtype) {
case VLC_ML_MEDIA_SUBTYPE_MOVIE:
@@ -1801,6 +1858,7 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
@synthesize secondaryActionableDetailLibraryItem =
_secondaryActionableDetailLibraryItem;
@synthesize labels = _labels;
@synthesize favorited = _favorited;
+@synthesize isFileBacked = _isFileBacked;
- (instancetype)initWithDisplayString:(NSString *)displayString
withPrimaryDetailString:(nullable NSString *)primaryDetailString
@@ -1815,6 +1873,7 @@ static NSString
*genreArrayDisplayString(NSArray<VLCMediaLibraryGenre *> * const
_libraryId = -1;
_smallArtworkGenerated = NO;
_smallArtworkMRL = @"";
+ _isFileBacked = NO;
_primaryActionableDetail = NO;
_primaryActionableDetailLibraryItem = nil;
_secondaryActionableDetail = NO;
=====================================
modules/gui/macosx/library/VLCLibraryMenuController.m
=====================================
@@ -49,6 +49,8 @@
NSHashTable<NSMenuItem*> *_inputItemRequiringMenuItems;
NSHashTable<NSMenuItem*> *_localInputItemRequiringMenuItems;
NSHashTable<NSMenuItem*> *_folderInputItemRequiringMenuItems;
+
+ NSMenuItem *_deleteItem;
}
@property (readwrite) NSMenuItem *favoriteItem;
@@ -80,8 +82,8 @@
NSMenuItem *revealItem = [[NSMenuItem alloc] initWithTitle:_NS("Reveal in
Finder") action:@selector(revealInFinder:) keyEquivalent:@""];
revealItem.target = self;
- NSMenuItem *deleteItem = [[NSMenuItem alloc] initWithTitle:_NS("Move to
Trash") action:@selector(moveToTrash:) keyEquivalent:@""];
- deleteItem.target = self;
+ _deleteItem = [[NSMenuItem alloc] initWithTitle:_NS("Move to Trash")
action:@selector(moveToTrash:) keyEquivalent:@""];
+ _deleteItem.target = self;
NSMenuItem *markUnseenItem = [[NSMenuItem alloc] initWithTitle:_NS("Mark
as Unseen") action:@selector(markUnseen:) keyEquivalent:@""];
markUnseenItem.target = self;
@@ -104,7 +106,7 @@
self.favoriteItem,
bookmarkItem,
revealItem,
- deleteItem,
+ _deleteItem,
markUnseenItem,
informationItem,
[NSMenuItem separatorItem],
@@ -116,7 +118,7 @@
[_mediaItemRequiringMenuItems addObject:appendItem];
[_mediaItemRequiringMenuItems addObject:self.favoriteItem];
[_mediaItemRequiringMenuItems addObject:revealItem];
- [_mediaItemRequiringMenuItems addObject:deleteItem];
+ [_mediaItemRequiringMenuItems addObject:_deleteItem];
[_mediaItemRequiringMenuItems addObject:informationItem];
_recentsMediaItemRequiringMenuItems = [NSHashTable weakObjectsHashTable];
@@ -128,7 +130,7 @@
_localInputItemRequiringMenuItems = [NSHashTable weakObjectsHashTable];
[_localInputItemRequiringMenuItems addObject:revealItem];
- [_localInputItemRequiringMenuItems addObject:deleteItem];
+ [_localInputItemRequiringMenuItems addObject:_deleteItem];
_folderInputItemRequiringMenuItems = [NSHashTable weakObjectsHashTable];
[_folderInputItemRequiringMenuItems addObject:bookmarkItem];
@@ -173,6 +175,29 @@
}
self.favoriteItem.title = anyUnfavorited ? _NS("Add to Favorites") :
_NS("Remove from Favorites");
self.favoriteItem.action = anyUnfavorited ? @selector(addFavorite:) :
@selector(removeFavorite:);
+
+ // Update delete menu item title based on whether items are file-backed
+ BOOL hasFileBacked = NO;
+ BOOL hasNonFileBacked = NO;
+
+ for (VLCLibraryRepresentedItem * const item in self.representedItems) {
+ if (item.item.isFileBacked) {
+ hasFileBacked = YES;
+ } else {
+ hasNonFileBacked = YES;
+ }
+ if (hasFileBacked && hasNonFileBacked) {
+ break;
+ }
+ }
+
+ if (hasFileBacked && hasNonFileBacked) {
+ _deleteItem.title = _NS("Move to Trash / Delete from Library");
+ } else if (hasFileBacked) {
+ _deleteItem.title = _NS("Move to Trash");
+ } else {
+ _deleteItem.title = _NS("Delete from Library");
+ }
} else if (_representedInputItems != nil &&
self.representedInputItems.count > 0) {
[self menuItems:_mediaItemRequiringMenuItems setHidden:YES];
=====================================
modules/gui/macosx/menus/VLCMainMenu.h
=====================================
@@ -54,6 +54,7 @@
@property (readwrite, weak) IBOutlet NSMenuItem *close_window;
@property (readwrite, weak) IBOutlet NSMenuItem *convertandsave;
@property (readwrite, weak) IBOutlet NSMenuItem *save_playlist;
+@property (readwrite, weak) IBOutlet NSMenuItem *savePlayqueueToLibrary;
@property (readwrite, weak) IBOutlet NSMenuItem *revealInFinder;
@property (readwrite, weak) IBOutlet NSMenu *editMenu;
@@ -237,6 +238,7 @@
- (IBAction)intfOpenNet:(id)sender;
- (IBAction)intfOpenCapture:(id)sender;
- (IBAction)savePlaylist:(id)sender;
+- (IBAction)savePlayQueueToLibrary:(id)sender;
- (IBAction)play:(id)sender;
- (IBAction)stop:(id)sender;
=====================================
modules/gui/macosx/menus/VLCMainMenu.m
=====================================
@@ -27,6 +27,7 @@
#import "extensions/NSScreen+VLCAdditions.h"
#import "extensions/NSString+Helpers.h"
+#import "library/VLCLibraryController.h"
#import "library/VLCLibraryWindow.h"
#import "library/VLCLibraryWindowController.h"
#import "library/VLCLibraryWindowSplitViewController.h"
@@ -360,6 +361,7 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
[_close_window setTitle: _NS("Close Window")];
[_convertandsave setTitle: _NS("Convert / Stream...")];
[_save_playlist setTitle: _NS("Save Playlist...")];
+ [_savePlayqueueToLibrary setTitle: _NS("Save Play Queue to Library...")];
[_revealInFinder setTitle: _NS("Reveal in Finder")];
[_editMenu setTitle: _NS("Edit")];
@@ -1383,6 +1385,21 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
}
}
+- (IBAction)savePlayQueueToLibrary:(id)sender
+{
+ // Check if there are items in the play queue
+ if (_playQueueController.playQueueModel.numberOfPlayQueueItems == 0) {
+ NSAlert * const alert = [[NSAlert alloc] init];
+ alert.messageText = _NS("Play Queue is Empty");
+ alert.informativeText = _NS("There are no items in the play queue to
save.");
+ alert.alertStyle = NSAlertStyleWarning;
+ [alert runModal];
+ return;
+ }
+
+ [VLCMain.sharedInstance.libraryController
showCreatePlaylistDialogForPlayQueue];
+}
+
- (IBAction)showConvertAndSave:(id)sender
{
[[VLCMain.sharedInstance convertAndSaveWindow] showWindow:self];
@@ -1900,6 +1917,8 @@ typedef NS_ENUM(NSInteger, VLCObjectType) {
if (mi == nil) {
return YES;
+ } else if (mi == self.savePlayqueueToLibrary) {
+ return _playQueueController.playQueueModel.numberOfPlayQueueItems > 0;
} else if (mi == self.play) {
return _playerController.playerState == VLC_PLAYER_STATE_PLAYING
? _playerController.currentMedia != nil &&
_playerController.pausable
=====================================
modules/gui/macosx/playqueue/VLCPlayQueueController.m
=====================================
@@ -24,6 +24,7 @@
#import <vlc_interface.h>
#import <vlc_player.h>
+#import <vlc_media_library.h>
#import "extensions/NSString+Helpers.h"
#import "main/VLCMain.h"
=====================================
modules/gui/macosx/playqueue/VLCPlayQueueMenuController.m
=====================================
@@ -26,6 +26,7 @@
#import "extensions/NSString+Helpers.h"
#import "extensions/NSMenu+VLCAdditions.h"
+#import "library/VLCLibraryController.h"
#import "main/VLCMain.h"
#import "playqueue/VLCPlayQueueController.h"
#import "playqueue/VLCPlayQueueModel.h"
@@ -47,6 +48,7 @@
NSMenuItem *_addFilesToPlayQueueMenuItem;
NSMenuItem *_clearPlayQueueMenuItem;
NSMenuItem *_sortMenuItem;
+ NSMenuItem *_createPlaylistMenuItem;
}
@property (readwrite, atomic) NSArray<NSMenuItem *> *items;
@@ -86,6 +88,9 @@
_clearPlayQueueMenuItem = [[NSMenuItem alloc] initWithTitle:_NS("Clear
Play Queue") action:@selector(clearPlayQueue:) keyEquivalent:@""];
_clearPlayQueueMenuItem.target = self;
+ _createPlaylistMenuItem = [[NSMenuItem alloc] initWithTitle:_NS("Create
Playlist from Queue") action:@selector(createPlaylistFromQueue:)
keyEquivalent:@""];
+ _createPlaylistMenuItem.target = self;
+
_playQueueSortingMenuController = [[VLCPlayQueueSortingMenuController
alloc] init];
_sortMenuItem = [[NSMenuItem alloc] initWithTitle:_NS("Sort Play Queue")
action:nil keyEquivalent:@""];
[_sortMenuItem
setSubmenu:_playQueueSortingMenuController.playQueueSortingMenu];
@@ -98,6 +103,7 @@
NSMenuItem.separatorItem,
_addFilesToPlayQueueMenuItem,
_clearPlayQueueMenuItem,
+ _createPlaylistMenuItem,
_sortMenuItem
];
@@ -106,6 +112,7 @@
NSMenuItem.separatorItem,
_addFilesToPlayQueueMenuItem,
_clearPlayQueueMenuItem,
+ _createPlaylistMenuItem,
_sortMenuItem
];
@@ -199,6 +206,27 @@
[_playQueueController clearPlayQueue];
}
+- (void)createPlaylistFromQueue:(id)sender
+{
+ NSIndexSet * const selectedIndexes =
self.playQueueTableView.selectedRowIndexes;
+
+ NSArray<VLCPlayQueueItem *> *items = nil;
+ if (selectedIndexes.count > 0) {
+ NSMutableArray<VLCPlayQueueItem *> * const selectedItems =
[NSMutableArray arrayWithCapacity:selectedIndexes.count];
+ [selectedIndexes enumerateIndexesUsingBlock:^(const NSUInteger idx,
BOOL * const stop) {
+ VLCPlayQueueItem * const item =
[_playQueueController.playQueueModel playQueueItemAtIndex:idx];
+ if (item) {
+ [selectedItems addObject:item];
+ }
+ }];
+ items = selectedItems.copy;
+ } else {
+ items = _playQueueController.playQueueModel.playQueueItems;
+ }
+
+ [VLCMain.sharedInstance.libraryController
showCreatePlaylistDialogForPlayQueueItems:items];
+}
+
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
if (menuItem == _addFilesToPlayQueueMenuItem) {
@@ -207,6 +235,9 @@
} else if (menuItem == _clearPlayQueueMenuItem) {
return (self.playQueueTableView.numberOfRows > 0);
+ } else if (menuItem == _createPlaylistMenuItem) {
+ return (self.playQueueTableView.numberOfRows > 0);
+
} else if (menuItem == _removeMenuItem ||
menuItem == _playMenuItem ||
menuItem == _informationMenuItem) {
=====================================
modules/gui/macosx/playqueue/VLCPlayQueueModel.h
=====================================
@@ -32,11 +32,12 @@ NS_ASSUME_NONNULL_BEGIN
@property (readwrite, assign) VLCPlayQueueController *playQueueController;
@property (readonly) NSUInteger numberOfPlayQueueItems;
+@property (readonly) NSArray<VLCPlayQueueItem *> *playQueueItems;
- (void)dropExistingData;
- (VLCPlayQueueItem *)playQueueItemAtIndex:(NSInteger)index;
-- (void)addItems:(NSArray *)array;
-- (void)addItems:(NSArray *)array atIndex:(size_t)index count:(size_t)count;
+- (void)addItems:(NSArray<VLCPlayQueueItem *> *)array;
+- (void)addItems:(NSArray<VLCPlayQueueItem *> *)array atIndex:(size_t)index
count:(size_t)count;
- (void)moveItemAtIndex:(size_t)index toTarget:(size_t)target;
- (void)removeItemsInRange:(NSRange)range;
- (void)updateItemAtIndex:(size_t)index;
=====================================
modules/gui/macosx/playqueue/VLCPlayQueueModel.m
=====================================
@@ -29,7 +29,7 @@
@interface VLCPlayQueueModel ()
{
- NSMutableArray *_playQueueArray;
+ NSMutableArray<VLCPlayQueueItem *> *_playQueueArray;
}
@end
@@ -49,6 +49,11 @@
return _playQueueArray.count;
}
+- (NSArray<VLCPlayQueueItem *> *)playQueueItems
+{
+ return [_playQueueArray copy];
+}
+
- (void)dropExistingData
{
[_playQueueArray removeAllObjects];
@@ -63,12 +68,12 @@
return _playQueueArray[index];
}
-- (void)addItems:(NSArray *)array
+- (void)addItems:(NSArray<VLCPlayQueueItem *> *)array
{
[_playQueueArray addObjectsFromArray:array];
}
-- (void)addItems:(NSArray *)array atIndex:(size_t)index count:(size_t)count
+- (void)addItems:(NSArray<VLCPlayQueueItem *> *)array atIndex:(size_t)index
count:(size_t)count
{
[_playQueueArray insertObjects:array atIndexes:[NSIndexSet
indexSetWithIndexesInRange:NSMakeRange(index, count)]];
}
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/20cb70f22beb160eff022ae69ed3e23c373936f8...a64451e05b9bdd5b30a7ec43f9a8d5d361120f9b
--
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/20cb70f22beb160eff022ae69ed3e23c373936f8...a64451e05b9bdd5b30a7ec43f9a8d5d361120f9b
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
_______________________________________________
vlc-commits mailing list
vlc-commits@videolan.org
https://mailman.videolan.org/listinfo/vlc-commits