📄 playlist.m
字号:
/* Create the menu entries for the main menu */ o_lmi = [[o_mm_mi_services submenu] addItemWithTitle: [NSString stringWithUTF8String: p_parser->psz_longname ? p_parser->psz_longname : ( p_parser->psz_shortname ? p_parser->psz_shortname: objectname)] action: @selector(servicesChange:) keyEquivalent: @""]; [o_lmi setTarget: self]; [o_lmi setRepresentedObject: [NSString stringWithCString:objectname]]; if( b_enabled ) [o_lmi setState: NSOnState]; } } vlc_list_release( p_list ); vlc_object_release( p_playlist ); //[self playlistUpdated];}- (void)searchfieldChanged:(NSNotification *)o_notification{ [o_search_field setStringValue:[[o_notification object] stringValue]];}- (void)initStrings{ [super initStrings]; [o_mi_save_playlist setTitle: _NS("Save Playlist...")]; [o_mi_play setTitle: _NS("Play")]; [o_mi_delete setTitle: _NS("Delete")]; [o_mi_recursive_expand setTitle: _NS("Expand Node")]; [o_mi_selectall setTitle: _NS("Select All")]; [o_mi_info setTitle: _NS("Information")]; [o_mi_preparse setTitle: _NS("Get Stream Information")]; [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 the playlist")]];#if 0 [o_search_button setTitle: _NS("Search")];#endif [o_search_field setToolTip: _NS("Search in Playlist")]; [o_mi_addNode setTitle: _NS("Add Folder to Playlist")]; [o_save_accessory_text setStringValue: _NS("File Format:")]; [[o_save_accessory_popup itemAtIndex:0] setTitle: _NS("Extended M3U")]; [[o_save_accessory_popup itemAtIndex:1] setTitle: _NS("XML Shareable Playlist Format (XSPF)")];}- (void)playlistUpdated{ unsigned int i; /* Clear indications of any existing column sorting */ for( i = 0 ; i < [[o_outline_view tableColumns] count] ; i++ ) { [o_outline_view setIndicatorImage:nil inTableColumn: [[o_outline_view tableColumns] objectAtIndex:i]]; } [o_outline_view setHighlightedTableColumn:nil]; o_tc_sortColumn = nil; // 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]; playlist_t *p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if(! p_playlist ) return; if( p_playlist->i_size >= 2 ) { [o_status_field setStringValue: [NSString stringWithFormat: _NS("%i items in the playlist"), p_playlist->i_size]]; } else { if( p_playlist->i_size == 0 ) { [o_status_field setStringValue: _NS("No items in the playlist")]; } else { [o_status_field setStringValue: _NS("1 item in the playlist")]; } } vlc_object_release( p_playlist );}- (void)playModeUpdated{ playlist_t *p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); vlc_value_t val, val2; if( p_playlist == NULL ) { return; } var_Get( p_playlist, "loop", &val2 ); var_Get( p_playlist, "repeat", &val ); if( val.b_bool == VLC_TRUE ) { [[[VLCMain sharedInstance] getControls] repeatOne]; } else if( val2.b_bool == VLC_TRUE ) { [[[VLCMain sharedInstance] getControls] repeatAll]; } else { [[[VLCMain sharedInstance] getControls] repeatOff]; } [[[VLCMain sharedInstance] getControls] shuffle]; vlc_object_release( p_playlist );}- (playlist_item_t *)parentOfItem:(playlist_item_t *)p_item{ int i; for( i = 0 ; i < p_item->i_parents; i++ ) { if( p_item->pp_parents[i]->i_view == i_current_view ) { return p_item->pp_parents[i]->p_parent; } } return NULL;}- (void)updateRowSelection{ int i_row; unsigned int j; playlist_t *p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); playlist_item_t *p_item, *p_temp_item; NSMutableArray *o_array = [NSMutableArray array]; if( p_playlist == NULL ) return; p_item = p_playlist->status.p_item; if( p_item == NULL ) { vlc_object_release(p_playlist); return; } p_temp_item = p_item; while( p_temp_item->i_parents > 0 ) { [o_array insertObject: [NSValue valueWithPointer: p_temp_item] atIndex: 0]; p_temp_item = [self parentOfItem: p_temp_item]; /*for (i = 0 ; i < p_temp_item->i_parents ; i++) { if( p_temp_item->pp_parents[i]->i_view == i_current_view ) { p_temp_item = p_temp_item->pp_parents[i]->p_parent; break; } }*/ } for (j = 0 ; j < [o_array count] - 1 ; j++) { id o_item; if( ( o_item = [o_outline_dict objectForKey: [NSString stringWithFormat: @"%p", [[o_array objectAtIndex:j] pointerValue]]] ) != nil ) [o_outline_view expandItem: o_item]; } i_row = [o_outline_view rowForItem:[o_outline_dict objectForKey:[NSString stringWithFormat: @"%p", p_item]]]; [o_outline_view selectRow: i_row byExtendingSelection: NO]; [o_outline_view scrollRowToVisible: i_row]; vlc_object_release(p_playlist); /* update our info-panel to reflect the new item */ [[[VLCMain sharedInstance] getInfo] updatePanel];}/* 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 inNode: (playlist_item_t *)p_node checkItemExistence:(BOOL)b_check{ playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); playlist_item_t *p_temp_item = p_item; if( p_playlist == NULL ) { return NO; } if( p_node == p_item ) { vlc_object_release(p_playlist); return YES; } if( p_node->i_children < 1) { vlc_object_release(p_playlist); return NO; } if ( p_temp_item ) { int i; vlc_mutex_lock( &p_playlist->object_lock ); if( b_check ) { /* Since outlineView: willDisplayCell:... may call this function with p_items that don't exist anymore, first check if the item is still in the playlist. Any cleaner solution welcomed. */ for( i = 0; i < p_playlist->i_all_size; i++ ) { if( p_playlist->pp_all_items[i] == p_item ) break; else if ( i == p_playlist->i_all_size - 1 ) { vlc_object_release( p_playlist ); vlc_mutex_unlock( &p_playlist->object_lock ); return NO; } } } while( p_temp_item->i_parents > 0 ) { p_temp_item = [self parentOfItem: p_temp_item]; if( p_temp_item == p_node ) { vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); return YES; }/* for( i = 0; i < p_temp_item->i_parents ; i++ ) { if( p_temp_item->pp_parents[i]->i_view == i_current_view ) { if( p_temp_item->pp_parents[i]->p_parent == p_node ) { vlc_mutex_unlock( &p_playlist->object_lock ); vlc_object_release( p_playlist ); return YES; } else { p_temp_item = p_temp_item->pp_parents[i]->p_parent; break; } } }*/ } vlc_mutex_unlock( &p_playlist->object_lock ); } vlc_object_release( p_playlist ); return NO;}/* This method is usefull for instance to remove the selected children of an already selected node */- (void)removeItemsFrom:(id)o_items ifChildrenOf:(id)o_nodes{ unsigned int i, j; for( i = 0 ; i < [o_items count] ; i++ ) { for ( j = 0 ; j < [o_nodes count] ; j++ ) { if( o_items == o_nodes) { if( j == i ) continue; } if( [self isItem: [[o_items objectAtIndex:i] pointerValue] inNode: [[o_nodes objectAtIndex:j] pointerValue] checkItemExistence: NO] ) { [o_items removeObjectAtIndex:i]; /* We need to execute the next iteration with the same index since the current item has been deleted */ i--; break; } } }}- (IBAction)savePlaylist:(id)sender{ intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); NSSavePanel *o_save_panel = [NSSavePanel savePanel]; NSString * o_name = [NSString stringWithFormat: @"%@", _NS("Untitled")]; //[o_save_panel setAllowedFileTypes: [NSArray arrayWithObjects: @"m3u", @"xpf", nil] ]; [o_save_panel setTitle: _NS("Save Playlist")]; [o_save_panel setPrompt: _NS("Save")]; [o_save_panel setAccessoryView: o_save_accessory_view]; if( [o_save_panel runModalForDirectory: nil file: o_name] == NSOKButton ) { NSString *o_filename = [o_save_panel filename]; if( [o_save_accessory_popup indexOfSelectedItem] == 1 ) { NSString * o_real_filename; NSRange range; range.location = [o_filename length] - [@".xspf" length]; range.length = [@".xspf" length]; if( [o_filename compare:@".xspf" options: NSCaseInsensitiveSearch range: range] != NSOrderedSame ) { o_real_filename = [NSString stringWithFormat: @"%@.xspf", o_filename]; } else { o_real_filename = o_filename; } playlist_Export( p_playlist, [o_real_filename fileSystemRepresentation], "export-xspf" ); } else { NSString * o_real_filename; NSRange range; range.location = [o_filename length] - [@".m3u" length]; range.length = [@".m3u" length]; if( [o_filename compare:@".m3u" options: NSCaseInsensitiveSearch range: range] != NSOrderedSame ) { o_real_filename = [NSString stringWithFormat: @"%@.m3u", o_filename]; } else { o_real_filename = o_filename; } playlist_Export( p_playlist, [o_real_filename fileSystemRepresentation], "export-m3u" ); } } vlc_object_release( p_playlist );}/* When called retrieves the selected outlineview row and plays that node or item */- (IBAction)playItem:(id)sender{ intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist != NULL ) { playlist_item_t *p_item; playlist_item_t *p_node = NULL; p_item = [[o_outline_view itemAtRow:[o_outline_view selectedRow]] pointerValue]; if( p_item ) { if( p_item->i_children == -1 ) { p_node = [self parentOfItem: p_item];/* for( i = 0 ; i < p_item->i_parents ; i++ ) { if( p_item->pp_parents[i]->i_view == i_current_view ) { p_node = p_item->pp_parents[i]->p_parent; } }*/ } else { p_node = p_item; if( p_node->i_children > 0 && p_node->pp_children[0]->i_children == -1 ) { p_item = p_node->pp_children[0]; } else { p_item = NULL; } } playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view, p_node, p_item ); } vlc_object_release( p_playlist ); }}/* 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" ); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -