/*****************************************************************************
* playlist.m: MacOS X interface module
*****************************************************************************
-* Copyright (C) 2002-2007 the VideoLAN team
+* Copyright (C) 2002-2008 the VideoLAN team
* $Id$
*
* Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
/* TODO
* add 'icons' for different types of nodes? (http://www.cocoadev.com/index.pl?IconAndTextInTableCell)
- * create toggle buttons for the shuffle, repeat one, repeat all functions.
* reimplement enable/disable item
* create a new 'tool' button (see the gear button in the Finder window) for 'actions'
(adding service discovery, other views, new node/playlist, save node/playlist) stuff like that
case NSEnterCharacter:
case NSCarriageReturnCharacter:
- [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist]
- playItem:self];
+ [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist] playItem:self];
break;
default:
p_item = (playlist_item_t *)[item pointerValue];
}
if( p_item )
- i_return = p_item->i_children;
+ i_return = p_item->i_children;
vlc_object_release( p_playlist );
- if( i_return <= 0 )
- i_return = 0;
-
- return i_return;
+ return i_return > 0 ? i_return : 0;
}
/* return the child at index for the Obj-C pointer item */ /* DONE */
if( o_value == nil )
{
+ msg_Warn( VLCIntf, "playlist item misses pointer value, adding one" );
o_value = [[NSValue valueWithPointer: p_return] retain];
- msg_Err( VLCIntf, "missing playlist item's pointer value" );
}
return o_value;
}
if( !EMPTY_STR( psz_title ) )
{
o_value = [NSString stringWithUTF8String: psz_title];
- if( o_value == NULL )
- o_value = [NSString stringWithCString: psz_title];
}
else
{
if( psz_name != NULL )
{
o_value = [NSString stringWithUTF8String: psz_name];
- if( o_value == NULL )
- o_value = [NSString stringWithCString: psz_name];
}
free( psz_name );
}
if( [[o_tc identifier] isEqualToString:@"2"] && !EMPTY_STR( psz_artist ) )
{
o_value = [NSString stringWithUTF8String: psz_artist];
- if( o_value == NULL )
- o_value = [NSString stringWithCString: psz_artist];
}
else if( [[o_tc identifier] isEqualToString:@"3"] )
{
- (void)awakeFromNib
{
playlist_t * p_playlist = pl_Yield( VLCIntf );
- vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE,
- FIND_ANYWHERE );
- int i_index;
+ int i;
[super awakeFromNib];
@"VLCPlaylistItemPboardType", nil]];
[o_outline_view setIntercellSpacing: NSMakeSize (0.0, 1.0)];
- /* this uses private Apple API which works fine until 10.4,
- * but keep checking in the future!
+ /* This uses private Apple API which works fine until 10.4.
+ * We need to keep checking in the future!
* These methods are being added artificially to NSOutlineView's interface above */
o_ascendingSortingImage = [[NSOutlineView class] _defaultTableHeaderSortImage];
o_descendingSortingImage = [[NSOutlineView class] _defaultTableHeaderReverseSortImage];
o_tc_sortColumn = nil;
- for( i_index = 0; i_index < p_list->i_count; i_index++ )
+ char ** ppsz_name;
+ char ** ppsz_services = services_discovery_GetServicesNames( p_playlist, &ppsz_name );
+ if( !ppsz_services )
+ {
+ vlc_object_release( p_playlist );
+ return;
+ }
+
+ for( i = 0; ppsz_services[i]; i++ )
{
vlc_bool_t b_enabled;
char *objectname;
NSMenuItem *o_lmi;
- module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object ;
- if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
- {
- /* Check for submodules */
- int i = -1;
- while( p_parser->pp_shortcuts[++i] != NULL ); i--;
+ char * name = ppsz_name[i] ? ppsz_name[i] : ppsz_services[i];
+ /* Check whether to enable these menuitems */
+ b_enabled = playlist_IsServicesDiscoveryLoaded( p_playlist, objectname );
+
+ /* Create the menu entries used in the playlist menu */
+ o_lmi = [[o_mi_services submenu] addItemWithTitle:
+ [NSString stringWithUTF8String: name]
+ action: @selector(servicesChange:)
+ keyEquivalent: @""];
+ [o_lmi setTarget: self];
+ [o_lmi setRepresentedObject: [NSString stringWithUTF8String: ppsz_services[i]]];
+ if( b_enabled ) [o_lmi setState: NSOnState];
+
+ /* Create the menu entries for the main menu */
+ o_lmi = [[o_mm_mi_services submenu] addItemWithTitle:
+ [NSString stringWithUTF8String: name]
+ action: @selector(servicesChange:)
+ keyEquivalent: @""];
+ [o_lmi setTarget: self];
+ [o_lmi setRepresentedObject: [NSString stringWithUTF8String: ppsz_services[i]]];
+ if( b_enabled ) [o_lmi setState: NSOnState];
+
+ free( ppsz_services[i] );
+ free( ppsz_name[i] );
+ }
+ free( ppsz_services );
+ free( ppsz_name );
- /* Check whether to enable these menuitems */
- objectname = i>=0 ? (char *)p_parser->pp_shortcuts[i] : (char *)p_parser->psz_object_name;
- b_enabled = playlist_IsServicesDiscoveryLoaded( p_playlist, objectname );
-
- /* Create the menu entries used in the playlist menu */
- o_lmi = [[o_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];
-
- /* 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_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_status_field setStringValue: _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_array insertObject: [NSValue valueWithPointer: p_temp_item] atIndex: 0];
p_temp_item = p_temp_item->p_parent;
- /*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++ )
}
- 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 */
- (IBAction)savePlaylist:(id)sender
{
- intf_thread_t * p_intf = VLCIntf;
- playlist_t * p_playlist = pl_Yield( p_intf );
+ playlist_t * p_playlist = pl_Yield( VLCIntf );
NSSavePanel *o_save_panel = [NSSavePanel savePanel];
NSString * o_name = [NSString stringWithFormat: @"%@", _NS("Untitled")];
}
else
{
- msg_Dbg( p_intf, "preparse of nodes not yet implemented" );
+ msg_Dbg( p_intf, "preparsing nodes not implemented" );
}
}
}
- (IBAction)deleteItem:(id)sender
{
- int i, i_count, i_row;
+ int i_count, i_row;
NSMutableArray *o_to_delete;
NSNumber *o_number;
playlist_t * p_playlist;
intf_thread_t * p_intf = VLCIntf;
- p_playlist = pl_Yield( p_intf );
-
o_to_delete = [NSMutableArray arrayWithArray:[[o_outline_view selectedRowEnumerator] allObjects]];
i_count = [o_to_delete count];
- for( i = 0; i < i_count; i++ )
+ p_playlist = pl_Yield( p_intf );
+
+ PL_LOCK;
+ for( int 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];
+#ifndef NDEBUG
+ msg_Dbg( p_intf, "deleting item %i (of %i) with id \"%i\", pointerValue \"%p\" and %i children", i+1, i_count,
+ p_item->p_input->i_id, [o_item pointerValue], p_item->i_children +1 );
+#endif
[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 )
+ if( p_item->i_children != -1 )
//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
- {
- playlist_DeleteFromInput( p_playlist, p_item->p_input->i_id, VLC_FALSE );
- }
+ playlist_DeleteFromInput( p_playlist, p_item->p_input->i_id, VLC_TRUE );
}
+ PL_UNLOCK;
+
[self playlistUpdated];
vlc_object_release( p_playlist );
}
if( [o_outline_view selectedRow] > -1 )
{
- p_item = [[o_outline_view itemAtRow: [o_outline_view selectedRow]]
- pointerValue];
+ p_item = [[o_outline_view itemAtRow: [o_outline_view selectedRow]] pointerValue];
}
else
/*If no item is selected, sort the whole playlist*/
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?) */
+ /* 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;
{
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]) ];
+ o_temp2 = [NSMutableString stringWithUTF8String: mounts[i_index].f_mntfromname];
+ [o_temp replaceOccurrencesOfString: @"/dev/rdisk" withString: @"/dev/disk" options:NSLiteralSearch range:NSMakeRange(0, [o_temp length]) ];
+ [o_temp2 replaceOccurrencesOfString: @"s0" withString: @"" options:NSLiteralSearch range:NSMakeRange(0, [o_temp2 length]) ];
+ [o_temp2 replaceOccurrencesOfString: @"s1" withString: @"" options:NSLiteralSearch 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]];
+ o_name = [[NSFileManager defaultManager] displayNameAtPath: [NSString stringWithUTF8String:mounts[i_index].f_mntonname]];
}
}
}
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_temp = [NSMutableString stringWithUTF8String: psz_dev ];
+ [o_temp replaceOccurrencesOfString: @"/dev/disk" withString: @"/dev/rdisk" options:NSLiteralSearch range:NSMakeRange(0, [o_temp length]) ];
+ [o_temp replaceOccurrencesOfString: @"s0" withString: @"" options:NSLiteralSearch range:NSMakeRange(0, [o_temp length]) ];
+ [o_temp replaceOccurrencesOfString: @"s1" withString: @"" options:NSLiteralSearch range:NSMakeRange(0, [o_temp length]) ];
o_uri = o_temp;
}
/* Recent documents menu */
o_true_file = [NSURL fileURLWithPath: o_uri];
- if( o_true_file != nil )
+ if( o_true_file != nil && (BOOL)config_GetInt( p_playlist, "macosx-recentitems" ) == YES )
{
[[NSDocumentController sharedDocumentController]
noteNewRecentDocumentURL: o_true_file];
}
/* Add the item */
+ /* FIXME: playlist_AddInput() can fail */
playlist_AddInput( p_playlist, p_input, PLAYLIST_INSERT,
i_position == -1 ? PLAYLIST_END : i_position + i_item, VLC_TRUE,
VLC_FALSE );
}
/* Add the item */
+ /* FIXME: playlist_NodeAddInput() can fail */
playlist_NodeAddInput( p_playlist, p_input, p_node,
PLAYLIST_INSERT,
i_position == -1 ?
[o_outline_dict setObject:o_value forKey:[NSString stringWithFormat:@"%p",
[o_value pointerValue]]];
+#ifndef NDEBUG
msg_Dbg( VLCIntf, "adding item %p", [o_value pointerValue] );
+#endif
return o_value;
}
/* 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])
+ 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;
/* 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] || item == nil) )
+ 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;