diff --git a/extras/package/macosx/VLC.xcodeproj/project.pbxproj b/extras/package/macosx/VLC.xcodeproj/project.pbxproj index b7e71374dc23d892e731ccec1a9617f54af1f238..d913151f341c64deb396f37e68fde9146d201a66 100644 --- a/extras/package/macosx/VLC.xcodeproj/project.pbxproj +++ b/extras/package/macosx/VLC.xcodeproj/project.pbxproj @@ -127,6 +127,7 @@ 7D445D842202524D00263D34 /* VLCPlaylistItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D445D832202524D00263D34 /* VLCPlaylistItem.m */; }; 7D445D872202574B00263D34 /* VLCPlaylistModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D445D862202574B00263D34 /* VLCPlaylistModel.m */; }; 7D445D8B22032B9200263D34 /* VLCPlaylistTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D445D8A22032B9200263D34 /* VLCPlaylistTableView.m */; }; + 7D445D8E2203375100263D34 /* VLCPlaylistMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D445D8D2203375100263D34 /* VLCPlaylistMenuController.m */; }; 7D66D4362200BC340040D04A /* VLCClickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D66D4352200BC340040D04A /* VLCClickerManager.m */; }; 7D66D4392200C5B80040D04A /* VLCVideoFilterHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D66D4382200C5B80040D04A /* VLCVideoFilterHelper.m */; }; 7D66D43C2200D6090040D04A /* VLCDetachedVideoWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D66D43B2200D6090040D04A /* VLCDetachedVideoWindow.m */; }; @@ -461,6 +462,9 @@ 7D445D862202574B00263D34 /* VLCPlaylistModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCPlaylistModel.m; sourceTree = "<group>"; }; 7D445D8922032B9200263D34 /* VLCPlaylistTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCPlaylistTableView.h; sourceTree = "<group>"; }; 7D445D8A22032B9200263D34 /* VLCPlaylistTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCPlaylistTableView.m; sourceTree = "<group>"; }; + 7D445D8C2203375100263D34 /* VLCPlaylistMenuController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCPlaylistMenuController.h; sourceTree = "<group>"; }; + 7D445D8D2203375100263D34 /* VLCPlaylistMenuController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCPlaylistMenuController.m; sourceTree = "<group>"; }; + 7D445D8F220339D400263D34 /* VLCPlaylistMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VLCPlaylistMenu.xib; sourceTree = "<group>"; }; 7D5678EB1D5BA1DC002698F3 /* VLCApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCApplication.h; sourceTree = "<group>"; }; 7D5678EC1D5BA1DC002698F3 /* VLCApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCApplication.m; sourceTree = "<group>"; }; 7D5678EE1D5BA397002698F3 /* VLCMainWindowControlsBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCMainWindowControlsBar.h; sourceTree = "<group>"; }; @@ -1333,6 +1337,8 @@ 7D0F63FE2201F63400FDB91F /* VLCPlaylistTableCellView.m */, 7D445D8922032B9200263D34 /* VLCPlaylistTableView.h */, 7D445D8A22032B9200263D34 /* VLCPlaylistTableView.m */, + 7D445D8C2203375100263D34 /* VLCPlaylistMenuController.h */, + 7D445D8D2203375100263D34 /* VLCPlaylistMenuController.m */, ); name = Playlist; sourceTree = "<group>"; @@ -1567,6 +1573,7 @@ 6B82240A1E4D2A9000833BE1 /* MainWindow.xib */, 7D713D332201BB130042BEB7 /* VLCLibraryWindow.xib */, 7D0F64002201F66D00FDB91F /* VLCPlaylistTableCellView.xib */, + 7D445D8F220339D400263D34 /* VLCPlaylistMenu.xib */, 7D0F64052202047900FDB91F /* VLCLibraryCollectionViewItem.xib */, 6B82241A1E4D2A9000833BE1 /* VLCStatusBarIconMainMenu.xib */, 6B8224181E4D2A9000833BE1 /* VLCFullScreenPanel.xib */, @@ -1718,6 +1725,7 @@ 6B8A6B0121279D2600DC29F3 /* PXSourceListTableCellView.m in Sources */, 1C3113981E508C6900D4DD76 /* VLCAudioEffectsWindowController.m in Sources */, 6BBBF9851F7B257100B404CD /* VLCLogMessage.m in Sources */, + 7D445D8E2203375100263D34 /* VLCPlaylistMenuController.m in Sources */, 1C31139A1E508C6900D4DD76 /* VLCBookmarksWindowController.m in Sources */, 6B0AB0F01F1AC8B3003A1B4E /* VLCSlider.m in Sources */, 6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */, diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am index 47f0fc3f653ec1105f12a84797d81807b6efad7f..095cd311fb15e22a0c50e7b1233ba27bb23148d4 100644 --- a/modules/gui/macosx/Makefile.am +++ b/modules/gui/macosx/Makefile.am @@ -94,6 +94,7 @@ libmacosx_plugin_la_SOURCES = \ gui/macosx/VLCPlaylistController.h gui/macosx/VLCPlaylistController.m \ gui/macosx/VLCPlaylistDataSource.h gui/macosx/VLCPlaylistDataSource.m \ gui/macosx/VLCPlaylistItem.h gui/macosx/VLCPlaylistItem.m \ + gui/macosx/VLCPlaylistMenuController.h gui/macosx/VLCPlaylistMenuController.m \ gui/macosx/VLCPlaylistModel.h gui/macosx/VLCPlaylistModel.m \ gui/macosx/VLCPlaylistTableCellView.h gui/macosx/VLCPlaylistTableCellView.m \ gui/macosx/VLCPlaylistTableView.h gui/macosx/VLCPlaylistTableView.m \ @@ -157,6 +158,7 @@ libmacosx_plugin_la_XIB_SOURCES = \ gui/macosx/UI/MainMenu.xib \ gui/macosx/UI/MainWindow.xib \ gui/macosx/UI/VLCLibraryWindow.xib \ + gui/macosx/UI/VLCPlaylistMenu.xib \ gui/macosx/UI/VLCPlaylistTableCellView.xib \ gui/macosx/UI/VLCLibraryCollectionViewItem.xib \ gui/macosx/UI/MediaInfo.xib \ diff --git a/modules/gui/macosx/UI/VLCPlaylistMenu.xib b/modules/gui/macosx/UI/VLCPlaylistMenu.xib new file mode 100644 index 0000000000000000000000000000000000000000..abeb2628f97a75cad42fa8ddf5a1d334391dca58 --- /dev/null +++ b/modules/gui/macosx/UI/VLCPlaylistMenu.xib @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="VLCPlaylistMenuController"> + <connections> + <outlet property="addFilesToPlaylistMenuItem" destination="Mdx-tr-uuI" id="XXf-67-eWE"/> + <outlet property="clearPlaylistMenuItem" destination="mfa-zG-Des" id="NjY-ev-rHM"/> + <outlet property="playMenuItem" destination="f6u-YD-nbW" id="cf7-f3-bCx"/> + <outlet property="playlistMenu" destination="dq6-Th-J8r" id="9Tj-Qo-HbU"/> + <outlet property="removeMenuItem" destination="YHt-8w-4G2" id="bRJ-4k-Oa5"/> + <outlet property="revealInFinderMenuItem" destination="FgT-MW-hvr" id="677-Gn-fVV"/> + <outlet property="sortPlaylistMenu" destination="fcX-EB-mJe" id="ww1-Y1-3SO"/> + <outlet property="sortPlaylistMenuItem" destination="fcX-EB-mJe" id="61o-Ll-UrY"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application" customClass="NSObject"/> + <customObject id="YLy-65-1bz" customClass="NSFontManager"/> + <menu id="dq6-Th-J8r"> + <items> + <menuItem title="Play" id="f6u-YD-nbW"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="play:" target="-2" id="baE-Tq-f7Q"/> + </connections> + </menuItem> + <menuItem title="Remove" id="YHt-8w-4G2"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="remove:" target="-2" id="d7Q-Rl-br2"/> + </connections> + </menuItem> + <menuItem title="Reveal in Finder" id="FgT-MW-hvr"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="revealInFinder:" target="-2" id="1hT-vw-QWq"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="hKI-E8-VMA"/> + <menuItem title="Add Files" id="Mdx-tr-uuI"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="addFilesToPlaylist:" target="-2" id="1MB-8E-leR"/> + </connections> + </menuItem> + <menuItem title="Clear Playlist" id="mfa-zG-Des"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="clearPlaylist:" target="-2" id="yy4-15-pKY"/> + </connections> + </menuItem> + <menuItem isSeparatorItem="YES" id="8XF-0j-B5C"/> + <menuItem title="Sort" id="fcX-EB-mJe"> + <modifierMask key="keyEquivalentModifierMask"/> + <menu key="submenu" title="Sort" id="7gg-17-3N9"> + <items> + <menuItem title="Item" id="cjh-Mt-gsu"> + <modifierMask key="keyEquivalentModifierMask"/> + </menuItem> + </items> + </menu> + </menuItem> + </items> + <point key="canvasLocation" x="-88" y="-124"/> + </menu> + </objects> +</document> diff --git a/modules/gui/macosx/VLCPlaylistController.m b/modules/gui/macosx/VLCPlaylistController.m index 975108e88bd7045a3070d6c9f722fe5faf17ec03..f5e632e9255dfb231e76496f4925c0a661911622 100644 --- a/modules/gui/macosx/VLCPlaylistController.m +++ b/modules/gui/macosx/VLCPlaylistController.m @@ -286,7 +286,13 @@ static const struct vlc_playlist_callbacks playlist_callbacks = { - (int)playItemAtIndex:(size_t)index { vlc_playlist_Lock(_p_playlist); - int ret = vlc_playlist_PlayAt(_p_playlist, index); + size_t playlistLength = vlc_playlist_Count(_p_playlist); + int ret = 0; + if (index >= playlistLength) { + ret = VLC_EGENERIC; + } else { + ret = vlc_playlist_PlayAt(_p_playlist, index); + } vlc_playlist_Unlock(_p_playlist); return ret; } diff --git a/modules/gui/macosx/VLCPlaylistItem.h b/modules/gui/macosx/VLCPlaylistItem.h index 210a6682f94dab695da45769d86eaec395c30afb..8168b1dc27ef2b8da82fa0f97e7cae54e3dafae5 100644 --- a/modules/gui/macosx/VLCPlaylistItem.h +++ b/modules/gui/macosx/VLCPlaylistItem.h @@ -27,13 +27,14 @@ NS_ASSUME_NONNULL_BEGIN @interface VLCPlaylistItem : NSObject -@property (readwrite, assign) input_item_t *inputItem; +@property (readonly) vlc_playlist_item_t *playlistItem; @property (readwrite, retain) NSString *title; +@property (readonly, copy, nullable) NSString *path; @property (readwrite, assign) vlc_tick_t duration; -@property (readwrite, retain) NSString *artistName; -@property (readwrite, retain) NSString *albumName; -@property (readwrite, retain) NSString *artworkURLString; +@property (readwrite, retain, nullable) NSString *artistName; +@property (readwrite, retain, nullable) NSString *albumName; +@property (readwrite, retain, nullable) NSString *artworkURLString; - (instancetype)initWithPlaylistItem:(vlc_playlist_item_t *)p_item; diff --git a/modules/gui/macosx/VLCPlaylistItem.m b/modules/gui/macosx/VLCPlaylistItem.m index 8fa6c0633b437ddbc7e55f8942a10938330205b4..52da3b1c5f21f1e290f66e44ae163bf023bff79e 100644 --- a/modules/gui/macosx/VLCPlaylistItem.m +++ b/modules/gui/macosx/VLCPlaylistItem.m @@ -23,6 +23,7 @@ #import "VLCPlaylistItem.h" #import "NSString+Helpers.h" #import <vlc_input.h> +#import <vlc_url.h> @implementation VLCPlaylistItem @@ -30,6 +31,7 @@ { self = [super init]; if (self) { + _playlistItem = p_item; input_item_t *p_media = vlc_playlist_item_GetMedia(p_item); vlc_mutex_lock(&p_media->lock); _title = toNSStr(p_media->psz_name); @@ -47,7 +49,27 @@ - (NSString *)description { - return [NSString stringWithFormat:@"item %p, title: %@", &_inputItem, _title]; + return [NSString stringWithFormat:@"item %p, title: %@", &_playlistItem, _title]; +} + +- (NSString *)path +{ + if (!_playlistItem) { + return nil; + } + input_item_t *p_media = vlc_playlist_item_GetMedia(_playlistItem); + if (!p_media) { + return nil; + } + char *psz_url = input_item_GetURI(p_media); + if (!psz_url) + return nil; + + char *psz_path = vlc_uri2path(psz_url); + NSString *path = toNSStr(psz_path); + free(psz_url); + free(psz_path); + return path; } @end diff --git a/modules/gui/macosx/VLCPlaylistMenuController.h b/modules/gui/macosx/VLCPlaylistMenuController.h new file mode 100644 index 0000000000000000000000000000000000000000..5c42e483d698c1a3affee89303cb0f279c09fb0c --- /dev/null +++ b/modules/gui/macosx/VLCPlaylistMenuController.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * VLCPlaylistMenuController.h: MacOS X interface module + ***************************************************************************** + * Copyright (C) 2002-2019 VLC authors and VideoLAN + * + * Authors: Benjamin Pracht <bigben at videolan dot org> + * Felix Paul Kühne <fkuehne at videolan dot org> + * David Fuhrmann <dfuhrmann # videolan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface VLCPlaylistMenuController : NSObject + +@property (readwrite, weak) NSTableView *playlistTableView; + +@property (readwrite, strong) IBOutlet NSMenu *playlistMenu; +@property (readwrite, weak) IBOutlet NSMenuItem *playMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *revealInFinderMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *addFilesToPlaylistMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *removeMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *clearPlaylistMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *sortPlaylistMenuItem; +@property (readwrite, weak) IBOutlet NSMenuItem *sortPlaylistMenu; + +- (IBAction)play:(id)sender; +- (IBAction)remove:(id)sender; +- (IBAction)revealInFinder:(id)sender; +- (IBAction)addFilesToPlaylist:(id)sender; +- (IBAction)clearPlaylist:(id)sender; + +@end + +NS_ASSUME_NONNULL_END diff --git a/modules/gui/macosx/VLCPlaylistMenuController.m b/modules/gui/macosx/VLCPlaylistMenuController.m new file mode 100644 index 0000000000000000000000000000000000000000..1bdc518e2bfd2c53bdfe7697bf29a522c2d0a921 --- /dev/null +++ b/modules/gui/macosx/VLCPlaylistMenuController.m @@ -0,0 +1,125 @@ +/***************************************************************************** + * VLCPlaylistMenuController.m: MacOS X interface module + ***************************************************************************** + * Copyright (C) 2002-2019 VLC authors and VideoLAN + * + * Authors: Benjamin Pracht <bigben at videolan dot org> + * Felix Paul Kühne <fkuehne at videolan dot org> + * David Fuhrmann <dfuhrmann # videolan.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#import "VLCPlaylistMenuController.h" +#import "VLCMain.h" +#import "VLCPlaylistController.h" +#import "VLCPlaylistModel.h" +#import "VLCPlaylistItem.h" +#import "VLCOpenWindowController.h" + +@interface VLCPlaylistMenuController () +{ + VLCPlaylistController *_playlistController; +} +@end + +@implementation VLCPlaylistMenuController + +- (instancetype)init +{ + self = [super init]; + if (self) { + _playlistController = [[VLCMain sharedInstance] playlistController]; + [[NSBundle mainBundle] loadNibNamed:@"VLCPlaylistMenu" owner:self topLevelObjects:nil]; + } + return self; +} + +- (void)awakeFromNib +{ + [_playMenuItem setTitle:_NS("Play")]; + [_revealInFinderMenuItem setTitle:_NS("Reveal in Finder")]; + [_addFilesToPlaylistMenuItem setTitle:_NS("Add File...")]; + [_removeMenuItem setTitle:_NS("Delete")]; + [_clearPlaylistMenuItem setTitle:_NS("Clear the playlist")]; + [_sortPlaylistMenuItem setTitle:_NS("Sort by")]; +} + +- (IBAction)play:(id)sender +{ + NSInteger selectedRow = self.playlistTableView.selectedRow; + + if (selectedRow != -1) { + [_playlistController playItemAtIndex:selectedRow]; + } else { + [_playlistController startPlaylist]; + } +} + +- (IBAction)remove:(id)sender +{ + NSInteger selectedRow = self.playlistTableView.selectedRow; + + if (selectedRow != -1) { + [_playlistController removeItemAtIndex:selectedRow]; + } +} + +- (IBAction)revealInFinder:(id)sender +{ + NSInteger selectedRow = self.playlistTableView.selectedRow; + + if (selectedRow == -1) + return; + + VLCPlaylistItem *item = [_playlistController.playlistModel playlistItemAtIndex:selectedRow]; + if (item == nil) { + return; + } + + NSString *path = item.path; + [[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:path]; +} + +- (IBAction)addFilesToPlaylist:(id)sender +{ + NSInteger selectedRow = self.playlistTableView.selectedRow; + + [[[VLCMain sharedInstance] open] openFileWithAction:^(NSArray *files) { + [self->_playlistController addPlaylistItems:files + atPosition:selectedRow + startPlayback:NO]; + }]; +} + +- (IBAction)clearPlaylist:(id)sender +{ + [_playlistController clearPlaylist]; +} + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + if (menuItem == self.addFilesToPlaylistMenuItem) { + return YES; + } + + if (_playlistController.playlistModel.numberOfPlaylistItems > 0) { + return YES; + } + + return NO; +} + +@end diff --git a/modules/gui/macosx/VLCPlaylistTableView.m b/modules/gui/macosx/VLCPlaylistTableView.m index 3d67b1ca6d6210cd62b1440784fda82ce47fd982..fc0fad676f1b979ddc736cda74ae84b93e73c6ee 100644 --- a/modules/gui/macosx/VLCPlaylistTableView.m +++ b/modules/gui/macosx/VLCPlaylistTableView.m @@ -26,13 +26,29 @@ #import "VLCPlaylistTableView.h" #import "VLCMain.h" #import "VLCPlaylistController.h" +#import "VLCPlaylistMenuController.h" + +@interface VLCPlaylistTableView () +{ + VLCPlaylistMenuController *_menuController; +} +@end @implementation VLCPlaylistTableView - (NSMenu *)menuForEvent:(NSEvent *)event { - return nil; - // FIXME: return([(VLCPlaylist *)[self delegate] menuForEvent: event]); + if (!_menuController) { + _menuController = [[VLCPlaylistMenuController alloc] init]; + _menuController.playlistTableView = self; + } + + NSPoint pt = [self convertPoint: [event locationInWindow] fromView: nil]; + NSInteger row = [self rowAtPoint:pt]; + if (row != -1 && ![[self selectedRowIndexes] containsIndex: row]) + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; + + return _menuController.playlistMenu; } - (void)keyDown:(NSEvent *)event diff --git a/po/POTFILES.in b/po/POTFILES.in index 739c5957d9baef056e01039ae52eab1c94993643..a6c8400492199c9cc56895748b7584c7e8776864 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -517,6 +517,8 @@ modules/gui/macosx/VLCPlaylist.h modules/gui/macosx/VLCPlaylist.m modules/gui/macosx/VLCPlaylistInfo.h modules/gui/macosx/VLCPlaylistInfo.m +modules/gui/macosx/VLCPlaylistMenuController.h +modules/gui/macosx/VLCPlaylistMenuController.m modules/gui/macosx/VLCPlaylistView.h modules/gui/macosx/VLCPlaylistView.m modules/gui/macosx/VLCPopupPanelController.h