X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fplaylist.m;h=9bf6fd8d9f5aa0c93bb9380d325f5e48ee00df75;hb=b58dfe3584f7a60fcd5afbdac903b513f7082804;hp=d0629203bb1176a1b086a7ea2fde2c2e52156db6;hpb=87c97ae1ea0c35449bbea9f48f528a157a8b6dce;p=vlc diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m index d0629203bb..9bf6fd8d9f 100644 --- a/modules/gui/macosx/playlist.m +++ b/modules/gui/macosx/playlist.m @@ -20,7 +20,7 @@ * * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /* TODO @@ -45,9 +45,11 @@ #include #include "intf.h" +#import "wizard.h" +#import "bookmarks.h" #include "playlist.h" #include "controls.h" -#include "osd.h" +#include "vlc_osd.h" #include "misc.h" /***************************************************************************** @@ -101,6 +103,15 @@ *****************************************************************************/ @implementation VLCPlaylistCommon +- (id)init +{ + self = [super init]; + if ( self != nil ) + { + o_outline_dict = [[NSMutableDictionary alloc] init]; + } + return self; +} - (void)awakeFromNib { playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, @@ -144,8 +155,13 @@ int i_return = 0; playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); - if( p_playlist == NULL || outlineView != o_outline_view ) + if( p_playlist == NULL ) + return 0; + if( outlineView != o_outline_view ) + { + vlc_object_release( p_playlist ); return 0; + } if( item == nil ) { @@ -155,6 +171,7 @@ if( p_view && p_view->p_root ) { i_return = p_view->p_root->i_children; + if( i_current_view == VIEW_CATEGORY ) { i_return--; /* remove the GENERAL item from the list */ @@ -216,8 +233,11 @@ vlc_object_release( p_playlist ); - o_value = [[NSValue valueWithPointer: p_return] retain]; - + o_value = [o_outline_dict objectForKey:[NSString stringWithFormat: @"%p", p_return]]; + if( o_value == nil ) + { + o_value = [[NSValue valueWithPointer: p_return] retain]; + } return o_value; } @@ -335,7 +355,12 @@ - (IBAction)reloadOutlineView { - [o_outline_view reloadData]; + /* Only reload the outlineview if the wizard window is open since this can + be quite long on big playlists */ + if( [[o_outline_view window] isVisible] ) + { + [o_outline_view reloadData]; + } } @end @@ -350,12 +375,8 @@ self = [super init]; if ( self != nil ) { - o_outline_dict = [[NSMutableDictionary alloc] init]; o_nodes_array = [[NSMutableArray alloc] init]; o_items_array = [[NSMutableArray alloc] init]; - - - //i_moveRow = -1; } return self; } @@ -374,7 +395,8 @@ [o_outline_view setDoubleAction: @selector(playItem:)]; [o_outline_view registerForDraggedTypes: - [NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; + [NSArray arrayWithObjects: NSFilenamesPboardType, + @"VLCPlaylistItemPboardType", nil]]; [o_outline_view setIntercellSpacing: NSMakeSize (0.0, 1.0)]; /* We need to check whether _defaultTableHeaderSortImage exists, since it @@ -441,27 +463,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_list_release( p_list ); vlc_object_release( p_playlist ); - /* Change the simple textfield into a searchField if we can... */ -#if 0 - if( MACOS_VERSION >= 10.3 ) - { - NSView *o_parentview = [o_status_field superview]; - NSSearchField *o_better_search_field = [[NSSearchField alloc]initWithFrame:[o_search_field frame]]; - [o_better_search_field setRecentsAutosaveName:@"VLC media player search"]; - [o_better_search_field setDelegate:self]; - [[NSNotificationCenter defaultCenter] addObserver: self - selector: @selector(searchfieldChanged:) - name: NSControlTextDidChangeNotification - object: o_better_search_field]; - - [o_better_search_field setTarget:self]; - [o_better_search_field setAction:@selector(searchItem:)]; - - [o_better_search_field setAutoresizingMask:NSViewMinXMargin]; - [o_parentview addSubview:o_better_search_field]; - [o_search_field setHidden:YES]; - } -#endif //[self playlistUpdated]; } @@ -480,11 +481,12 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [o_mi_recursive_expand setTitle: _NS("Expand Node")]; [o_mi_selectall setTitle: _NS("Select All")]; [o_mi_info setTitle: _NS("Properties")]; + [o_mi_preparse setTitle: _NS("Preparse")]; [o_mi_sort_name setTitle: _NS("Sort Node by Name")]; [o_mi_sort_author setTitle: _NS("Sort Node by Author")]; [o_mi_services setTitle: _NS("Services discovery")]; [o_status_field setStringValue: [NSString stringWithFormat: - _NS("no items in playlist")]]; + _NS("No items in the playlist")]]; [o_random_ckb setTitle: _NS("Random")]; #if 0 @@ -494,13 +496,14 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [[o_loop_popup itemAtIndex:0] setTitle: _NS("Standard Play")]; [[o_loop_popup itemAtIndex:1] setTitle: _NS("Repeat One")]; [[o_loop_popup itemAtIndex:2] setTitle: _NS("Repeat All")]; + [o_mi_addNode setTitle: _NS("Add Folder to Playlist")]; } - (void)playlistUpdated { unsigned int i; - /* Clear indications of any existing column sorting*/ + /* Clear indications of any existing column sorting */ for( i = 0 ; i < [[o_outline_view tableColumns] count] ; i++ ) { [o_outline_view setIndicatorImage:nil inTableColumn: @@ -512,6 +515,8 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ // TODO Find a way to keep the dict size to a minimum //[o_outline_dict removeAllObjects]; [o_outline_view reloadData]; + [[[[VLCMain sharedInstance] getWizard] getPlaylistWizard] reloadOutlineView]; + [[[[VLCMain sharedInstance] getBookmarks] getDataTable] reloadData]; } - (void)playModeUpdated @@ -561,7 +566,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (void)updateRowSelection { -// int i; int i_row; unsigned int j; @@ -615,7 +619,8 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_object_release(p_playlist); } -/* Check if p_item is a child of p_node recursively. We need to check the item existence first since OSX sometimes tries to redraw items that have been +/* Check if p_item is a child of p_node recursively. We need to check the item + existence first since OSX sometimes tries to redraw items that have been deleted. We don't do it when not required since this verification takes quite a long time on big playlists (yes, pretty hacky). */ - (BOOL)isItem: (playlist_item_t *)p_item @@ -745,6 +750,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { playlist_Export( p_playlist, [[o_save_panel filename] fileSystemRepresentation], "export-m3u" ); } + vlc_object_release( p_playlist ); } @@ -759,7 +765,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { playlist_item_t *p_item; playlist_item_t *p_node = NULL; -// int i; p_item = [[o_outline_view itemAtRow:[o_outline_view selectedRow]] pointerValue]; @@ -795,6 +800,49 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } } +/* When called retrieves the selected outlineview row and plays that node or item */ +- (IBAction)preparseItem:(id)sender +{ + int i_count; + NSMutableArray *o_to_preparse; + intf_thread_t * p_intf = VLCIntf; + playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + + o_to_preparse = [NSMutableArray arrayWithArray:[[o_outline_view selectedRowEnumerator] allObjects]]; + i_count = [o_to_preparse count]; + + if( p_playlist != NULL ) + { + int i, i_row; + NSNumber *o_number; + playlist_item_t *p_item = NULL; + + for( i = 0; i < i_count; i++ ) + { + o_number = [o_to_preparse lastObject]; + i_row = [o_number intValue]; + p_item = [[o_outline_view itemAtRow:i_row] pointerValue]; + [o_to_preparse removeObject: o_number]; + [o_outline_view deselectRow: i_row]; + + if( p_item ) + { + if( p_item->i_children == -1 ) + { + playlist_PreparseEnqueue( p_playlist, &p_item->input ); + } + else + { + msg_Dbg( p_intf, "preparse of nodes not yet implemented" ); + } + } + } + vlc_object_release( p_playlist ); + } + [self playlistUpdated]; +} + - (IBAction)servicesChange:(id)sender { NSMenuItem *o_mi = (NSMenuItem *)sender; @@ -975,9 +1023,9 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ NSMutableString *o_temp, *o_temp2; o_temp = [NSMutableString stringWithString: o_uri]; o_temp2 = [NSMutableString stringWithCString: mounts[i_index].f_mntfromname]; - [o_temp replaceOccurrencesOfString: @"/dev/rdisk" withString: @"/dev/disk" options:NULL range:NSMakeRange(0, [o_temp length]) ]; - [o_temp2 replaceOccurrencesOfString: @"s0" withString: @"" options:NULL range:NSMakeRange(0, [o_temp2 length]) ]; - [o_temp2 replaceOccurrencesOfString: @"s1" withString: @"" options:NULL range:NSMakeRange(0, [o_temp2 length]) ]; + [o_temp replaceOccurrencesOfString: @"/dev/rdisk" withString: @"/dev/disk" options:nil range:NSMakeRange(0, [o_temp length]) ]; + [o_temp2 replaceOccurrencesOfString: @"s0" withString: @"" options:nil range:NSMakeRange(0, [o_temp2 length]) ]; + [o_temp2 replaceOccurrencesOfString: @"s1" withString: @"" options:nil range:NSMakeRange(0, [o_temp2 length]) ]; if( strstr( [o_temp fileSystemRepresentation], [o_temp2 fileSystemRepresentation] ) != NULL ) { @@ -1002,9 +1050,9 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ statfs( [o_uri fileSystemRepresentation], buf ); psz_dev = strdup(buf->f_mntfromname); o_temp = [NSMutableString stringWithCString: psz_dev ]; - [o_temp replaceOccurrencesOfString: @"/dev/disk" withString: @"/dev/rdisk" options:NULL range:NSMakeRange(0, [o_temp length]) ]; - [o_temp replaceOccurrencesOfString: @"s0" withString: @"" options:NULL range:NSMakeRange(0, [o_temp length]) ]; - [o_temp replaceOccurrencesOfString: @"s1" withString: @"" options:NULL range:NSMakeRange(0, [o_temp length]) ]; + [o_temp replaceOccurrencesOfString: @"/dev/disk" withString: @"/dev/rdisk" options:nil range:NSMakeRange(0, [o_temp length]) ]; + [o_temp replaceOccurrencesOfString: @"s0" withString: @"" options:nil range:NSMakeRange(0, [o_temp length]) ]; + [o_temp replaceOccurrencesOfString: @"s1" withString: @"" options:nil range:NSMakeRange(0, [o_temp length]) ]; o_uri = o_temp; } @@ -1056,7 +1104,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } /* Add the item */ - playlist_AddItem( p_playlist, p_item, PLAYLIST_APPEND, i_position == -1 ? PLAYLIST_END : i_position + i_item ); + playlist_AddItem( p_playlist, p_item, PLAYLIST_INSERT, i_position == -1 ? PLAYLIST_END : i_position + i_item ); if( i_item == 0 && !b_enqueue ) { @@ -1090,7 +1138,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } /* Add the item */ - playlist_NodeAddItem( p_playlist, p_item, i_view, p_node, PLAYLIST_APPEND, i_position + i_item ); + playlist_NodeAddItem( p_playlist, p_item, i_view, p_node, PLAYLIST_INSERT, i_position + i_item ); if( i_item == 0 && !b_enqueue ) { @@ -1316,6 +1364,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [o_mi_delete setEnabled: b_item_sel]; [o_mi_selectall setEnabled: b_rows]; [o_mi_info setEnabled: b_item_sel]; + [o_mi_preparse setEnabled: b_item_sel]; [o_mi_recursive_expand setEnabled: b_item_sel]; [o_mi_sort_name setEnabled: b_item_sel]; [o_mi_sort_author setEnabled: b_item_sel]; @@ -1425,6 +1474,28 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ vlc_object_release( p_playlist ); } +- (IBAction)addNode:(id)sender +{ + /* simply adds a new node to the end of the playlist */ + playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, + FIND_ANYWHERE ); + if( !p_playlist ) + { + msg_Err( VLCIntf, "Uh Oh! Unable to find playlist!" ); + return; + } + + playlist_item_t * p_item = playlist_NodeCreate( p_playlist, VIEW_CATEGORY, + _("Empty Folder"), p_playlist->p_general ); + + if(! p_item ) + msg_Warn( VLCIntf, "node creation failed, fix VLC!" ); + + playlist_ViewUpdate( p_playlist, VIEW_CATEGORY ); + + vlc_object_release( p_playlist ); +} + @end @implementation VLCPlaylist (NSOutlineViewDataSource) @@ -1440,19 +1511,17 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ if( p_playlist->i_size >= 2 ) { [o_status_field setStringValue: [NSString stringWithFormat: - _NS("%i items in playlist"), p_playlist->i_size]]; + _NS("%i items in the playlist"), p_playlist->i_size]]; } else { if( p_playlist->i_size == 0 ) { - [o_status_field setStringValue: [NSString stringWithFormat: - _NS("no items in playlist"), p_playlist->i_size]]; + [o_status_field setStringValue: _NS("No items in the playlist")]; } else { - [o_status_field setStringValue: [NSString stringWithFormat: - _NS("1 item in playlist"), p_playlist->i_size]]; + [o_status_field setStringValue: _NS("1 item in the playlist")]; } } vlc_object_release( p_playlist ); @@ -1467,7 +1536,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* Required for drag & drop and reordering */ - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard { - unsigned int i,j; + unsigned int i; playlist_t *p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -1502,47 +1571,12 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [self removeItemsFrom: o_nodes_array ifChildrenOf: o_nodes_array]; [self removeItemsFrom: o_items_array ifChildrenOf: o_nodes_array]; -#if 0 - for( i = 0 ; i < [o_nodes_array count] ; i++ ) - { - for ( j = 0 ; j < [o_nodes_array count] ; j++ ) - { - if( j == i ) continue; - if( [self isItem: [[o_nodes_array objectAtIndex:i] pointerValue] - inNode: [[o_nodes_array objectAtIndex:j] pointerValue]] ) - { - [o_nodes_array removeObjectAtIndex:i]; - /* We need to execute the next iteration with the same index - since the current item has been deleted */ - i--; - break; - } - } - } - - for( i = 0 ; i < [o_items_array count] ; i++ ) - { - for ( j = 0 ; j < [o_nodes_array count] ; j++ ) - { - if( [self isItem: [[o_items_array objectAtIndex:i] pointerValue] - inNode: [[o_nodes_array objectAtIndex:j] pointerValue]] ) - { - [o_items_array removeObjectAtIndex:i]; - i--; - break; - } - } - } -#endif /* We add the "VLCPlaylistItemPboardType" type to be able to recognize - a Drop operation comçing from the playlist. - We need to add NSFilenamesPboardType otherwise the outlineview refuses - to the drop. */ + a Drop operation coming from the playlist. */ [pboard declareTypes: [NSArray arrayWithObjects: - @"VLCPlaylistItemPboardType",NSFilenamesPboardType, nil] owner: self]; - [pboard setPropertyList:[NSArray array] - forType:NSFilenamesPboardType]; + @"VLCPlaylistItemPboardType", nil] owner: self]; + [pboard setData:[NSData data] forType:@"VLCPlaylistItemPboardType"]; vlc_object_release(p_playlist); return YES; @@ -1556,13 +1590,24 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ if( !p_playlist ) return NSDragOperationNone; + /* Dropping ON items is not allowed if item is not a node */ + if( item ) + { + if( index == NSOutlineViewDropOnItemIndex && + ((playlist_item_t *)[item pointerValue])->i_children == -1 ) + { + vlc_object_release( p_playlist ); + return NSDragOperationNone; + } + } + /* We refuse to drop an item in anything else than a child of the General Node. We still accept items that would be root nodes of the outlineview - however, to allow drop in an empty playlist.*/ + however, to allow drop in an empty playlist. */ if( !([self isItem: [item pointerValue] inNode: p_playlist->p_general checkItemExistence: NO] || item == nil) ) { - vlc_object_release(p_playlist); + vlc_object_release( p_playlist ); return NSDragOperationNone; } @@ -1577,7 +1622,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ [[o_nodes_array objectAtIndex: i] pointerValue] checkItemExistence: NO] ) { - vlc_object_release(p_playlist); + vlc_object_release( p_playlist ); return NSDragOperationNone; } } @@ -1606,7 +1651,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* Drag & Drop inside the playlist */ if( [[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"] ) { - int i_row; + int i_row, i_removed_from_node = 0; unsigned int i; playlist_item_t *p_new_parent, *p_item = NULL; NSArray *o_all_items = [o_nodes_array arrayByAddingObjectsFromArray: @@ -1614,35 +1659,15 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ /* If the item is to be dropped as root item of the outline, make it a child of the General node. Else, choose the proposed parent as parent. */ - if( item == nil ) - p_new_parent = p_playlist->p_general; - else - p_new_parent = [item pointerValue]; + if( item == nil ) p_new_parent = p_playlist->p_general; + else p_new_parent = [item pointerValue]; - /* If the proposed parent is not a node, then use the parent node of - this item. */ - if( p_new_parent->i_children <= 0 ) + /* Make sure the proposed parent is a node. + (This should never be true) */ + if( p_new_parent->i_children < 0 ) { - int j; - playlist_item_t *p_temp_item = p_new_parent; - p_new_parent = [self parentOfItem: p_new_parent]; - if( !p_new_parent ) - { - vlc_object_release(p_playlist); - return NO; - } - /* Calculate the position of the dropped item in this new parent: - following the first proposed parent. */ - for( j = 0; j < p_new_parent->i_children; j++ ) - { - if( p_new_parent->pp_children[j] == p_temp_item ) - { - index = j; - break; - } - else if( j == p_new_parent->i_children - 1 ) - index = -1; - } + vlc_object_release( p_playlist ); + return NO; } for( i = 0; i < [o_all_items count]; i++ ) @@ -1668,18 +1693,6 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ } } - - /* If we move the playing item in a different node or we move the - node containing the playing item in a different node, then stop - playback, or the playlist refuses to detach the item. */ -/* if( p_playlist->status.i_status != PLAYLIST_STOPPED && - (( p_item == p_playlist->status.p_item && - p_new_parent != p_old_parent) || - ( p_item->i_children > 0 && - [self isItem: p_playlist->status.p_item inNode:p_item] == YES)) - { - playlist_Stop( p_playlist ); - }*/ vlc_mutex_lock( &p_playlist->object_lock ); // Acually detach the item from the old position if( playlist_NodeRemoveItem( p_playlist, p_item, p_old_parent ) == @@ -1693,12 +1706,15 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ i_new_index = -1; /* If we move the item in the same node, we need to take into account that one item will be deleted */ - else if((p_new_parent == p_old_parent && - i_old_index < index + (int)i) - || p_new_parent == p_playlist->p_general || index == 0 ) - i_new_index = index + i; else - i_new_index = index + i + 1; + { + if ((p_new_parent == p_old_parent && + i_old_index < index + (int)i) ) + { + i_removed_from_node++; + } + i_new_index = index + i - i_removed_from_node; + } // Reattach the item to the new position playlist_NodeInsert( p_playlist, i_current_view, p_item, p_new_parent, i_new_index ); @@ -1747,26 +1763,11 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { [self appendArray: o_array atPos: index enqueue: YES]; } + /* This should never occur */ else if( p_node->i_children == -1 ) { - int i_counter; - playlist_item_t *p_real_node = NULL; - - for( i_counter = 0 ; i_counter < p_node->i_parents ; i_counter++ ) - { - if( p_node->pp_parents[i_counter]->i_view == i_current_view ) - { - p_real_node = p_node->pp_parents[i_counter]->p_parent; - break; - } - if( i_counter == p_node->i_parents ) - { - vlc_object_release(p_playlist); - return NO; - } - } - [self appendNodeArray: o_array inNode: p_real_node - atPos: index inView: i_current_view enqueue: YES]; + vlc_object_release( p_playlist ); + return NO; } else {