open.m 19.4 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * open.m: MacOS X plugin for vlc
 *****************************************************************************
 * Copyright (C) 2002 VideoLAN
5
 * $Id: open.m,v 1.6 2003/01/05 02:39:48 massiot Exp $
6
7
 *
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> 
8
 *          Christophe Massiot <massiot@via.ecp.fr>
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
40
41
42
43
44
45
46
47
 *
 * 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 <paths.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IOCDMedia.h>
#include <IOKit/storage/IODVDMedia.h>

#import <Cocoa/Cocoa.h>

#include <vlc/vlc.h>
#include <vlc/intf.h>

#include "netutils.h"

#import "intf.h"
#import "playlist.h"
48
#import "open.h"
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

/*****************************************************************************
 * GetEjectableMediaOfClass 
 *****************************************************************************/
NSArray *GetEjectableMediaOfClass( const char *psz_class )
{
    io_object_t next_media;
    mach_port_t master_port;
    kern_return_t kern_result;
    NSArray *o_devices = nil;
    NSMutableArray *p_list = nil;
    io_iterator_t media_iterator;
    CFMutableDictionaryRef classes_to_match;

    kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
    if( kern_result != KERN_SUCCESS )
    {
        return( nil );
    }
    
    classes_to_match = IOServiceMatching( psz_class );
    if( classes_to_match == NULL )
    {
        return( nil );
    }
    
    CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectable ), 
                          kCFBooleanTrue );
    
    kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, 
                                                &media_iterator );
    if( kern_result != KERN_SUCCESS )
    {
        return( nil );
    }

    p_list = [NSMutableArray arrayWithCapacity: 1];
    
    next_media = IOIteratorNext( media_iterator );
    if( next_media != NULL )
    {
        char psz_buf[0x32];
        size_t dev_path_length;
        CFTypeRef str_bsd_path;
    
        do
        {
            str_bsd_path = IORegistryEntryCreateCFProperty( next_media,
                                                            CFSTR( kIOBSDName ),
                                                            kCFAllocatorDefault,
                                                            0 );
            if( str_bsd_path == NULL )
            {
                IOObjectRelease( next_media );
                continue;
            }
            
            snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
            dev_path_length = strlen( psz_buf );
            
            if( CFStringGetCString( str_bsd_path,
                                    (char*)&psz_buf + dev_path_length,
                                    sizeof(psz_buf) - dev_path_length,
                                    kCFStringEncodingASCII ) )
            {
                [p_list addObject: [NSString stringWithCString: psz_buf]];
            }
            
            CFRelease( str_bsd_path );
            
            IOObjectRelease( next_media );
        
        } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
    }
    
    IOObjectRelease( media_iterator );

    o_devices = [NSArray arrayWithArray: p_list];

    return( o_devices );
}

/*****************************************************************************
 * VLCOpen implementation 
 *****************************************************************************/
@implementation VLCOpen

- (void)awakeFromNib
{
138
139
    intf_thread_t * p_intf = [NSApp getIntf];

140
    [o_panel setTitle: _NS("Open Target")];
141
    [o_mrl_lbl setTitle: _NS("Media Resource Locator (MRL)")];
142
143
144
145
146
147
148
149
150

    [o_btn_ok setTitle: _NS("OK")];
    [o_btn_cancel setTitle: _NS("Cancel")];

    [[o_tabview tabViewItemAtIndex: 0] setLabel: _NS("File")];
    [[o_tabview tabViewItemAtIndex: 1] setLabel: _NS("Disc")];
    [[o_tabview tabViewItemAtIndex: 2] setLabel: _NS("Network")];

    [o_file_btn_browse setTitle: _NS("Browse...")];
151
    [o_file_stream setTitle: _NS("Treat as a pipe rather than as a file")];
152
153
154
155

    [o_disc_device_lbl setStringValue: _NS("Device name")];
    [o_disc_title_lbl setStringValue: _NS("Title")];
    [o_disc_chapter_lbl setStringValue: _NS("Chapter")];
156
    [o_disc_videots_btn_browse setStringValue: _NS("Browse...")];
157
    [o_disc_dvd_menus setTitle: _NS("Use DVD menus")];
158

159
160
    [[o_disc_type cellAtRow:0 column:0] setTitle: _NS("VIDEO_TS folder")];
    [[o_disc_type cellAtRow:1 column:0] setTitle: _NS("DVD")];
161
    [[o_disc_type cellAtRow:2 column:0] setTitle: _NS("VCD")];
162
163
164
165
166
167
168
169

    [o_net_udp_port_lbl setStringValue: _NS("Port")];
    [o_net_udpm_addr_lbl setStringValue: _NS("Address")];
    [o_net_udpm_port_lbl setStringValue: _NS("Port")];
    [o_net_cs_addr_lbl setStringValue: _NS("Address")];
    [o_net_cs_port_lbl setStringValue: _NS("Port")];
    [o_net_http_url_lbl setStringValue: _NS("URL")];

170
171
172
173
174
175
176
177
178
179
    [[o_net_mode cellAtRow:0 column:0] setTitle: _NS("UDP/RTP")];
    [[o_net_mode cellAtRow:1 column:0] setTitle: _NS("UDP/RTP Multicast")];
    [[o_net_mode cellAtRow:2 column:0] setTitle: _NS("Channel server")];
    [[o_net_mode cellAtRow:3 column:0] setTitle: _NS("HTTP/FTP/MMS")];

    [o_net_udp_port setIntValue: config_GetInt( p_intf, "server-port" )];
    [o_net_udp_port_stp setIntValue: config_GetInt( p_intf, "server-port" )];
    [o_net_cs_port setIntValue: config_GetInt( p_intf, "channel-port" )];
    [o_net_cs_port_stp setIntValue: config_GetInt( p_intf, "channel-port" )];

180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openFilePathChanged:)
        name: NSControlTextDidChangeNotification
        object: o_file_path];

    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_device];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_title];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_chapter];
197
198
199
200
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_videots_folder];
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_udp_port];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_udpm_addr];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_udpm_port];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_cs_addr];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_cs_port];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openNetInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_net_http_url];
226
227
}

228
- (void)openTarget:(int)i_type
229
230
231
{
    int i_result;

232
233
234
235
    [o_tabview selectTabViewItemAtIndex: i_type];

    i_result = [NSApp runModalForWindow: o_panel];
    [o_panel close];
236
237
238

    if( i_result )
    {
239
        NSString *o_source = [o_mrl stringValue];
240
241
242
243
244
245

        [o_playlist appendArray: 
            [NSArray arrayWithObject: o_source] atPos: -1];
    }
}

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
- (void)tabView:(NSTabView *)o_tv didSelectTabViewItem:(NSTabViewItem *)o_tvi
{
    NSString *o_label = [o_tvi label];

    if( [o_label isEqualToString: _NS("File")] )
    {
        [self openFilePathChanged: nil];
    }
    else if( [o_label isEqualToString: _NS("Disc")] )
    {
        [self openDiscTypeChanged: nil];
    }
    else if( [o_label isEqualToString: _NS("Network")] )
    {
        [self openNetModeChanged: nil];
    }  
}

264
- (IBAction)openFileGeneric:(id)sender
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
{
    [self openFilePathChanged: nil];
    [self openTarget: 0];
}

- (IBAction)openDisc:(id)sender
{
    [self openDiscTypeChanged: nil];
    [self openTarget: 1];
}

- (IBAction)openNet:(id)sender
{
    [self openNetModeChanged: nil];
    [self openTarget: 2];
}

- (void)openFilePathChanged:(NSNotification *)o_notification
{
    NSString *o_mrl_string;
    NSString *o_filename = [o_file_path stringValue];
286
    vlc_bool_t b_stream = [o_file_stream state];
287

288
289
290
    o_mrl_string = [NSString stringWithFormat: @"%s://%@",
                    b_stream ? "stream" : "file",
                    o_filename];
291
292
293
    [o_mrl setStringValue: o_mrl_string]; 
}

294
295
296
297
298
- (IBAction)openFileStreamChanged:(id)sender
{
    [self openFilePathChanged: nil];
}

299
300
301
- (IBAction)openDiscTypeChanged:(id)sender
{
    NSString *o_type;
302
    vlc_bool_t b_device, b_menus, b_title_chapter;
303
304
    
    [o_disc_device removeAllItems];
305
    b_title_chapter = ![o_disc_dvd_menus state];
306
307
308
    
    o_type = [[o_disc_type selectedCell] title];

309
    if ( [o_type isEqualToString: _NS("VIDEO_TS folder")] )
310
    {
311
        b_device = 0; b_menus = 1;
312
313
314
    }
    else
    {
315
316
317
        NSArray *o_devices;
        NSString *o_disc;
        const char *psz_class = NULL;
318
        b_device = 1;
319
320
321
322
323

        if ( [o_type isEqualToString: _NS("VCD")] )
        {
            psz_class = kIOCDMediaClass;
            o_disc = o_type;
324
325
            b_menus = 0; b_title_chapter = 1;
            [o_disc_dvd_menus setState: FALSE];
326
        }
327
        else
328
329
330
        {
            psz_class = kIODVDMediaClass;
            o_disc = o_type;
331
            b_menus = 1;
332
        }
333
    
334
335
        o_devices = GetEjectableMediaOfClass( psz_class );
        if ( o_devices != nil )
336
        {
337
            int i_devices = [o_devices count];
338
        
339
            if ( i_devices )
340
            {
341
342
343
344
345
346
347
348
349
350
351
352
353
354
                int i;
        
                for( i = 0; i < i_devices; i++ )
                {
                    [o_disc_device 
                        addItemWithObjectValue: [o_devices objectAtIndex: i]];
                }

                [o_disc_device selectItemAtIndex: 0];
            }
            else
            {
                [o_disc_device setStringValue: 
                    [NSString stringWithFormat: _NS("No %@s found"), o_disc]];
355
356
357
            }
        }
    }
358

359
360
361
362
363
    [o_disc_device setEnabled: b_device];
    [o_disc_title setEnabled: b_title_chapter];
    [o_disc_title_stp setEnabled: b_title_chapter];
    [o_disc_chapter setEnabled: b_title_chapter];
    [o_disc_chapter_stp setEnabled: b_title_chapter];
364
365
366
    [o_disc_videots_folder setEnabled: !b_device];
    [o_disc_videots_btn_browse setEnabled: !b_device];
    [o_disc_dvd_menus setEnabled: b_menus];
367

368
    [self openDiscInfoChanged: nil];
369
370
}

371
- (IBAction)openDiscStepperChanged:(id)sender
372
{
373
    int i_tag = [sender tag];
374

375
    if( i_tag == 0 )
376
    {
377
        [o_disc_title setIntValue: [o_disc_title_stp intValue]];
378
    }
379
    else if( i_tag == 1 )
380
    {
381
382
        [o_disc_chapter setIntValue: [o_disc_chapter_stp intValue]];
    }
383

384
385
    [self openDiscInfoChanged: nil];
}
386

387
388
389
390
- (void)openDiscInfoChanged:(NSNotification *)o_notification
{
    NSString *o_type;
    NSString *o_device;
391
    NSString *o_videots;
392
393
    NSString *o_mrl_string;
    int i_title, i_chapter;
394
    vlc_bool_t b_menus;
395

396
397
398
399
    o_type = [[o_disc_type selectedCell] title];
    o_device = [o_disc_device stringValue];
    i_title = [o_disc_title intValue];
    i_chapter = [o_disc_chapter intValue];
400
    o_videots = [o_disc_videots_folder stringValue];
401
    b_menus = [o_disc_dvd_menus state];
402
403

    if ( [o_type isEqualToString: _NS("VCD")] )
404
    {
405
406
407
408
409
        if ( [o_device isEqualToString:
                [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
            o_device = @"";
        o_mrl_string = [NSString stringWithFormat: @"vcd://%@@%i,%i",
                        o_device, i_title, i_chapter]; 
410
    }
411
    else if ( [o_type isEqualToString: _NS("DVD")] )
412
    {
413
414
415
        if ( [o_device isEqualToString:
                [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
            o_device = @"";
416
417
418
419
420
421
        if ( b_menus )
            o_mrl_string = [NSString stringWithFormat: @"dvdplay://%@",
                            o_device]; 
        else
            o_mrl_string = [NSString stringWithFormat: @"dvdold://%@@%i,%i",
                            o_device, i_title, i_chapter]; 
422
423
424
    }
    else /* VIDEO_TS folder */
    {
425
426
427
428
429
430
        if ( b_menus )
            o_mrl_string = [NSString stringWithFormat: @"dvdplay://%@",
                            o_videots]; 
        else
            o_mrl_string = [NSString stringWithFormat: @"dvdread://%@@%i,%i",
                            o_videots, i_title, i_chapter]; 
431
    }
432

433
    [o_mrl setStringValue: o_mrl_string]; 
434
435
}

436
437
438
439
440
441
- (IBAction)openDiscMenusChanged:(id)sender
{
    [self openDiscInfoChanged: nil];
    [self openDiscTypeChanged: nil];
}

442
443
- (IBAction)openNetModeChanged:(id)sender
{
444
445
446
447
448
    NSString *o_mode;
    BOOL b_udp = FALSE;
    BOOL b_udpm = FALSE;
    BOOL b_cs = FALSE;
    BOOL b_http = FALSE;
449
450
451

    o_mode = [[o_net_mode selectedCell] title];

452
453
    if( [o_mode isEqualToString: @"UDP/RTP"] ) b_udp = TRUE;   
    else if( [o_mode isEqualToString: @"UDP/RTP Multicast"] ) b_udpm = TRUE;
454
    else if( [o_mode isEqualToString: @"Channel server"] ) b_cs = TRUE;
455
    else if( [o_mode isEqualToString: @"HTTP/FTP/MMS"] ) b_http = TRUE;
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474

    [o_net_udp_port setEnabled: b_udp];
    [o_net_udp_port_stp setEnabled: b_udp];
    [o_net_udpm_addr setEnabled: b_udpm];
    [o_net_udpm_port setEnabled: b_udpm];
    [o_net_udpm_port_stp setEnabled: b_udpm];
    [o_net_cs_addr setEnabled: b_cs];
    [o_net_cs_port setEnabled: b_cs]; 
    [o_net_cs_port_stp setEnabled: b_cs]; 
    [o_net_http_url setEnabled: b_http];

    [self openNetInfoChanged: nil];
}

- (IBAction)openNetStepperChanged:(id)sender
{
    int i_tag = [sender tag];

    if( i_tag == 0 )
475
    {
476
        [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
477
    }
478
    else if( i_tag == 1 )
479
    {
480
        [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
481
    }
482
    else if( i_tag == 2 )
483
    {
484
        [o_net_cs_port setIntValue: [o_net_cs_port_stp intValue]];
485
486
    }

487
488
489
490
491
492
493
494
495
496
497
498
    [self openNetInfoChanged: nil];
}

- (void)openNetInfoChanged:(NSNotification *)o_notification
{
    NSString *o_mode;
    vlc_bool_t b_channel;
    NSString *o_mrl_string = [NSString string];
    intf_thread_t * p_intf = [NSApp getIntf];

    o_mode = [[o_net_mode selectedCell] title];

499
    b_channel = (vlc_bool_t)[o_mode isEqualToString: _NS("Channel server")]; 
500
501
    config_PutInt( p_intf, "network-channel", b_channel );

502
    if( [o_mode isEqualToString: _NS("UDP/RTP")] )
503
    {
504
505
506
507
        int i_port = [o_net_udp_port intValue];

        o_mrl_string = [NSString stringWithString: @"udp://"]; 

508
        if( i_port != config_GetInt( p_intf, "server-port" ) )
509
510
511
512
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @"@:%i", i_port]; 
        } 
513
    }
514
    else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) 
515
    {
516
517
518
519
        NSString *o_addr = [o_net_udpm_addr stringValue];
        int i_port = [o_net_udpm_port intValue];

        o_mrl_string = [NSString stringWithFormat: @"udp://@%@", o_addr]; 
520

521
        if( i_port != config_GetInt( p_intf, "server-port" ) )
522
523
524
525
526
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @":%i", i_port]; 
        } 
    }
527
    else if( [o_mode isEqualToString: _NS("Channel server")] )
528
    {
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
        NSString *o_addr = [o_net_cs_addr stringValue];
        int i_port = [o_net_cs_port intValue];

        if( p_intf->p_vlc->p_channel == NULL )
        {
            network_ChannelCreate( p_intf );
        } 

        config_PutPsz( p_intf, "channel-server", [o_addr lossyCString] ); 
        if( i_port < 65536 )
        {
            config_PutInt( p_intf, "channel-port", i_port );
        }

        /* FIXME: we should use a playlist server instead */
        o_mrl_string = [NSString stringWithString: @"udp://"];
545
    }
546
    else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] )
547
    {
548
549
        NSString *o_url = [o_net_http_url stringValue];

550
551
552
553
554
        if ( ![o_url hasPrefix:@"http:"] && ![o_url hasPrefix:@"ftp:"]
              && ![o_url hasPrefix:@"mms"] )
            o_mrl_string = [NSString stringWithFormat: @"http://%@", o_url];
        else
            o_mrl_string = o_url;
555
    }
556
557

    [o_mrl setStringValue: o_mrl_string];
558
559
}

560
- (IBAction)openFileBrowse:(id)sender
561
{
562
563
564
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
    
    [o_open_panel setAllowsMultipleSelection: NO];
565
566
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];
567

568
569
    if( [o_open_panel runModalForDirectory: nil 
            file: nil types: nil] == NSOKButton )
570
    {
571
572
573
        NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
        [o_file_path setStringValue: o_filename];
        [self openFilePathChanged: nil];
574
575
576
    }
}

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
- (IBAction)openVTSBrowse:(id)sender
{
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];

    [o_open_panel setAllowsMultipleSelection: NO];
    [o_open_panel setCanChooseFiles: NO];
    [o_open_panel setCanChooseDirectories: YES];
    [o_open_panel setTitle: _NS("Open VIDEO_TS Directory")];
    [o_open_panel setPrompt: _NS("Open")];

    if( [o_open_panel runModalForDirectory: nil
            file: nil types: nil] == NSOKButton )
    {
        NSString *o_dirname = [[o_open_panel filenames] objectAtIndex: 0];
        [o_disc_videots_folder setStringValue: o_dirname];
        [self openDiscInfoChanged: nil];
    }
}

596
597
598
599
600
- (IBAction)openFile:(id)sender
{
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];

    [o_open_panel setAllowsMultipleSelection: NO];
601
602
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];
603
604
605
606
607
608
609
610

    if( [o_open_panel runModalForDirectory: nil
            file: nil types: nil] == NSOKButton )
    {
        [o_playlist appendArray: [o_open_panel filenames] atPos: -1];
    }
}

611
612
613
614
615
616
617
- (IBAction)panelCancel:(id)sender
{
    [NSApp stopModalWithCode: 0];
}

- (IBAction)panelOk:(id)sender
{
618
619
620
621
622
623
624
625
    if( [[o_mrl stringValue] length] )
    {
        [NSApp stopModalWithCode: 1];
    }
    else
    {
        NSBeep();
    }
626
627
628
}

@end