*
* 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
#include <vlc_keys.h>
#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"
/*****************************************************************************
*****************************************************************************/
@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,
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 )
{
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 */
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;
}
- (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
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;
}
[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
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];
}
[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
[[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:
// 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
- (void)updateRowSelection
{
-// int i;
int i_row;
unsigned int j;
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
{
playlist_Export( p_playlist, [[o_save_panel filename] fileSystemRepresentation], "export-m3u" );
}
+ vlc_object_release( p_playlist );
}
{
playlist_item_t *p_item;
playlist_item_t *p_node = NULL;
-// int i;
p_item = [[o_outline_view itemAtRow:[o_outline_view selectedRow]] pointerValue];
}
}
+/* 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;
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 )
{
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;
}
}
/* 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 )
{
}
/* 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 )
{
[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];
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)
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 );
/* 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 );
[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;
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;
}
[[o_nodes_array objectAtIndex: i] pointerValue]
checkItemExistence: NO] )
{
- vlc_object_release(p_playlist);
+ vlc_object_release( p_playlist );
return NSDragOperationNone;
}
}
/* 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:
/* 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++ )
}
}
-
- /* 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 ) ==
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 );
{
[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
{