playlist.m 12.7 KB
Newer Older
1
2
3
/*****************************************************************************
 * playlist.m: MacOS X interface plugin
 *****************************************************************************
4
 * Copyright (C) 2002-2003 VideoLAN
hartman's avatar
hartman committed
5
 * $Id: playlist.m,v 1.17 2003/03/17 23:13:06 hartman Exp $
6
7
 *
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
hartman's avatar
hartman committed
8
 *          Derk-Jan Hartman <thedj@users.sourceforge.net>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <sys/param.h>                                    /* for MAXPATHLEN */
#include <string.h>

#include "intf.h"
#include "playlist.h"

/*****************************************************************************
 * VLCPlaylistView implementation 
 *****************************************************************************/
@implementation VLCPlaylistView

hartman's avatar
hartman committed
40
41
42
43
44
45
46
47
48
- (void)dealloc
{
    if( o_striped_row_color != nil )
    {
        [o_striped_row_color release];
    }
    [super dealloc];
}

49
50
- (NSMenu *)menuForEvent:(NSEvent *)o_event
{
Jon Lech Johansen's avatar
Jon Lech Johansen committed
51
    return( [[self delegate] menuForEvent: o_event] );
52
53
}

54
55
56
- (void)keyDown:(NSEvent *)o_event
{
    unichar key = 0;
57
    int i_row;
58
59
    playlist_t * p_playlist;
    intf_thread_t * p_intf = [NSApp getIntf];
60
61
62
63
64
65

    if( [[o_event characters] length] )
    {
        key = [[o_event characters] characterAtIndex: 0];
    }

66
67
    p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                          FIND_ANYWHERE );
68
69
    
    if ( p_playlist == NULL )
70
    {
71
        return;
72
    }
73
    
74
75
76
    switch( key )
    {
        case ' ':
77
            vlc_mutex_lock( &p_playlist->object_lock );
78
            if( p_playlist->p_input != NULL )
79
80
81
            {
                input_SetStatus( p_playlist->p_input, INPUT_STATUS_PAUSE );
            }
82
            vlc_mutex_unlock( &p_playlist->object_lock );
83
84
            break;

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
        case NSDeleteCharacter:
        case NSDeleteFunctionKey:
        case NSDeleteCharFunctionKey:
        case NSBackspaceCharacter:
            while( ( i_row = [self selectedRow] ) != -1 )
            {
                if( p_playlist->i_index == i_row && p_playlist->i_status )
                {
                    playlist_Stop( p_playlist );
                }
        
                playlist_Delete( p_playlist, i_row ); 
        
                [self deselectRow: i_row];
            }
            [self reloadData];
            break;
            
103
104
105
106
        default:
            [super keyDown: o_event];
            break;
    }
107
108
109
110
111

    if( p_playlist != NULL )
    {
        vlc_object_release( p_playlist );
    }
112
113
}

hartman's avatar
hartman committed
114
115
116
117
118
119
120
121
122
- (void) highlightSelectionInClipRect:(NSRect)o_rect {
    NSRect o_new_rect;
    float f_height = [self rowHeight] + [self intercellSpacing].height;
    float f_origin_y = NSMaxY( o_rect );
    int i_row = o_rect.origin.y / f_height;
    
    if ( i_row % 2 == 0 )
    {
        i_row++;
hartman's avatar
hartman committed
123
    }
hartman's avatar
hartman committed
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    
    o_new_rect.size.width = o_rect.size.width;
    o_new_rect.size.height = f_height;
    o_new_rect.origin.x = o_rect.origin.x;
    o_new_rect.origin.y = i_row * f_height;
    
    if ( o_striped_row_color == nil )
    {
        o_striped_row_color = [[[NSColor alternateSelectedControlColor]
                                highlightWithLevel: 0.90] retain];
    }
    [o_striped_row_color set];
    
    while ( o_new_rect.origin.y < f_origin_y ) {
        NSRectFill( o_new_rect );
        o_new_rect.origin.y += f_height * 2.0;
    }
    [super highlightSelectionInClipRect:o_rect];
hartman's avatar
hartman committed
142
143
}

144
145
146
147
148
149
150
@end

/*****************************************************************************
 * VLCPlaylist implementation 
 *****************************************************************************/
@implementation VLCPlaylist

hartman's avatar
hartman committed
151
152
153
154
155
156
157
158
159
160
- (id)init
{
    self = [super init];
    if ( self !=nil )
    {
        i_moveRow = -1;
    }
    return self;
}

161
162
163
164
165
166
- (void)awakeFromNib
{
    [o_table_view setTarget: self];
    [o_table_view setDelegate: self];
    [o_table_view setDataSource: self];

Jon Lech Johansen's avatar
Jon Lech Johansen committed
167
    [o_table_view setDoubleAction: @selector(playItem:)];
168
169
170
171

    [o_table_view registerForDraggedTypes: 
        [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];

Jon Lech Johansen's avatar
Jon Lech Johansen committed
172
173
174
    [o_mi_play setTitle: _NS("Play")];
    [o_mi_delete setTitle: _NS("Delete")];
    [o_mi_selectall setTitle: _NS("Select All")];
hartman's avatar
hartman committed
175
176
177
    
    [o_btn_add setToolTip: _NS("Add")];
    [o_btn_remove setToolTip: _NS("Delete")];
178
179
180
181
182
183
184
185
186
}

- (BOOL)tableView:(NSTableView *)o_tv 
                  shouldEditTableColumn:(NSTableColumn *)o_tc
                  row:(int)i_row
{
    return( NO );
}

Jon Lech Johansen's avatar
Jon Lech Johansen committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
- (NSMenu *)menuForEvent:(NSEvent *)o_event
{
    NSPoint pt;
    vlc_bool_t b_rows;
    vlc_bool_t b_item_sel;

    pt = [o_table_view convertPoint: [o_event locationInWindow] 
                                                 fromView: nil];
    b_item_sel = ( [o_table_view rowAtPoint: pt] != -1 &&
                   [o_table_view selectedRow] != -1 );
    b_rows = [o_table_view numberOfRows] != 0;

    [o_mi_play setEnabled: b_item_sel];
    [o_mi_delete setEnabled: b_item_sel];
    [o_mi_selectall setEnabled: b_rows];

    return( o_ctx_menu );
}

- (IBAction)playItem:(id)sender
207
208
209
210
211
212
213
214
215
216
{
    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                       FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        return;
    }

Jon Lech Johansen's avatar
Jon Lech Johansen committed
217
    playlist_Goto( p_playlist, [o_table_view selectedRow] );
218
219
220
221

    vlc_object_release( p_playlist );
}

Jon Lech Johansen's avatar
Jon Lech Johansen committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
- (IBAction)deleteItems:(id)sender
{
    int i_row;

    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                       FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        return;
    }

    while( ( i_row = [o_table_view selectedRow] ) != -1 )
    {
        if( p_playlist->i_index == i_row && p_playlist->i_status )
        {
            playlist_Stop( p_playlist );
        }

        playlist_Delete( p_playlist, i_row ); 

        [o_table_view deselectRow: i_row];
    }

    vlc_object_release( p_playlist );

hartman's avatar
hartman committed
249
250
251
    /* this is actually duplicity, because the intf.m manage also updates the view
     * when the playlist changes. we do this on purpose, because else there is a 
     * delay of .5 sec or so when we delete an item */
Jon Lech Johansen's avatar
Jon Lech Johansen committed
252
253
254
255
256
257
258
259
    [self playlistUpdated];
}

- (IBAction)selectAll:(id)sender
{
    [o_table_view selectAll: nil];
}

260
- (void)appendArray:(NSArray*)o_array atPos:(int)i_pos enqueue:(BOOL)b_enqueue
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
{
    int i_items;
    NSString * o_value;
    NSEnumerator * o_enum;
    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                       FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        return;
    }

    i_items = 0;
    o_enum = [o_array objectEnumerator];
    while( ( o_value = [o_enum nextObject] ) )
    {
        NSURL * o_url;

280
281
282
283
        int i_mode = PLAYLIST_INSERT;
        
        if (i_items == 0 && !b_enqueue)
            i_mode |= PLAYLIST_GO;
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298

        playlist_Add( p_playlist, [o_value fileSystemRepresentation],
            i_mode, i_pos == -1 ? PLAYLIST_END : i_pos + i_items );

        o_url = [NSURL fileURLWithPath: o_value];
        if( o_url != nil )
        { 
            [[NSDocumentController sharedDocumentController]
                noteNewRecentDocumentURL: o_url]; 
        }

        i_items++;
    }

    vlc_object_release( p_playlist );
Jon Lech Johansen's avatar
Jon Lech Johansen committed
299
300
301
302
303
}

- (void)playlistUpdated
{
    [o_table_view reloadData];
304
305
}

306
- (void)updateRowSelection
hartman's avatar
ALL:    
hartman committed
307
308
309
310
311
312
313
314
315
316
317
{
    int i_row;

    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                       FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        return;
    }
318
319

    vlc_mutex_lock( &p_playlist->object_lock );    
hartman's avatar
ALL:    
hartman committed
320
    i_row = p_playlist->i_index;
321
    vlc_mutex_unlock( &p_playlist->object_lock );
hartman's avatar
ALL:    
hartman committed
322
    vlc_object_release( p_playlist );
323

hartman's avatar
ALL:    
hartman committed
324
325
326
327
    [o_table_view selectRow: i_row byExtendingSelection: NO];
    [o_table_view scrollRowToVisible: i_row];
}

328
329
330
331
332
333
334
335
336
@end

@implementation VLCPlaylist (NSTableDataSource)

- (int)numberOfRowsInTableView:(NSTableView *)o_tv
{
    int i_count = 0;
    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
337
                                                       FIND_ANYWHERE );
338
339
340

    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
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
        vlc_object_release( p_playlist );
    }

    return( i_count );
}

- (id)tableView:(NSTableView *)o_tv 
                objectValueForTableColumn:(NSTableColumn *)o_tc 
                row:(int)i_row
{
    id o_value = nil;
    intf_thread_t * p_intf = [NSApp getIntf];
    playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                               FIND_ANYWHERE );

    if( p_playlist == NULL )
    {
        return( nil );
    }

    vlc_mutex_lock( &p_playlist->object_lock );
365
366
    o_value = [[NSString stringWithUTF8String: 
        p_playlist->pp_items[i_row]->psz_name] lastPathComponent]; 
367
368
369
370
371
372
373
    vlc_mutex_unlock( &p_playlist->object_lock ); 

    vlc_object_release( p_playlist );

    return( o_value );
}

hartman's avatar
hartman committed
374
375
376
- (BOOL)tableView:(NSTableView *)o_tv
                    writeRows:(NSArray*)o_rows
                    toPasteboard:(NSPasteboard*)o_pasteboard 
hartman's avatar
hartman committed
377
{
hartman's avatar
hartman committed
378
    int i_rows = [o_rows count];
hartman's avatar
hartman committed
379
380
    NSArray *o_filenames = [NSArray array];
    
hartman's avatar
hartman committed
381
382
383
    [o_pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:self];
    [o_pasteboard setPropertyList:o_filenames forType:NSFilenamesPboardType];
    if ( i_rows == 1 )
hartman's avatar
hartman committed
384
    {
hartman's avatar
hartman committed
385
        i_moveRow = [[o_rows objectAtIndex:0]intValue];
hartman's avatar
hartman committed
386
387
388
389
390
        return YES;
    }
    return NO;
}

hartman's avatar
hartman committed
391
392
393
394
- (NSDragOperation)tableView:(NSTableView*)o_tv
                    validateDrop:(id <NSDraggingInfo>)o_info
                    proposedRow:(int)i_row
                    proposedDropOperation:(NSTableViewDropOperation)o_operation 
hartman's avatar
hartman committed
395
{
hartman's avatar
hartman committed
396
    if ( o_operation == NSTableViewDropAbove )
hartman's avatar
hartman committed
397
    {
hartman's avatar
hartman committed
398
        if ( i_moveRow >= 0 )
hartman's avatar
hartman committed
399
        {
hartman's avatar
hartman committed
400
401
402
403
404
405
406
            if ( i_row != i_moveRow )
            {
                return NSDragOperationMove;
            }
            /* what if in the previous run, the row wasn't actually moved? 
               then we can't drop new files on this location */
            return NSDragOperationNone;
hartman's avatar
hartman committed
407
        }
hartman's avatar
hartman committed
408
        return NSDragOperationGeneric;
hartman's avatar
hartman committed
409
410
411
412
    }
    return NSDragOperationNone;
}

hartman's avatar
hartman committed
413
414
415
416
- (BOOL)tableView:(NSTableView*)o_tv
                    acceptDrop:(id <NSDraggingInfo>)o_info
                    row:(int)i_proposed_row
                    dropOperation:(NSTableViewDropOperation)o_operation 
hartman's avatar
hartman committed
417
{
hartman's avatar
hartman committed
418
    if (  i_moveRow >= 0 )
hartman's avatar
hartman committed
419
    {
hartman's avatar
hartman committed
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
        if (i_moveRow != -1 && i_proposed_row != -1)
        {
            intf_thread_t * p_intf = [NSApp getIntf];
            playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                            FIND_ANYWHERE );
        
            if( p_playlist == NULL )
            {
                i_moveRow = -1;
                return NO;
            }
    
            playlist_Move( p_playlist, i_moveRow, i_proposed_row ); 
        
            vlc_object_release( p_playlist );
        }
hartman's avatar
hartman committed
436
        [self playlistUpdated];
hartman's avatar
hartman committed
437
438
        i_moveRow = -1;
        return YES;
hartman's avatar
hartman committed
439
440
441
442
443
444
    }
    else
    {
        NSArray * o_values;
        NSPasteboard * o_pasteboard;
        
hartman's avatar
hartman committed
445
        o_pasteboard = [o_info draggingPasteboard];
hartman's avatar
hartman committed
446
447
448
449
450
        
        if( [[o_pasteboard types] containsObject: NSFilenamesPboardType] )
        {
            o_values = [o_pasteboard propertyListForType: NSFilenamesPboardType];
        
hartman's avatar
hartman committed
451
            [self appendArray: o_values atPos: i_proposed_row enqueue:YES];
hartman's avatar
hartman committed
452
453
454
455
456
457
458
459
        
            return( YES );
        }
        
        return( NO );
    }
}

460
461
@end