1 /*****************************************************************************
2 * VLCPlaylist.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2002-2015 VLC authors and VideoLAN
7 * Authors: Derk-Jan Hartman <hartman at videola/n dot org>
8 * Benjamin Pracht <bigben at videolan dot org>
9 * Felix Paul Kühne <fkuehne at videolan dot org>
10 * David Fuhrmann <david dot fuhrmann at googlemail dot com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
28 * add 'icons' for different types of nodes? (http://www.cocoadev.com/index.pl?IconAndTextInTableCell)
29 * reimplement enable/disable item
33 /*****************************************************************************
35 *****************************************************************************/
36 #include <stdlib.h> /* malloc(), free() */
37 #include <sys/param.h> /* for MAXPATHLEN */
40 #include <sys/mount.h>
42 #import "CompatibilityFixes.h"
45 #import "VLCPlaylist.h"
46 #import "VLCMainMenu.h"
47 #import "VLCPlaylistInfo.h"
48 #import "VLCResumeDialogController.h"
49 #import "VLCOpenWindowController.h"
51 #include <vlc_actions.h>
52 #import <vlc_interface.h>
55 @interface VLCPlaylist ()
57 NSImage *_descendingSortingImage;
58 NSImage *_ascendingSortingImage;
60 BOOL b_selected_item_met;
61 BOOL b_isSortDescending;
62 NSTableColumn *_sortTableColumn;
64 BOOL b_playlistmenu_nib_loaded;
68 // information for playlist table columns menu
70 NSDictionary *_translationsForPlaylistTableColumns;
71 NSArray *_menuOrderOfPlaylistTableColumns;
74 - (void)saveTableColumns;
77 @implementation VLCPlaylist
83 _ascendingSortingImage = [NSImage imageNamed:@"NSAscendingSortIndicator"];
84 _descendingSortingImage = [NSImage imageNamed:@"NSDescendingSortIndicator"];
86 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(applicationWillTerminate:) name: NSApplicationWillTerminateNotification object: nil];
89 _translationsForPlaylistTableColumns = [[NSDictionary alloc] initWithObjectsAndKeys:
90 _NS("Track Number"), TRACKNUM_COLUMN,
91 _NS("Title"), TITLE_COLUMN,
92 _NS("Author"), ARTIST_COLUMN,
93 _NS("Duration"), DURATION_COLUMN,
94 _NS("Genre"), GENRE_COLUMN,
95 _NS("Album"), ALBUM_COLUMN,
96 _NS("Description"), DESCRIPTION_COLUMN,
97 _NS("Date"), DATE_COLUMN,
98 _NS("Language"), LANGUAGE_COLUMN,
99 _NS("URI"), URI_COLUMN,
100 _NS("File Size"), FILESIZE_COLUMN,
102 // this array also assigns tags (index) to type of menu item
103 _menuOrderOfPlaylistTableColumns = [[NSArray alloc] initWithObjects: TRACKNUM_COLUMN, TITLE_COLUMN,
104 ARTIST_COLUMN, DURATION_COLUMN, GENRE_COLUMN, ALBUM_COLUMN,
105 DESCRIPTION_COLUMN, DATE_COLUMN, LANGUAGE_COLUMN, URI_COLUMN,
106 FILESIZE_COLUMN,nil];
114 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
115 NSMutableArray *columnArray = [[NSMutableArray alloc] init];
116 [columnArray addObject: [NSArray arrayWithObjects:TITLE_COLUMN, [NSNumber numberWithFloat:190.], nil]];
117 [columnArray addObject: [NSArray arrayWithObjects:ARTIST_COLUMN, [NSNumber numberWithFloat:95.], nil]];
118 [columnArray addObject: [NSArray arrayWithObjects:DURATION_COLUMN, [NSNumber numberWithFloat:95.], nil]];
120 NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
121 [NSArray arrayWithArray:columnArray], @"PlaylistColumnSelection", nil];
123 [defaults registerDefaults:appDefaults];
126 - (VLCPLModel *)model
135 if (var_InheritBool(getIntf(), "macosx-large-text")) {
136 fontToUse = [NSFont systemFontOfSize:13.];
139 fontToUse = [NSFont systemFontOfSize:11.];
143 NSArray *columns = [_outlineView tableColumns];
144 NSUInteger count = columns.count;
145 for (NSUInteger x = 0; x < count; x++)
146 [[[columns objectAtIndex:x] dataCell] setFont:fontToUse];
147 [_outlineView setRowHeight:rowHeight];
152 // This is only called for the playlist popup menu
156 - (void)setOutlineView:(VLCPlaylistView * __nullable)outlineView
158 _outlineView = outlineView;
159 [_outlineView setDelegate:self];
161 playlist_t * p_playlist = pl_Get(getIntf());
163 _model = [[VLCPLModel alloc] initWithOutlineView:_outlineView playlist:p_playlist rootItem:p_playlist->p_playing];
164 [_outlineView setDataSource:_model];
165 [_outlineView reloadData];
167 [_outlineView setTarget: self];
168 [_outlineView setDoubleAction: @selector(playItem:)];
170 [_outlineView setAllowsEmptySelection: NO];
171 [_outlineView registerForDraggedTypes: [NSArray arrayWithObjects:NSFilenamesPboardType, @"VLCPlaylistItemPboardType", nil]];
172 [_outlineView setIntercellSpacing: NSMakeSize (0.0, 1.0)];
177 - (void)setPlaylistHeaderView:(NSTableHeaderView * __nullable)playlistHeaderView
179 _playlistHeaderView = playlistHeaderView;
181 // Setup playlist table column selection for both context and main menu
182 NSMenu *contextMenu = [[NSMenu alloc] init];
183 [self setupPlaylistTableColumnsForMenu:contextMenu];
184 [_playlistHeaderView setMenu:contextMenu];
185 [self setupPlaylistTableColumnsForMenu:[[[VLCMain sharedInstance] mainMenu] playlistTableColumnsMenu]];
187 NSArray *columnArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"PlaylistColumnSelection"];
189 BOOL hasTitleItem = NO;
191 for (NSArray *column in columnArray) {
192 NSString *columnName = column[0];
193 NSNumber *columnWidth = column[1];
195 if ([columnName isEqualToString:@"status"])
198 // Memorize if we custom set always-enabled title item
199 if ([columnName isEqualToString:TITLE_COLUMN]) {
203 if(![self setPlaylistColumnTableState: NSOnState forColumn:columnName])
206 [[_outlineView tableColumnWithIdentifier:columnName] setWidth:[columnWidth floatValue]];
209 // Set the always enabled title item if not already done
211 [self setPlaylistColumnTableState:NSOnState forColumn:TITLE_COLUMN];
214 - (void)applicationWillTerminate:(NSNotification *)notification
216 /* let's make sure we save the correct widths and positions, since this likely changed since the last time the user played with the column selection */
217 [self saveTableColumns];
222 [_playPlaylistMenuItem setTitle: _NS("Play")];
223 [_deletePlaylistMenuItem setTitle: _NS("Delete")];
224 [_recursiveExpandPlaylistMenuItem setTitle: _NS("Expand All")];
225 [_recursiveCollapsePlaylistMenuItem setTitle: _NS("Collapse All")];
226 [_selectAllPlaylistMenuItem setTitle: _NS("Select All")];
227 [_infoPlaylistMenuItem setTitle: _NS("Media Information...")];
228 [_revealInFinderPlaylistMenuItem setTitle: _NS("Reveal in Finder")];
229 [_addFilesToPlaylistMenuItem setTitle: _NS("Add File...")];
232 - (void)playlistUpdated
234 [_outlineView reloadData];
237 - (void)playbackModeUpdated
239 [_model playbackModeUpdated];
243 - (BOOL)isSelectionEmpty
245 return [_outlineView selectedRow] == -1;
248 - (void)currentlyPlayingItemChanged
250 VLCPLItem *item = [[self model] currentlyPlayingItem];
254 // Search for item row for selection
255 NSInteger itemIndex = [_outlineView rowForItem:item];
257 // Expand if needed. This must be done from root to child
258 // item in order to work
259 NSMutableArray *itemsToExpand = [NSMutableArray array];
260 VLCPLItem *tmpItem = [item parent];
261 while (tmpItem != nil) {
262 [itemsToExpand addObject:tmpItem];
263 tmpItem = [tmpItem parent];
266 for(int i = (int)itemsToExpand.count - 1; i >= 0; i--) {
267 VLCPLItem *currentItem = [itemsToExpand objectAtIndex:i];
268 [_outlineView expandItem: currentItem];
272 // Update highlight for currently playing item
273 [_outlineView reloadData];
275 // Search for row again
276 itemIndex = [_outlineView rowForItem:item];
281 [_outlineView selectRowIndexes: [NSIndexSet indexSetWithIndex: itemIndex] byExtendingSelection: NO];
282 [_outlineView scrollRowToVisible: itemIndex];
286 #pragma mark Playlist actions
288 /* When called retrieves the selected outlineview row and plays that node or item */
289 - (IBAction)playItem:(id)sender
291 playlist_t *p_playlist = pl_Get(getIntf());
293 // ignore clicks on column header when handling double action
294 if (sender == _outlineView && [_outlineView clickedRow] == -1)
297 VLCPLItem *o_item = [_outlineView itemAtRow:[_outlineView selectedRow]];
302 playlist_item_t *p_item = playlist_ItemGetById(p_playlist, [o_item plItemId]);
303 playlist_item_t *p_node = playlist_ItemGetById(p_playlist, [[[self model] rootItem] plItemId]);
305 if (p_item && p_node) {
306 playlist_ViewPlay(p_playlist, p_node, p_item);
311 - (IBAction)revealItemInFinder:(id)sender
313 NSIndexSet *selectedRows = [_outlineView selectedRowIndexes];
314 if (selectedRows.count < 1)
317 VLCPLItem *o_item = [_outlineView itemAtRow:selectedRows.firstIndex];
319 char *psz_url = input_item_GetURI([o_item input]);
322 char *psz_path = vlc_uri2path(psz_url);
323 NSString *path = toNSStr(psz_path);
327 msg_Dbg(getIntf(), "Reveal url %s in finder", [path UTF8String]);
328 [[NSWorkspace sharedWorkspace] selectFile: path inFileViewerRootedAtPath: path];
331 - (IBAction)selectAll:(id)sender
333 [_outlineView selectAll: nil];
336 - (IBAction)showInfoPanel:(id)sender
338 [[[VLCMain sharedInstance] currentMediaInfoPanel] toggleWindow:sender];
341 - (IBAction)addFilesToPlaylist:(id)sender
343 NSIndexSet *selectedRows = [_outlineView selectedRowIndexes];
346 VLCPLItem *parentItem = [[self model] rootItem];
348 if (selectedRows.count >= 1) {
349 position = (int)selectedRows.firstIndex + 1;
350 parentItem = [_outlineView itemAtRow:selectedRows.firstIndex];
351 if ([parentItem parent] != nil)
352 parentItem = [parentItem parent];
355 [[[VLCMain sharedInstance] open] openFileWithAction:^(NSArray *files) {
356 [self addPlaylistItems:files
357 withParentItemId:[parentItem plItemId]
363 - (IBAction)deleteItem:(id)sender
365 [_model deleteSelectedItem];
368 // Actions for playlist column selections
371 - (void)togglePlaylistColumnTable:(id)sender
373 NSInteger i_new_state = ![sender state];
374 NSInteger i_tag = [sender tag];
376 NSString *column = [_menuOrderOfPlaylistTableColumns objectAtIndex:i_tag];
378 [self setPlaylistColumnTableState:i_new_state forColumn:column];
381 - (BOOL)setPlaylistColumnTableState:(NSInteger)i_state forColumn:(NSString *)columnId
383 NSUInteger i_tag = [_menuOrderOfPlaylistTableColumns indexOfObject: columnId];
384 // prevent setting unknown columns
385 if(i_tag == NSNotFound)
388 // update state of menu items
389 [[[_playlistHeaderView menu] itemWithTag: i_tag] setState: i_state];
390 [[[[[VLCMain sharedInstance] mainMenu] playlistTableColumnsMenu] itemWithTag: i_tag] setState: i_state];
392 // Change outline view
393 if (i_state == NSOnState) {
394 NSString *title = [_translationsForPlaylistTableColumns objectForKey:columnId];
398 NSTableColumn *tableColumn = [[NSTableColumn alloc] initWithIdentifier:columnId];
399 [tableColumn setEditable:NO];
400 [[tableColumn dataCell] setFont:[NSFont controlContentFontOfSize:11.]];
402 [[tableColumn headerCell] setStringValue:[_translationsForPlaylistTableColumns objectForKey:columnId]];
404 if ([columnId isEqualToString: TRACKNUM_COLUMN]) {
405 [tableColumn setMinWidth:20.];
406 [tableColumn setMaxWidth:70.];
407 [[tableColumn headerCell] setStringValue:@"#"];
410 [tableColumn setMinWidth:42.];
413 [_outlineView addTableColumn:tableColumn];
414 [_outlineView reloadData];
415 [_outlineView setNeedsDisplay: YES];
418 [_outlineView removeTableColumn: [_outlineView tableColumnWithIdentifier:columnId]];
420 [_outlineView setOutlineTableColumn: [_outlineView tableColumnWithIdentifier:TITLE_COLUMN]];
425 - (BOOL)validateMenuItem:(NSMenuItem *)item
427 if ([item action] == @selector(revealItemInFinder:)) {
428 NSIndexSet *selectedRows = [_outlineView selectedRowIndexes];
429 if (selectedRows.count != 1)
432 VLCPLItem *o_item = [_outlineView itemAtRow:selectedRows.firstIndex];
434 // Check if item exists in file system
435 char *psz_url = input_item_GetURI([o_item input]);
436 NSURL *url = [NSURL URLWithString:toNSStr(psz_url)];
438 if (![url isFileURL])
440 if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]])
443 } else if ([item action] == @selector(deleteItem:)) {
444 return [_outlineView numberOfSelectedRows] > 0 && _model.editAllowed;
445 } else if ([item action] == @selector(selectAll:)) {
446 return [_outlineView numberOfRows] > 0;
447 } else if ([item action] == @selector(playItem:)) {
448 return [_outlineView numberOfSelectedRows] > 0;
449 } else if ([item action] == @selector(recursiveExpandOrCollapseNode:)) {
450 return [_outlineView numberOfSelectedRows] > 0;
451 } else if ([item action] == @selector(showInfoPanel:)) {
452 return [_outlineView numberOfSelectedRows] > 0;
459 #pragma mark Helper for playlist table columns
461 - (void)setupPlaylistTableColumnsForMenu:(NSMenu *)menu
463 NSMenuItem *menuItem;
464 NSUInteger count = [_menuOrderOfPlaylistTableColumns count];
465 for (NSUInteger i = 0; i < count; i++) {
466 NSString *columnId = [_menuOrderOfPlaylistTableColumns objectAtIndex:i];
467 NSString *title = [_translationsForPlaylistTableColumns objectForKey:columnId];
468 menuItem = [menu addItemWithTitle:title
469 action:@selector(togglePlaylistColumnTable:)
471 [menuItem setTarget:self];
474 /* don't set a valid action for the title column selector, since we want it to be disabled */
475 if ([columnId isEqualToString: TITLE_COLUMN])
476 [menuItem setAction:nil];
481 - (void)saveTableColumns
483 NSMutableArray *arrayToSave = [[NSMutableArray alloc] init];
484 NSArray *columns = [[NSArray alloc] initWithArray:[_outlineView tableColumns]];
485 NSUInteger columnCount = [columns count];
486 NSTableColumn *currentColumn;
487 for (NSUInteger i = 0; i < columnCount; i++) {
488 currentColumn = [columns objectAtIndex:i];
489 [arrayToSave addObject:[NSArray arrayWithObjects:[currentColumn identifier], [NSNumber numberWithFloat:[currentColumn width]], nil]];
491 [[NSUserDefaults standardUserDefaults] setObject:arrayToSave forKey:@"PlaylistColumnSelection"];
492 [[NSUserDefaults standardUserDefaults] synchronize];
496 #pragma mark Item helpers
498 - (input_item_t *)createItem:(NSDictionary *)itemToCreateDict
500 intf_thread_t *p_intf = getIntf();
502 input_item_t *p_input;
503 BOOL b_rem = FALSE, b_dir = FALSE, b_writable = FALSE;
504 NSString *uri, *name, *path;
506 NSArray *optionsArray;
509 uri = (NSString *)[itemToCreateDict objectForKey: @"ITEM_URL"];
510 url = [NSURL URLWithString: uri];
512 name = (NSString *)[itemToCreateDict objectForKey: @"ITEM_NAME"];
513 optionsArray = (NSArray *)[itemToCreateDict objectForKey: @"ITEM_OPTIONS"];
515 if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&b_dir] && b_dir &&
516 [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:path isRemovable: &b_rem
517 isWritable:&b_writable isUnmountable:NULL description:NULL type:NULL] && b_rem && !b_writable && [url isFileURL]) {
519 NSString *diskType = [[VLCStringUtility sharedInstance] getVolumeTypeFromMountPath: path];
520 msg_Dbg(p_intf, "detected optical media of type %s in the file input", [diskType UTF8String]);
522 if ([diskType isEqualToString: kVLCMediaDVD])
523 uri = [NSString stringWithFormat: @"dvdnav://%@", [[VLCStringUtility sharedInstance] getBSDNodeFromMountPath: path]];
524 else if ([diskType isEqualToString: kVLCMediaVideoTSFolder])
525 uri = [NSString stringWithFormat: @"dvdnav://%@", path];
526 else if ([diskType isEqualToString: kVLCMediaAudioCD])
527 uri = [NSString stringWithFormat: @"cdda://%@", [[VLCStringUtility sharedInstance] getBSDNodeFromMountPath: path]];
528 else if ([diskType isEqualToString: kVLCMediaVCD])
529 uri = [NSString stringWithFormat: @"vcd://%@#0:0", [[VLCStringUtility sharedInstance] getBSDNodeFromMountPath: path]];
530 else if ([diskType isEqualToString: kVLCMediaSVCD])
531 uri = [NSString stringWithFormat: @"vcd://%@@0:0", [[VLCStringUtility sharedInstance] getBSDNodeFromMountPath: path]];
532 else if ([diskType isEqualToString: kVLCMediaBD] || [diskType isEqualToString: kVLCMediaBDMVFolder])
533 uri = [NSString stringWithFormat: @"bluray://%@", path];
535 msg_Warn(getIntf(), "unknown disk type, treating %s as regular input", [path UTF8String]);
537 p_input = input_item_New([uri UTF8String], [[[NSFileManager defaultManager] displayNameAtPath:path] UTF8String]);
540 p_input = input_item_New([uri fileSystemRepresentation], name ? [name UTF8String] : NULL);
546 NSUInteger count = [optionsArray count];
547 for (NSUInteger i = 0; i < count; i++)
548 input_item_AddOption(p_input, [[optionsArray objectAtIndex:i] UTF8String], VLC_INPUT_OPTION_TRUSTED);
551 /* Recent documents menu */
552 if (url != nil && var_InheritBool(getIntf(), "macosx-recentitems"))
553 [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:url];
558 - (NSArray *)createItemsFromExternalPasteboard:(NSPasteboard *)pasteboard
560 NSArray *o_array = [NSArray array];
561 if (![[pasteboard types] containsObject: NSFilenamesPboardType])
564 NSArray *o_values = [[pasteboard propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
565 NSUInteger count = [o_values count];
567 for (NSUInteger i = 0; i < count; i++) {
569 char *psz_uri = vlc_path2uri([[o_values objectAtIndex:i] UTF8String], NULL);
573 o_dic = [NSDictionary dictionaryWithObject:toNSStr(psz_uri) forKey:@"ITEM_URL"];
576 o_array = [o_array arrayByAddingObject: o_dic];
582 - (void)addPlaylistItems:(NSArray*)array
587 BOOL b_autoplay = var_InheritBool(getIntf(), "macosx-autoplay");
589 [self addPlaylistItems:array withParentItemId:i_plItemId atPos:-1 startPlayback:b_autoplay];
592 - (void)addPlaylistItems:(NSArray*)array tryAsSubtitle:(BOOL)isSubtitle
594 input_thread_t *p_input = pl_CurrentInput(getIntf());
595 if (isSubtitle && array.count == 1 && p_input) {
596 int i_result = input_AddSlave(p_input, SLAVE_TYPE_SPU,
597 [[[array firstObject] objectForKey:@"ITEM_URL"] UTF8String],
599 if (i_result == VLC_SUCCESS) {
600 vlc_object_release(p_input);
606 vlc_object_release(p_input);
608 [self addPlaylistItems:array];
611 - (void)addPlaylistItems:(NSArray*)array withParentItemId:(int)i_plItemId atPos:(int)i_position startPlayback:(BOOL)b_start
613 playlist_t * p_playlist = pl_Get(getIntf());
616 playlist_item_t *p_parent = NULL;
618 p_parent = playlist_ItemGetById(p_playlist, i_plItemId);
620 p_parent = p_playlist->p_playing;
627 NSUInteger count = [array count];
628 int i_current_offset = 0;
629 for (NSUInteger i = 0; i < count; ++i) {
631 NSDictionary *o_current_item = [array objectAtIndex:i];
632 input_item_t *p_input = [self createItem: o_current_item];
636 int i_pos = (i_position == -1) ? PLAYLIST_END : i_position + i_current_offset++;
637 playlist_item_t *p_item = playlist_NodeAddInput(p_playlist, p_input,
642 if (i == 0 && b_start) {
643 playlist_ViewPlay(p_playlist, p_parent, p_item);
645 input_item_Release(p_input);
650 - (IBAction)recursiveExpandOrCollapseNode:(id)sender
652 bool expand = (sender == _recursiveExpandPlaylistMenuItem);
654 NSIndexSet * selectedRows = [_outlineView selectedRowIndexes];
655 NSUInteger count = [selectedRows count];
656 NSUInteger indexes[count];
657 [selectedRows getIndexes:indexes maxCount:count inIndexRange:nil];
660 for (NSUInteger i = 0; i < count; i++) {
661 item = [_outlineView itemAtRow: indexes[i]];
663 /* We need to collapse the node first, since OSX refuses to recursively
664 expand an already expanded node, even if children nodes are collapsed. */
665 if ([_outlineView isExpandable:item]) {
666 [_outlineView collapseItem: item collapseChildren: YES];
669 [_outlineView expandItem: item expandChildren: YES];
672 selectedRows = [_outlineView selectedRowIndexes];
673 [selectedRows getIndexes:indexes maxCount:count inIndexRange:nil];
677 - (NSMenu *)menuForEvent:(NSEvent *)o_event
679 if (!b_playlistmenu_nib_loaded)
680 b_playlistmenu_nib_loaded = [[NSBundle mainBundle] loadNibNamed:@"PlaylistMenu" owner:self topLevelObjects:nil];
682 NSPoint pt = [_outlineView convertPoint: [o_event locationInWindow] fromView: nil];
683 NSInteger row = [_outlineView rowAtPoint:pt];
684 if (row != -1 && ![[_outlineView selectedRowIndexes] containsIndex: row])
685 [_outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
687 // TODO Reenable once per-item info panel is supported again
688 _infoPlaylistMenuItem.hidden = YES;
690 return _playlistMenu;
693 - (void)outlineView:(NSOutlineView *)outlineView didClickTableColumn:(NSTableColumn *)aTableColumn
696 NSString * identifier = [aTableColumn identifier];
698 if (_sortTableColumn == aTableColumn)
699 b_isSortDescending = !b_isSortDescending;
701 b_isSortDescending = false;
703 if (b_isSortDescending)
704 type = ORDER_REVERSE;
708 [[self model] sortForColumn:identifier withMode:type];
710 /* Clear indications of any existing column sorting */
711 NSUInteger count = [[_outlineView tableColumns] count];
712 for (NSUInteger i = 0 ; i < count ; i++)
713 [_outlineView setIndicatorImage:nil inTableColumn: [[_outlineView tableColumns] objectAtIndex:i]];
715 [_outlineView setHighlightedTableColumn:nil];
716 _sortTableColumn = aTableColumn;
717 [_outlineView setHighlightedTableColumn:aTableColumn];
719 if (b_isSortDescending)
720 [_outlineView setIndicatorImage:_descendingSortingImage inTableColumn:aTableColumn];
722 [_outlineView setIndicatorImage:_ascendingSortingImage inTableColumn:aTableColumn];
726 - (void)outlineView:(NSOutlineView *)outlineView
727 willDisplayCell:(id)cell
728 forTableColumn:(NSTableColumn *)tableColumn
731 /* this method can be called when VLC is already dead, hence the extra checks */
732 intf_thread_t * p_intf = getIntf();
735 playlist_t *p_playlist = pl_Get(p_intf);
738 if (var_InheritBool(getIntf(), "macosx-large-text"))
739 fontToUse = [NSFont systemFontOfSize:13.];
741 fontToUse = [NSFont systemFontOfSize:11.];
743 BOOL b_is_playing = NO;
745 playlist_item_t *p_current_item = playlist_CurrentPlayingItem(p_playlist);
746 if (p_current_item) {
747 b_is_playing = p_current_item->i_id == [item plItemId];
752 [cell setFont: [[NSFontManager sharedFontManager] convertFont:fontToUse toHaveTrait:NSBoldFontMask]];
754 [cell setFont: [[NSFontManager sharedFontManager] convertFont:fontToUse toNotHaveTrait:NSBoldFontMask]];
757 // TODO remove method
758 - (NSArray *)draggedItems
760 return [[self model] draggedItems];