1 /*****************************************************************************
2 * playlist.m: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2002-2003 VideoLAN
5 * $Id: playlist.m,v 1.20 2003/04/15 14:05:13 hartman Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Derk-Jan Hartman <thedj@users.sourceforge.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <sys/param.h> /* for MAXPATHLEN */
35 /*****************************************************************************
36 * VLCPlaylistView implementation
37 *****************************************************************************/
38 @implementation VLCPlaylistView
42 if( o_striped_row_color != nil )
44 [o_striped_row_color release];
49 - (NSMenu *)menuForEvent:(NSEvent *)o_event
51 return( [[self delegate] menuForEvent: o_event] );
54 - (void)keyDown:(NSEvent *)o_event
58 playlist_t * p_playlist;
59 intf_thread_t * p_intf = [NSApp getIntf];
61 if( [[o_event characters] length] )
63 key = [[o_event characters] characterAtIndex: 0];
66 p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
69 if ( p_playlist == NULL )
77 vlc_mutex_lock( &p_playlist->object_lock );
78 if( p_playlist->p_input != NULL )
80 input_SetStatus( p_playlist->p_input, INPUT_STATUS_PAUSE );
82 vlc_mutex_unlock( &p_playlist->object_lock );
85 case NSDeleteCharacter:
86 case NSDeleteFunctionKey:
87 case NSDeleteCharFunctionKey:
88 case NSBackspaceCharacter:
89 while( ( i_row = [self selectedRow] ) != -1 )
91 if( p_playlist->i_index == i_row && p_playlist->i_status )
93 playlist_Stop( p_playlist );
96 playlist_Delete( p_playlist, i_row );
98 [self deselectRow: i_row];
104 [super keyDown: o_event];
108 if( p_playlist != NULL )
110 vlc_object_release( p_playlist );
114 - (void) highlightSelectionInClipRect:(NSRect)o_rect {
116 float f_height = [self rowHeight] + [self intercellSpacing].height;
117 float f_origin_y = NSMaxY( o_rect );
118 int i_row = o_rect.origin.y / f_height;
120 if ( i_row % 2 == 0 )
125 o_new_rect.size.width = o_rect.size.width;
126 o_new_rect.size.height = f_height;
127 o_new_rect.origin.x = o_rect.origin.x;
128 o_new_rect.origin.y = i_row * f_height;
130 if ( o_striped_row_color == nil )
132 o_striped_row_color = [[[NSColor alternateSelectedControlColor]
133 highlightWithLevel: 0.90] retain];
135 [o_striped_row_color set];
137 while ( o_new_rect.origin.y < f_origin_y ) {
138 NSRectFill( o_new_rect );
139 o_new_rect.origin.y += f_height * 2.0;
141 [super highlightSelectionInClipRect:o_rect];
146 /*****************************************************************************
147 * VLCPlaylist implementation
148 *****************************************************************************/
149 @implementation VLCPlaylist
163 [o_table_view setTarget: self];
164 [o_table_view setDelegate: self];
165 [o_table_view setDataSource: self];
167 [o_table_view setDoubleAction: @selector(playItem:)];
169 [o_table_view registerForDraggedTypes:
170 [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
172 [o_mi_play setTitle: _NS("Play")];
173 [o_mi_delete setTitle: _NS("Delete")];
174 [o_mi_selectall setTitle: _NS("Select All")];
176 [o_btn_add setToolTip: _NS("Add")];
177 [o_btn_remove setToolTip: _NS("Delete")];
180 - (BOOL)tableView:(NSTableView *)o_tv
181 shouldEditTableColumn:(NSTableColumn *)o_tc
187 - (NSMenu *)menuForEvent:(NSEvent *)o_event
191 vlc_bool_t b_item_sel;
193 pt = [o_table_view convertPoint: [o_event locationInWindow]
195 b_item_sel = ( [o_table_view rowAtPoint: pt] != -1 &&
196 [o_table_view selectedRow] != -1 );
197 b_rows = [o_table_view numberOfRows] != 0;
199 [o_mi_play setEnabled: b_item_sel];
200 [o_mi_delete setEnabled: b_item_sel];
201 [o_mi_selectall setEnabled: b_rows];
203 return( o_ctx_menu );
206 - (IBAction)playItem:(id)sender
208 intf_thread_t * p_intf = [NSApp getIntf];
209 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
212 if( p_playlist == NULL )
217 playlist_Goto( p_playlist, [o_table_view selectedRow] );
219 vlc_object_release( p_playlist );
222 - (IBAction)deleteItems:(id)sender
226 intf_thread_t * p_intf = [NSApp getIntf];
227 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
230 if( p_playlist == NULL )
235 while( ( i_row = [o_table_view selectedRow] ) != -1 )
237 if( p_playlist->i_index == i_row && p_playlist->i_status )
239 playlist_Stop( p_playlist );
242 playlist_Delete( p_playlist, i_row );
244 [o_table_view deselectRow: i_row];
247 vlc_object_release( p_playlist );
249 /* this is actually duplicity, because the intf.m manage also updates the view
250 * when the playlist changes. we do this on purpose, because else there is a
251 * delay of .5 sec or so when we delete an item */
252 [self playlistUpdated];
255 - (IBAction)selectAll:(id)sender
257 [o_table_view selectAll: nil];
260 - (void)appendArray:(NSArray*)o_array atPos:(int)i_pos enqueue:(BOOL)b_enqueue
264 NSEnumerator * o_enum;
265 intf_thread_t * p_intf = [NSApp getIntf];
266 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
269 if( p_playlist == NULL )
275 o_enum = [o_array objectEnumerator];
276 while( ( o_value = [o_enum nextObject] ) )
280 int i_mode = PLAYLIST_INSERT;
282 if (i_items == 0 && !b_enqueue)
283 i_mode |= PLAYLIST_GO;
285 playlist_Add( p_playlist, [o_value fileSystemRepresentation],
286 i_mode, i_pos == -1 ? PLAYLIST_END : i_pos + i_items );
288 o_url = [NSURL fileURLWithPath: o_value];
291 [[NSDocumentController sharedDocumentController]
292 noteNewRecentDocumentURL: o_url];
298 vlc_object_release( p_playlist );
301 - (void)playlistUpdated
303 [o_table_view reloadData];
306 - (void)updateRowSelection
310 intf_thread_t * p_intf = [NSApp getIntf];
311 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
314 if( p_playlist == NULL )
319 vlc_mutex_lock( &p_playlist->object_lock );
320 i_row = p_playlist->i_index;
321 vlc_mutex_unlock( &p_playlist->object_lock );
322 vlc_object_release( p_playlist );
324 [o_table_view selectRow: i_row byExtendingSelection: NO];
325 [o_table_view scrollRowToVisible: i_row];
330 @implementation VLCPlaylist (NSTableDataSource)
332 - (int)numberOfRowsInTableView:(NSTableView *)o_tv
335 intf_thread_t * p_intf = [NSApp getIntf];
336 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
339 if( p_playlist != NULL )
341 vlc_mutex_lock( &p_playlist->object_lock );
342 i_count = p_playlist->i_size;
343 vlc_mutex_unlock( &p_playlist->object_lock );
344 vlc_object_release( p_playlist );
350 - (id)tableView:(NSTableView *)o_tv
351 objectValueForTableColumn:(NSTableColumn *)o_tc
355 intf_thread_t * p_intf = [NSApp getIntf];
356 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
359 if( p_playlist == NULL )
364 vlc_mutex_lock( &p_playlist->object_lock );
365 o_value = [[NSString stringWithUTF8String:
366 p_playlist->pp_items[i_row]->psz_name] lastPathComponent];
367 vlc_mutex_unlock( &p_playlist->object_lock );
369 vlc_object_release( p_playlist );
374 - (BOOL)tableView:(NSTableView *)o_tv
375 writeRows:(NSArray*)o_rows
376 toPasteboard:(NSPasteboard*)o_pasteboard
378 int i_rows = [o_rows count];
379 NSArray *o_filenames = [NSArray array];
381 [o_pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
382 [o_pasteboard setPropertyList:o_filenames forType:NSFilenamesPboardType];
385 i_moveRow = [[o_rows objectAtIndex:0]intValue];
391 - (NSDragOperation)tableView:(NSTableView*)o_tv
392 validateDrop:(id <NSDraggingInfo>)o_info
393 proposedRow:(int)i_row
394 proposedDropOperation:(NSTableViewDropOperation)o_operation
396 if ( o_operation == NSTableViewDropAbove )
398 if ( i_moveRow >= 0 )
400 if ( i_row != i_moveRow )
402 return NSDragOperationMove;
404 /* what if in the previous run, the row wasn't actually moved?
405 then we can't drop new files on this location */
406 return NSDragOperationNone;
408 return NSDragOperationGeneric;
410 return NSDragOperationNone;
413 - (BOOL)tableView:(NSTableView*)o_tv
414 acceptDrop:(id <NSDraggingInfo>)o_info
415 row:(int)i_proposed_row
416 dropOperation:(NSTableViewDropOperation)o_operation
418 if ( i_moveRow >= 0 )
420 if (i_moveRow != -1 && i_proposed_row != -1)
422 intf_thread_t * p_intf = [NSApp getIntf];
423 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
426 if( p_playlist == NULL )
432 playlist_Move( p_playlist, i_moveRow, i_proposed_row );
434 vlc_object_release( p_playlist );
436 [self playlistUpdated];
443 NSPasteboard * o_pasteboard;
445 intf_thread_t * p_intf = [NSApp getIntf];
446 o_pasteboard = [o_info draggingPasteboard];
448 if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
450 o_values = [[o_pasteboard propertyListForType: NSFilenamesPboardType]
451 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
452 [self appendArray: o_values atPos: i_proposed_row enqueue:YES];
454 config_PutPsz( p_intf, "sub-file", "" );
455 config_PutInt( p_intf, "sub-delay", 0 );
456 config_PutFloat( p_intf, "sub-fps", 0.0 );
457 config_PutPsz( p_intf, "sout", "" );
464 [self updateRowSelection];