📄 playlist.m
字号:
}- (void)outlineView: (NSTableView*)o_tv didClickTableColumn:(NSTableColumn *)o_tc{ int i_mode = 0, i_type; intf_thread_t *p_intf = VLCIntf; playlist_t *p_playlist = pl_Yield( p_intf ); /* Check whether the selected table column header corresponds to a sortable table column*/ if( !( o_tc == o_tc_name || o_tc == o_tc_author ) ) { vlc_object_release( p_playlist ); return; } if( o_tc_sortColumn == o_tc ) { b_isSortDescending = !b_isSortDescending; } else { b_isSortDescending = false; } if( o_tc == o_tc_name ) { i_mode = SORT_TITLE; } else if( o_tc == o_tc_author ) { i_mode = SORT_ARTIST; } if( b_isSortDescending ) { i_type = ORDER_REVERSE; } else { i_type = ORDER_NORMAL; } vlc_object_lock( p_playlist ); playlist_RecursiveNodeSort( p_playlist, p_playlist->p_root_category, i_mode, i_type ); vlc_object_unlock( p_playlist ); vlc_object_release( p_playlist ); [self playlistUpdated]; o_tc_sortColumn = o_tc; [o_outline_view setHighlightedTableColumn:o_tc]; if( b_isSortDescending ) { [o_outline_view setIndicatorImage:o_descendingSortingImage inTableColumn:o_tc]; } else { [o_outline_view setIndicatorImage:o_ascendingSortingImage inTableColumn:o_tc]; }}- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item{ playlist_t *p_playlist = pl_Yield( VLCIntf ); id o_playing_item; o_playing_item = [o_outline_dict objectForKey: [NSString stringWithFormat:@"%p", p_playlist->status.p_item]]; if( [self isItem: [o_playing_item pointerValue] inNode: [item pointerValue] checkItemExistence: YES] || [o_playing_item isEqual: item] ) { [cell setFont: [[NSFontManager sharedFontManager] convertFont:[cell font] toHaveTrait:NSBoldFontMask]]; } else { [cell setFont: [[NSFontManager sharedFontManager] convertFont:[cell font] toNotHaveTrait:NSBoldFontMask]]; } vlc_object_release( p_playlist );}- (IBAction)addNode:(id)sender{ /* we have to create a new thread here because otherwise we would block the * interface since the interaction-stuff and this code would run in the same * thread */ [NSThread detachNewThreadSelector: @selector(addNodeThreadedly) toTarget: self withObject:nil]; [self playlistUpdated];}- (void)addNodeThreadedly{ NSAutoreleasePool * ourPool = [[NSAutoreleasePool alloc] init]; /* simply adds a new node to the end of the playlist */ playlist_t * p_playlist = pl_Yield( VLCIntf ); vlc_thread_set_priority( p_playlist, VLC_THREAD_PRIORITY_LOW ); int ret_v; char *psz_name = NULL; ret_v = intf_UserStringInput( p_playlist, _("New Node"), _("Please enter a name for the new node."), &psz_name ); PL_LOCK; if( ret_v != DIALOG_CANCELLED && psz_name ) { playlist_NodeCreate( p_playlist, psz_name, p_playlist->p_local_category, 0, NULL ); } else if(! config_GetInt( p_playlist, "interact" ) ) { /* in case that the interaction is disabled, just give it a bogus name */ playlist_NodeCreate( p_playlist, _("Empty Folder"), p_playlist->p_local_category, 0, NULL ); } PL_UNLOCK; free( psz_name ); pl_Release( VLCIntf ); [ourPool release];}@end@implementation VLCPlaylist (NSOutlineViewDataSource)- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item{ id o_value = [super outlineView: outlineView child: index ofItem: item]; playlist_t *p_playlist = pl_Yield( VLCIntf ); if( playlist_CurrentSize( p_playlist ) >= 2 ) { [o_status_field setStringValue: [NSString stringWithFormat: _NS("%i items"), playlist_CurrentSize( p_playlist )]]; } else { if( playlist_IsEmpty( p_playlist ) ) { [o_status_field setStringValue: _NS("No items in the playlist")]; } else { [o_status_field setStringValue: _NS("1 item")]; } } vlc_object_release( p_playlist ); [o_outline_dict setObject:o_value forKey:[NSString stringWithFormat:@"%p", [o_value pointerValue]]]; return o_value;}/* Required for drag & drop and reordering */- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard{ unsigned int i; playlist_t *p_playlist = pl_Yield( VLCIntf ); /* First remove the items that were moved during the last drag & drop operation */ [o_items_array removeAllObjects]; [o_nodes_array removeAllObjects]; for( i = 0 ; i < [items count] ; i++ ) { id o_item = [items objectAtIndex: i]; /* Refuse to move items that are not in the General Node (Service Discovery) */ if( ![self isItem: [o_item pointerValue] inNode: p_playlist->p_local_category checkItemExistence: NO] && ( var_CreateGetBool( p_playlist, "media-library" ) && ![self isItem: [o_item pointerValue] inNode: p_playlist->p_ml_category checkItemExistence: NO]) ) { vlc_object_release(p_playlist); return NO; } /* Fill the items and nodes to move in 2 different arrays */ if( ((playlist_item_t *)[o_item pointerValue])->i_children > 0 ) [o_nodes_array addObject: o_item]; else [o_items_array addObject: o_item]; } /* Now we need to check if there are selected items that are in already selected nodes. In that case, we only want to move the nodes */ [self removeItemsFrom: o_nodes_array ifChildrenOf: o_nodes_array]; [self removeItemsFrom: o_items_array ifChildrenOf: o_nodes_array]; /* We add the "VLCPlaylistItemPboardType" type to be able to recognize a Drop operation coming from the playlist. */ [pboard declareTypes: [NSArray arrayWithObjects: @"VLCPlaylistItemPboardType", nil] owner: self]; [pboard setData:[NSData data] forType:@"VLCPlaylistItemPboardType"]; vlc_object_release(p_playlist); return YES;}- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index{ playlist_t *p_playlist = pl_Yield( VLCIntf ); NSPasteboard *o_pasteboard = [info draggingPasteboard]; 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; } } /* Don't allow on drop on playlist root element's child */ if( !item && index != NSOutlineViewDropOnItemIndex) { 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. */ if( !( ([self isItem: [item pointerValue] inNode: p_playlist->p_local_category checkItemExistence: NO] || ( var_CreateGetBool( p_playlist, "media-library" ) && [self isItem: [item pointerValue] inNode: p_playlist->p_ml_category checkItemExistence: NO] ) ) || item == nil ) ) { vlc_object_release( p_playlist ); return NSDragOperationNone; } /* Drop from the Playlist */ if( [[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"] ) { unsigned int i; for( i = 0 ; i < [o_nodes_array count] ; i++ ) { /* We refuse to Drop in a child of an item we are moving */ if( [self isItem: [item pointerValue] inNode: [[o_nodes_array objectAtIndex: i] pointerValue] checkItemExistence: NO] ) { vlc_object_release( p_playlist ); return NSDragOperationNone; } } vlc_object_release( p_playlist ); return NSDragOperationMove; } /* Drop from the Finder */ else if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] ) { vlc_object_release( p_playlist ); return NSDragOperationGeneric; } vlc_object_release( p_playlist ); return NSDragOperationNone;}- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index{ playlist_t * p_playlist = pl_Yield( VLCIntf ); NSPasteboard *o_pasteboard = [info draggingPasteboard]; /* Drag & Drop inside the playlist */ if( [[o_pasteboard types] containsObject: @"VLCPlaylistItemPboardType"] ) { 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: o_items_array]; /* 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_local_category; else p_new_parent = [item pointerValue]; /* Make sure the proposed parent is a node. (This should never be true) */ if( p_new_parent->i_children < 0 ) { vlc_object_release( p_playlist ); return NO; } for( i = 0; i < [o_all_items count]; i++ ) { playlist_item_t *p_old_parent = NULL; int i_old_index = 0; p_item = [[o_all_items objectAtIndex:i] pointerValue]; p_old_parent = p_item->p_parent; if( !p_old_parent ) continue; /* We may need the old index later */ if( p_new_parent == p_old_parent ) { int j; for( j = 0; j < p_old_parent->i_children; j++ ) { if( p_old_parent->pp_children[j] == p_item ) { i_old_index = j; break; } } } PL_LOCK; // Actually detach the item from the old position if( playlist_NodeRemoveItem( p_playlist, p_item, p_old_parent ) == VLC_SUCCESS ) { int i_new_index; /* Calculate the new index */ if( index == -1 ) 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) ) { i_removed_from_node++; } i_new_index = index + i - i_removed_from_node; } // Reattach the item to the new position playlist_NodeInsert( p_playlist, p_item, p_new_parent, i_new_index ); } PL_UNLOCK; } [self playlistUpdated]; i_row = [o_outline_view rowForItem:[o_outline_dict objectForKey:[NSString stringWithFormat: @"%p", [[o_all_items objectAtIndex: 0] pointerValue]]]]; if( i_row == -1 ) { i_row = [o_outline_view rowForItem:[o_outline_dict objectForKey:[NSString stringWithFormat: @"%p", p_new_parent]]]; } [o_outline_view deselectAll: self]; [o_outline_view selectRow: i_row byExtendingSelection: NO]; [o_outline_view scrollRowToVisible: i_row]; vlc_object_release( p_playlist ); return YES; } else if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] ) { int i; playlist_item_t *p_node = [item pointerValue]; NSArray *o_array = [NSArray array]; NSArray *o_values = [[o_pasteboard propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector: @selector(caseInsensitiveCompare:)]; for( i = 0; i < (int)[o_values count]; i++) { NSDictionary *o_dic; o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; o_array = [o_array arrayByAddingObject: o_dic]; } if ( item == nil ) { [self appendArray:o_array atPos:index enqueue: YES]; } else { assert( p_node->i_children != -1 ); [self appendNodeArray:o_array inNode: p_node atPos:index enqueue:YES]; } vlc_object_release( p_playlist ); return YES; } vlc_object_release( p_playlist ); return NO;}@end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -