+- (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")]];
+
+ [o_random_ckb setTitle: _NS("Random")];
+#if 0
+ [o_search_button setTitle: _NS("Search")];
+#endif
+ [o_search_field setToolTip: _NS("Search in Playlist")];
+ [[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")];
+
+ [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 )
+ {
+ [o_loop_popup selectItemAtIndex: 1];
+ }
+ else if( val2.b_bool == VLC_TRUE )
+ {
+ [o_loop_popup selectItemAtIndex: 2];
+ }
+ else
+ {
+ [o_loop_popup selectItemAtIndex: 0];
+ }
+
+ var_Get( p_playlist, "random", &val );
+ [o_random_ckb setState: val.b_bool];
+
+ 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" );
+ }
+ }
+ }
+ vlc_object_release( p_playlist );
+ }
+ [self playlistUpdated];
+}
+
+- (IBAction)servicesChange:(id)sender
+{
+ NSMenuItem *o_mi = (NSMenuItem *)sender;
+ NSString *o_string = [o_mi representedObject];
+ playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( !playlist_IsServicesDiscoveryLoaded( p_playlist, [o_string cString] ) )
+ playlist_ServicesDiscoveryAdd( p_playlist, [o_string cString] );
+ else
+ playlist_ServicesDiscoveryRemove( p_playlist, [o_string cString] );
+
+ [o_mi setState: playlist_IsServicesDiscoveryLoaded( p_playlist,
+ [o_string cString] ) ? YES : NO];
+
+ i_current_view = VIEW_CATEGORY;
+ playlist_ViewUpdate( p_playlist, i_current_view );
+ vlc_object_release( p_playlist );
+ [self playlistUpdated];
+ return;
+}
+
+- (IBAction)selectAll:(id)sender
+{
+ [o_outline_view selectAll: nil];
+}
+
+- (IBAction)deleteItem:(id)sender
+{
+ int i, i_count, i_row;
+ NSMutableArray *o_to_delete;
+ NSNumber *o_number;
+
+ playlist_t * p_playlist;
+ intf_thread_t * p_intf = VLCIntf;
+
+ p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if ( p_playlist == NULL )
+ {
+ return;
+ }
+ o_to_delete = [NSMutableArray arrayWithArray:[[o_outline_view selectedRowEnumerator] allObjects]];
+ i_count = [o_to_delete count];
+
+ for( i = 0; i < i_count; i++ )
+ {
+ o_number = [o_to_delete lastObject];
+ i_row = [o_number intValue];
+ id o_item = [o_outline_view itemAtRow: i_row];
+ playlist_item_t *p_item = [o_item pointerValue];
+ [o_to_delete removeObject: o_number];
+ [o_outline_view deselectRow: i_row];
+
+ if( [[o_outline_view dataSource] outlineView:o_outline_view
+ numberOfChildrenOfItem: o_item] > 0 )
+ //is a node and not an item
+ {
+ if( p_playlist->status.i_status != PLAYLIST_STOPPED &&
+ [self isItem: p_playlist->status.p_item inNode:
+ ((playlist_item_t *)[o_item pointerValue])
+ checkItemExistence: NO] == YES )
+ {
+ // if current item is in selected node and is playing then stop playlist
+ playlist_Stop( p_playlist );
+ }
+ vlc_mutex_lock( &p_playlist->object_lock );
+ playlist_NodeDelete( p_playlist, p_item, VLC_TRUE, VLC_FALSE );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ }
+ else
+ {
+ if( p_playlist->status.i_status != PLAYLIST_STOPPED &&
+ p_playlist->status.p_item == [[o_outline_view itemAtRow: i_row] pointerValue] )
+ {
+ playlist_Stop( p_playlist );
+ }
+ vlc_mutex_lock( &p_playlist->object_lock );
+ playlist_Delete( p_playlist, p_item->input.i_id );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ }
+ }
+ [self playlistUpdated];
+ vlc_object_release( p_playlist );
+}
+
+- (IBAction)sortNodeByName:(id)sender
+{
+ [self sortNode: SORT_TITLE];
+}
+
+- (IBAction)sortNodeByAuthor:(id)sender
+{
+ [self sortNode: SORT_AUTHOR];
+}
+
+- (void)sortNode:(int)i_mode
+{
+ playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ playlist_item_t * p_item;
+
+ if (p_playlist == NULL)
+ {
+ return;
+ }
+
+ if( [o_outline_view selectedRow] > -1 )
+ {
+ p_item = [[o_outline_view itemAtRow: [o_outline_view selectedRow]]
+ pointerValue];
+ }
+ else
+ /*If no item is selected, sort the whole playlist*/
+ {
+ playlist_view_t * p_view = playlist_ViewFind( p_playlist, i_current_view );
+ p_item = p_view->p_root;
+ }
+
+ if( p_item->i_children > -1 ) // the item is a node
+ {
+ vlc_mutex_lock( &p_playlist->object_lock );
+ playlist_RecursiveNodeSort( p_playlist, p_item, i_mode, ORDER_NORMAL );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ }
+ else
+ {
+ int i;
+
+ for( i = 0 ; i < p_item->i_parents ; i++ )
+ {
+ if( p_item->pp_parents[i]->i_view == i_current_view )
+ {
+ vlc_mutex_lock( &p_playlist->object_lock );
+ playlist_RecursiveNodeSort( p_playlist,
+ p_item->pp_parents[i]->p_parent, i_mode, ORDER_NORMAL );
+ vlc_mutex_unlock( &p_playlist->object_lock );
+ break;
+ }
+ }
+ }
+ vlc_object_release( p_playlist );
+ [self playlistUpdated];
+}
+
+- (playlist_item_t *)createItem:(NSDictionary *)o_one_item
+{
+ intf_thread_t * p_intf = VLCIntf;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+
+ if( p_playlist == NULL )
+ {
+ return NULL;
+ }
+ playlist_item_t *p_item;
+ int i;
+ BOOL b_rem = FALSE, b_dir = FALSE;
+ NSString *o_uri, *o_name;
+ NSArray *o_options;
+ NSURL *o_true_file;
+
+ /* Get the item */
+ o_uri = (NSString *)[o_one_item objectForKey: @"ITEM_URL"];
+ o_name = (NSString *)[o_one_item objectForKey: @"ITEM_NAME"];
+ o_options = (NSArray *)[o_one_item objectForKey: @"ITEM_OPTIONS"];
+
+ /* Find the name for a disc entry ( i know, can you believe the trouble?) */
+ if( ( !o_name || [o_name isEqualToString:@""] ) && [o_uri rangeOfString: @"/dev/"].location != NSNotFound )
+ {
+ int i_count, i_index;
+ struct statfs *mounts = NULL;
+
+ i_count = getmntinfo (&mounts, MNT_NOWAIT);
+ /* getmntinfo returns a pointer to static data. Do not free. */
+ for( i_index = 0 ; i_index < i_count; i_index++ )
+ {
+ 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: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 )
+ {
+ o_name = [[NSFileManager defaultManager] displayNameAtPath: [NSString stringWithCString:mounts[i_index].f_mntonname]];
+ }
+ }
+ }
+ /* If no name, then make a guess */
+ if( !o_name) o_name = [[NSFileManager defaultManager] displayNameAtPath: o_uri];
+
+ if( [[NSFileManager defaultManager] fileExistsAtPath:o_uri isDirectory:&b_dir] && b_dir &&
+ [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath: o_uri isRemovable: &b_rem
+ isWritable:NULL isUnmountable:NULL description:NULL type:NULL] && b_rem )
+ {
+ /* All of this is to make sure CD's play when you D&D them on VLC */
+ /* Converts mountpoint to a /dev file */
+ struct statfs *buf;
+ char *psz_dev;
+ NSMutableString *o_temp;
+
+ buf = (struct statfs *) malloc (sizeof(struct statfs));
+ 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: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;
+ }
+
+ p_item = playlist_ItemNew( p_intf, [o_uri fileSystemRepresentation], [o_name UTF8String] );
+ if( !p_item )
+ return NULL;
+
+ if( o_options )
+ {
+ for( i = 0; i < (int)[o_options count]; i++ )
+ {
+ playlist_ItemAddOption( p_item, strdup( [[o_options objectAtIndex:i] UTF8String] ) );
+ }
+ }
+
+ /* Recent documents menu */
+ o_true_file = [NSURL fileURLWithPath: o_uri];
+ if( o_true_file != nil )
+ {
+ [[NSDocumentController sharedDocumentController]
+ noteNewRecentDocumentURL: o_true_file];
+ }
+
+ vlc_object_release( p_playlist );
+ return p_item;
+}
+
+- (void)appendArray:(NSArray*)o_array atPos:(int)i_position enqueue:(BOOL)b_enqueue
+{
+ int i_item;
+ playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ for( i_item = 0; i_item < (int)[o_array count]; i_item++ )
+ {
+ playlist_item_t *p_item;
+ NSDictionary *o_one_item;
+
+ /* Get the item */
+ o_one_item = [o_array objectAtIndex: i_item];
+ p_item = [self createItem: o_one_item];
+ if( !p_item )
+ {
+ continue;
+ }
+
+ /* Add the item */
+ playlist_AddItem( p_playlist, p_item, PLAYLIST_INSERT, i_position == -1 ? PLAYLIST_END : i_position + i_item );
+
+ if( i_item == 0 && !b_enqueue )
+ {
+ playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item );
+ }
+ }
+ vlc_object_release( p_playlist );
+}
+
+- (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position inView:(int)i_view enqueue:(BOOL)b_enqueue
+{
+ int i_item;
+ playlist_t * p_playlist = vlc_object_find( VLCIntf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ for( i_item = 0; i_item < (int)[o_array count]; i_item++ )
+ {
+ playlist_item_t *p_item;
+ NSDictionary *o_one_item;
+
+ /* Get the item */
+ o_one_item = [o_array objectAtIndex: i_item];
+ p_item = [self createItem: o_one_item];
+ if( !p_item )
+ {
+ continue;
+ }
+
+ /* Add the item */
+ playlist_NodeAddItem( p_playlist, p_item, i_view, p_node, PLAYLIST_INSERT, i_position + i_item );
+
+ if( i_item == 0 && !b_enqueue )
+ {
+ playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item );
+ }
+ }
+ vlc_object_release( p_playlist );
+
+}
+
+- (IBAction)handlePopUp:(id)sender
+
+{
+ intf_thread_t * p_intf = VLCIntf;
+ vlc_value_t val1,val2;
+ playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+ FIND_ANYWHERE );
+ if( p_playlist == NULL )
+ {
+ return;
+ }
+
+ switch( [o_loop_popup indexOfSelectedItem] )
+ {
+ case 1: