]> git.sesse.net Git - vlc/blob - modules/gui/macosx/playlist.m
4af3cf5ecce30672d2e3be612d13c4bca3496553
[vlc] / modules / gui / macosx / playlist.m
1 /*****************************************************************************
2  * playlist.m: MacOS X interface plugin
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: playlist.m,v 1.11 2003/02/13 14:16:41 hartman Exp $
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <sys/param.h>                                    /* for MAXPATHLEN */
29 #include <string.h>
30
31 #include "intf.h"
32 #include "playlist.h"
33
34 /*****************************************************************************
35  * VLCPlaylistView implementation 
36  *****************************************************************************/
37 @implementation VLCPlaylistView
38
39 - (NSMenu *)menuForEvent:(NSEvent *)o_event
40 {
41     return( [[self delegate] menuForEvent: o_event] );
42 }
43
44 - (void)keyDown:(NSEvent *)o_event
45 {
46     unichar key = 0;
47     int i_row;
48     playlist_t * p_playlist;
49     intf_thread_t * p_intf = [NSApp getIntf];
50
51     if( [[o_event characters] length] )
52     {
53         key = [[o_event characters] characterAtIndex: 0];
54     }
55
56     p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
57                                           FIND_ANYWHERE );
58     
59     if ( p_playlist == NULL )
60     {
61         return;
62     }
63     
64     switch( key )
65     {
66         case ' ':
67             vlc_mutex_lock( &p_playlist->object_lock );
68             if( p_playlist != NULL && p_playlist->p_input != NULL )
69             {
70                 input_SetStatus( p_playlist->p_input, INPUT_STATUS_PAUSE );
71             }
72             vlc_mutex_unlock( &p_playlist->object_lock );
73             break;
74
75         case NSDeleteCharacter:
76         case NSDeleteFunctionKey:
77         case NSDeleteCharFunctionKey:
78         case NSBackspaceCharacter:
79             while( ( i_row = [self selectedRow] ) != -1 )
80             {
81                 if( p_playlist->i_index == i_row && p_playlist->i_status )
82                 {
83                     playlist_Stop( p_playlist );
84                 }
85         
86                 playlist_Delete( p_playlist, i_row ); 
87         
88                 [self deselectRow: i_row];
89             }
90             [self reloadData];
91             break;
92             
93         default:
94             [super keyDown: o_event];
95             break;
96     }
97
98     if( p_playlist != NULL )
99     {
100         vlc_object_release( p_playlist );
101     }
102 }
103
104 @end
105
106 /*****************************************************************************
107  * VLCPlaylist implementation 
108  *****************************************************************************/
109 @implementation VLCPlaylist
110
111 - (void)awakeFromNib
112 {
113     [o_table_view setTarget: self];
114     [o_table_view setDelegate: self];
115     [o_table_view setDataSource: self];
116
117     [o_table_view setDoubleAction: @selector(playItem:)];
118
119     [o_table_view registerForDraggedTypes: 
120         [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
121
122     [o_mi_play setTitle: _NS("Play")];
123     [o_mi_delete setTitle: _NS("Delete")];
124     [o_mi_selectall setTitle: _NS("Select All")];
125 }
126
127 - (BOOL)tableView:(NSTableView *)o_tv 
128                   shouldEditTableColumn:(NSTableColumn *)o_tc
129                   row:(int)i_row
130 {
131     return( NO );
132 }
133
134 - (NSDragOperation)tableView:(NSTableView*)o_tv 
135                    validateDrop:(id <NSDraggingInfo>)info 
136                    proposedRow:(int)i_row 
137                    proposedDropOperation:(NSTableViewDropOperation)operation
138 {
139     return( NSDragOperationPrivate );
140 }
141
142 - (BOOL)tableView:(NSTableView*)o_tv 
143                   acceptDrop:(id <NSDraggingInfo>)info 
144                   row:(int)i_row 
145                   dropOperation:(NSTableViewDropOperation)operation
146 {
147     NSArray * o_values;
148     NSPasteboard * o_pasteboard;
149
150     o_pasteboard = [info draggingPasteboard];
151
152     if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
153     {
154         o_values = [o_pasteboard propertyListForType: NSFilenamesPboardType];
155
156         [self appendArray: o_values atPos: i_row enqueue:YES];
157
158         return( YES );
159     }
160
161     return( NO ); 
162 }
163
164 - (void)tableView:(NSTableView *)o_tv willDisplayCell:(id)o_cell
165                   forTableColumn:(NSTableColumn *)o_tc row:(int)i_row
166 {
167     NSColor * o_color;
168
169     [o_cell setDrawsBackground: YES];
170
171     if( i_row % 2 )
172     {
173         o_color = [[NSColor alternateSelectedControlColor]
174                             highlightWithLevel: 0.90];
175     }
176     else
177     {
178         o_color = [o_tv backgroundColor]; 
179     }
180
181     [o_cell setBackgroundColor: o_color];
182 }
183
184 - (NSMenu *)menuForEvent:(NSEvent *)o_event
185 {
186     NSPoint pt;
187     vlc_bool_t b_rows;
188     vlc_bool_t b_item_sel;
189
190     pt = [o_table_view convertPoint: [o_event locationInWindow] 
191                                                  fromView: nil];
192     b_item_sel = ( [o_table_view rowAtPoint: pt] != -1 &&
193                    [o_table_view selectedRow] != -1 );
194     b_rows = [o_table_view numberOfRows] != 0;
195
196     [o_mi_play setEnabled: b_item_sel];
197     [o_mi_delete setEnabled: b_item_sel];
198     [o_mi_selectall setEnabled: b_rows];
199
200     return( o_ctx_menu );
201 }
202
203 - (IBAction)playItem:(id)sender
204 {
205     intf_thread_t * p_intf = [NSApp getIntf];
206     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
207                                                        FIND_ANYWHERE );
208
209     if( p_playlist == NULL )
210     {
211         return;
212     }
213
214     playlist_Goto( p_playlist, [o_table_view selectedRow] );
215
216     vlc_object_release( p_playlist );
217 }
218
219 - (IBAction)deleteItems:(id)sender
220 {
221     int i_row;
222
223     intf_thread_t * p_intf = [NSApp getIntf];
224     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
225                                                        FIND_ANYWHERE );
226
227     if( p_playlist == NULL )
228     {
229         return;
230     }
231
232     while( ( i_row = [o_table_view selectedRow] ) != -1 )
233     {
234         if( p_playlist->i_index == i_row && p_playlist->i_status )
235         {
236             playlist_Stop( p_playlist );
237         }
238
239         playlist_Delete( p_playlist, i_row ); 
240
241         [o_table_view deselectRow: i_row];
242     }
243
244     vlc_object_release( p_playlist );
245
246     /* this is actually duplicity, because the intf.m manage also updates the view
247      * when the playlist changes. we do this on purpose, because else there is a 
248      * delay of .5 sec or so when we delete an item */
249     [self playlistUpdated];
250 }
251
252 - (IBAction)selectAll:(id)sender
253 {
254     [o_table_view selectAll: nil];
255 }
256
257 - (void)appendArray:(NSArray*)o_array atPos:(int)i_pos enqueue:(BOOL)b_enqueue
258 {
259     int i_items;
260     NSString * o_value;
261     NSEnumerator * o_enum;
262     intf_thread_t * p_intf = [NSApp getIntf];
263     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
264                                                        FIND_ANYWHERE );
265
266     if( p_playlist == NULL )
267     {
268         return;
269     }
270
271     i_items = 0;
272     o_enum = [o_array objectEnumerator];
273     while( ( o_value = [o_enum nextObject] ) )
274     {
275         NSURL * o_url;
276
277         int i_mode = PLAYLIST_INSERT;
278         
279         if (i_items == 0 && !b_enqueue)
280             i_mode |= PLAYLIST_GO;
281
282         playlist_Add( p_playlist, [o_value fileSystemRepresentation],
283             i_mode, i_pos == -1 ? PLAYLIST_END : i_pos + i_items );
284
285         o_url = [NSURL fileURLWithPath: o_value];
286         if( o_url != nil )
287         { 
288             [[NSDocumentController sharedDocumentController]
289                 noteNewRecentDocumentURL: o_url]; 
290         }
291
292         i_items++;
293     }
294
295     vlc_object_release( p_playlist );
296 }
297
298 - (void)playlistUpdated
299 {
300     [o_table_view reloadData];
301 }
302
303 - (void)updateState
304 {
305     int i_row;
306
307     intf_thread_t * p_intf = [NSApp getIntf];
308     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
309                                                        FIND_ANYWHERE );
310
311     if( p_playlist == NULL )
312     {
313         return;
314     }
315     
316     i_row = p_playlist->i_index;
317     vlc_object_release( p_playlist );
318     
319     [o_table_view selectRow: i_row byExtendingSelection: NO];
320     [o_table_view scrollRowToVisible: i_row];
321     
322     vout_thread_t * p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
323                                                           FIND_ANYWHERE );
324
325     if ( p_vout == NULL )
326     {
327         [[NSApp keyWindow] makeFirstResponder:o_table_view];
328         return;
329     }
330     else if ( !p_vout->b_fullscreen )
331     {
332         [[NSApp keyWindow] makeFirstResponder:o_table_view];
333     }
334     vlc_object_release( (vlc_object_t *)p_vout );
335 }
336
337 @end
338
339 @implementation VLCPlaylist (NSTableDataSource)
340
341 - (int)numberOfRowsInTableView:(NSTableView *)o_tv
342 {
343     int i_count = 0;
344     intf_thread_t * p_intf = [NSApp getIntf];
345     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
346                                                FIND_ANYWHERE );
347
348     if( p_playlist != NULL )
349     {
350         i_count = p_playlist->i_size;
351         vlc_object_release( p_playlist );
352     }
353
354     return( i_count );
355 }
356
357 - (id)tableView:(NSTableView *)o_tv 
358                 objectValueForTableColumn:(NSTableColumn *)o_tc 
359                 row:(int)i_row
360 {
361     id o_value = nil;
362     intf_thread_t * p_intf = [NSApp getIntf];
363     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
364                                                FIND_ANYWHERE );
365
366     if( p_playlist == NULL )
367     {
368         return( nil );
369     }
370
371     vlc_mutex_lock( &p_playlist->object_lock );
372     o_value = [[NSString stringWithUTF8String: 
373         p_playlist->pp_items[i_row]->psz_name] lastPathComponent]; 
374     vlc_mutex_unlock( &p_playlist->object_lock ); 
375
376     vlc_object_release( p_playlist );
377
378     return( o_value );
379 }
380
381 @end
382