open.m 28.2 KB
Newer Older
1
2
3
4
/*****************************************************************************
 * open.m: MacOS X plugin for vlc
 *****************************************************************************
 * Copyright (C) 2002 VideoLAN
5
 * $Id: open.m,v 1.19 2003/02/05 02:31:27 hartman Exp $
6
7
 *
 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> 
8
 *          Christophe Massiot <massiot@via.ecp.fr>
9
 *          Derk-Jan Hartman <thedj@users.sourceforge.net>
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 <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>

40
41
42
#include "intf.h"
#include "playlist.h"
#include "open.h"
43
44
45
46
47
48
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

#include "netutils.h"

/*****************************************************************************
 * 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
{
134
    intf_thread_t * p_intf = [NSApp getIntf];
Christophe Massiot's avatar
Christophe Massiot committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    char * psz_sout = config_GetPsz( p_intf, "sout" );

    if ( psz_sout != NULL && *psz_sout )
    {
        [o_sout_cbox setState: YES];

        NSRect s_rect = [o_panel frame];
        s_rect.size.height = OPEN_PANEL_FULL_HEIGHT + WINDOW_TITLE_HEIGHT;
        [o_panel setFrame: s_rect display: NO];

        NSPoint s_point;
        s_point.x = 0;
        s_point.y = 0;
        [[o_panel contentView] setBoundsOrigin: s_point];
    }
    else
    {
        [o_sout_cbox setState: NO];

        NSRect s_rect = [o_panel frame];
        s_rect.size.height = OPEN_PANEL_SHORT_HEIGHT + WINDOW_TITLE_HEIGHT;
        [o_panel setFrame: s_rect display: NO];

        NSPoint s_point;
        s_point.x = 0;
        s_point.y = OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
        [[o_panel contentView] setBoundsOrigin: s_point];
    }
hartman's avatar
hartman committed
163
    free(psz_sout);
164

165
    [o_panel setTitle: _NS("Open Source")];
166
    [o_mrl_lbl setTitle: _NS("Media Resource Locator (MRL)")];
167
    [o_ckbox_enqueue setTitle: _NS("Only enqueue in playlist. Do not play.")];
168
169
170
171
172
173
174
175
176

    [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...")];
177
    [o_file_stream setTitle: _NS("Treat as a pipe rather than as a file")];
178

179
180
181
    [o_file_sub_btn_browse setTitle: _NS("Browse...")];
    [o_file_sub_ckbox setTitle: _NS("Load subtitles")];

182
183
184
    [o_disc_device_lbl setStringValue: _NS("Device name")];
    [o_disc_title_lbl setStringValue: _NS("Title")];
    [o_disc_chapter_lbl setStringValue: _NS("Chapter")];
185
    [o_disc_videots_btn_browse setTitle: _NS("Browse...")];
186
    [o_disc_dvd_menus setTitle: _NS("Use DVD menus (EXPERIMENTAL)")];
187

188
189
    [[o_disc_type cellAtRow:0 column:0] setTitle: _NS("VIDEO_TS folder")];
    [[o_disc_type cellAtRow:1 column:0] setTitle: _NS("DVD")];
190
    [[o_disc_type cellAtRow:2 column:0] setTitle: _NS("VCD")];
191
192
193
194
195
196
197
198

    [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")];

199
200
201
202
203
204
205
206
207
208
    [[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" )];

Christophe Massiot's avatar
Christophe Massiot committed
209
210
211
212
213
214
    [o_sout_cbox setTitle: _NS("Stream output")];
    [o_sout_mrl_lbl setTitle: _NS("Stream output MRL")];
    [[o_sout_access cellAtRow:0 column:0] setTitle: _NS("File")];
    [[o_sout_access cellAtRow:1 column:0] setTitle: _NS("UDP")];
    [[o_sout_access cellAtRow:2 column:0] setTitle: _NS("RTP")];

215
    [o_sout_file_btn_browse setTitle: _NS("Browse...")];
Christophe Massiot's avatar
Christophe Massiot committed
216
217
218
    [o_sout_udp_addr_lbl setStringValue: _NS("Address")];
    [o_sout_udp_port_lbl setStringValue: _NS("Port")];

219
220
221
    [[o_sout_mux cellAtRow:0 column:0] setTitle: _NS("AVI")];
    [[o_sout_mux cellAtRow:0 column:1] setTitle: _NS("PS")];
    [[o_sout_mux cellAtRow:0 column:2] setTitle: _NS("TS")];
Christophe Massiot's avatar
Christophe Massiot committed
222

223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
    [[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];
240
241
242
243
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_videots_folder];
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

    [[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];
Christophe Massiot's avatar
Christophe Massiot committed
269
270
271
272
273
274
275
276
277
278
279
280
281

    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(soutInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_sout_file_path];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(soutInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_sout_udp_addr];
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(soutInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_sout_udp_port];
282
283
}

284
- (void)openTarget:(int)i_type
285
286
287
{
    int i_result;

288
    [o_tabview selectTabViewItemAtIndex: i_type];
289
290
    [o_ckbox_enqueue setState: NSOffState];
    [o_file_sub_path setStringValue: @""];
291
    [o_file_sub_ckbox setState: NSOnState];
292
293
294
    [o_file_sub_path setEnabled: NO];
    [o_file_sub_btn_browse setEnabled: NO];
    
295
296
    i_result = [NSApp runModalForWindow: o_panel];
    [o_panel close];
297
298
299

    if( i_result )
    {
Christophe Massiot's avatar
Christophe Massiot committed
300
        NSString *o_sout = [o_sout_mrl stringValue];
301
302
        intf_thread_t * p_intf = [NSApp getIntf];
        
Christophe Massiot's avatar
Christophe Massiot committed
303
304
305
306
307
        if ( [o_sout_cbox state] )
        {
            config_PutPsz( p_intf, "sout", [o_sout lossyCString] );
        }

308
        NSString *o_source = [o_mrl stringValue];
309
310
311
        BOOL b_enq = [o_ckbox_enqueue state] == NSOnState ? YES : NO;
        NSString *subPath = [o_file_sub_path stringValue];
        
312
        [o_playlist appendArray: 
313
314
315
316
            [NSArray arrayWithObject: o_source] atPos: -1 enqueue:b_enq];
        
        if (([o_file_sub_ckbox state] == NSOnState) && !([subPath isEqualTo: @""]))
            config_PutPsz( p_intf, "sub-file", strdup( [subPath cString] ) );
317
    }
Christophe Massiot's avatar
Christophe Massiot committed
318
319

    [self soutModeChanged: nil];
320
321
}

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
- (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];
    }  
}

340
- (IBAction)openFileGeneric:(id)sender
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
{
    [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];
hartman's avatar
hartman committed
362
    NSString *o_ext = [o_filename pathExtension];
363
    vlc_bool_t b_stream = [o_file_stream state];
364

hartman's avatar
hartman committed
365
366
367
368
369
370
371
372
373
374
375
376
377
    if ([o_ext isEqualToString: @"bin"] ||
        [o_ext isEqualToString: @"cue"] ||
        [o_ext isEqualToString: @"vob"] ||
        [o_ext isEqualToString: @"iso"])
    {
        o_mrl_string = o_filename;
    }
    else
    {
        o_mrl_string = [NSString stringWithFormat: @"%s://%@",
                        b_stream ? "stream" : "file",
                        o_filename];
    }
378
379
380
    [o_mrl setStringValue: o_mrl_string]; 
}

Christophe Massiot's avatar
Christophe Massiot committed
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
- (IBAction)openFileBrowse:(id)sender
{
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
    
    [o_open_panel setAllowsMultipleSelection: NO];
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];

    if( [o_open_panel runModalForDirectory: nil 
            file: nil types: nil] == NSOKButton )
    {
        NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
        [o_file_path setStringValue: o_filename];
        [self openFilePathChanged: nil];
    }
}

398
399
400
401
402
- (IBAction)openFileStreamChanged:(id)sender
{
    [self openFilePathChanged: nil];
}

403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
- (IBAction)loadSubsChanged:(id)sender
{
    if ([o_file_sub_ckbox state] == NSOnState)
    {
        [o_file_sub_path setEnabled:YES];
        [o_file_sub_btn_browse setEnabled:YES];
    }
    else
    {
        [o_file_sub_path setEnabled:NO];
        [o_file_sub_btn_browse setEnabled:NO];
    }
}

- (IBAction)openSubBrowse:(id)sender
{
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
    
    [o_open_panel setAllowsMultipleSelection: NO];
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];

    if( [o_open_panel runModalForDirectory: nil 
            file: nil types: nil] == NSOKButton )
    {
        NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
        [o_file_sub_path setStringValue: o_filename];
    }
}

433
434
435
- (IBAction)openDiscTypeChanged:(id)sender
{
    NSString *o_type;
436
    vlc_bool_t b_device, b_menus, b_title_chapter;
437
438
    
    [o_disc_device removeAllItems];
439
    b_title_chapter = ![o_disc_dvd_menus state];
440
441
442
    
    o_type = [[o_disc_type selectedCell] title];

443
    if ( [o_type isEqualToString: _NS("VIDEO_TS folder")] )
444
    {
445
        b_device = 0; b_menus = 1;
446
447
448
    }
    else
    {
449
450
451
        NSArray *o_devices;
        NSString *o_disc;
        const char *psz_class = NULL;
452
        b_device = 1;
453
454
455
456
457

        if ( [o_type isEqualToString: _NS("VCD")] )
        {
            psz_class = kIOCDMediaClass;
            o_disc = o_type;
458
459
            b_menus = 0; b_title_chapter = 1;
            [o_disc_dvd_menus setState: FALSE];
460
        }
461
        else
462
463
464
        {
            psz_class = kIODVDMediaClass;
            o_disc = o_type;
465
            b_menus = 1;
466
        }
467
    
468
469
        o_devices = GetEjectableMediaOfClass( psz_class );
        if ( o_devices != nil )
470
        {
471
            int i_devices = [o_devices count];
472
        
473
            if ( i_devices )
474
            {
475
476
477
478
479
480
481
482
483
484
485
486
487
488
                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]];
489
490
491
            }
        }
    }
492

493
494
495
496
497
    [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];
498
499
500
    [o_disc_videots_folder setEnabled: !b_device];
    [o_disc_videots_btn_browse setEnabled: !b_device];
    [o_disc_dvd_menus setEnabled: b_menus];
501

502
    [self openDiscInfoChanged: nil];
503
504
}

505
- (IBAction)openDiscStepperChanged:(id)sender
506
{
507
    int i_tag = [sender tag];
508

509
    if( i_tag == 0 )
510
    {
511
        [o_disc_title setIntValue: [o_disc_title_stp intValue]];
512
    }
513
    else if( i_tag == 1 )
514
    {
515
516
        [o_disc_chapter setIntValue: [o_disc_chapter_stp intValue]];
    }
517

518
519
    [self openDiscInfoChanged: nil];
}
520

521
522
523
524
- (void)openDiscInfoChanged:(NSNotification *)o_notification
{
    NSString *o_type;
    NSString *o_device;
525
    NSString *o_videots;
526
527
    NSString *o_mrl_string;
    int i_title, i_chapter;
528
    vlc_bool_t b_menus;
529

530
531
532
533
    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];
534
    o_videots = [o_disc_videots_folder stringValue];
535
    b_menus = [o_disc_dvd_menus state];
536
537

    if ( [o_type isEqualToString: _NS("VCD")] )
538
    {
539
540
541
542
543
        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]; 
544
    }
545
    else if ( [o_type isEqualToString: _NS("DVD")] )
546
    {
547
548
549
        if ( [o_device isEqualToString:
                [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
            o_device = @"";
550
551
552
553
554
555
        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]; 
556
557
558
    }
    else /* VIDEO_TS folder */
    {
559
560
561
562
563
564
        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]; 
565
    }
566

567
    [o_mrl setStringValue: o_mrl_string]; 
568
569
}

570
571
572
573
574
575
- (IBAction)openDiscMenusChanged:(id)sender
{
    [self openDiscInfoChanged: nil];
    [self openDiscTypeChanged: nil];
}

Christophe Massiot's avatar
Christophe Massiot committed
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
- (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];
    }
}

595
596
- (IBAction)openNetModeChanged:(id)sender
{
597
598
599
600
601
    NSString *o_mode;
    BOOL b_udp = FALSE;
    BOOL b_udpm = FALSE;
    BOOL b_cs = FALSE;
    BOOL b_http = FALSE;
602
603
604

    o_mode = [[o_net_mode selectedCell] title];

Christophe Massiot's avatar
Christophe Massiot committed
605
606
607
608
    if( [o_mode isEqualToString: _NS("UDP/RTP")] ) b_udp = TRUE;   
    else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) b_udpm = TRUE;
    else if( [o_mode isEqualToString: _NS("Channel server")] ) b_cs = TRUE;
    else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] ) b_http = TRUE;
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

    [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 )
628
    {
629
        [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
630
    }
631
    else if( i_tag == 1 )
632
    {
633
        [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
634
    }
635
    else if( i_tag == 2 )
636
    {
637
        [o_net_cs_port setIntValue: [o_net_cs_port_stp intValue]];
638
639
    }

640
641
642
643
644
645
646
647
648
649
650
651
    [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];

652
    b_channel = (vlc_bool_t)[o_mode isEqualToString: _NS("Channel server")]; 
653
654
    config_PutInt( p_intf, "network-channel", b_channel );

655
    if( [o_mode isEqualToString: _NS("UDP/RTP")] )
656
    {
657
658
659
660
        int i_port = [o_net_udp_port intValue];

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

661
        if( i_port != config_GetInt( p_intf, "server-port" ) )
662
663
664
665
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @"@:%i", i_port]; 
        } 
666
    }
667
    else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) 
668
    {
669
670
671
672
        NSString *o_addr = [o_net_udpm_addr stringValue];
        int i_port = [o_net_udpm_port intValue];

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

674
        if( i_port != config_GetInt( p_intf, "server-port" ) )
675
676
677
678
679
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @":%i", i_port]; 
        } 
    }
680
    else if( [o_mode isEqualToString: _NS("Channel server")] )
681
    {
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
        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://"];
698
    }
699
    else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] )
700
    {
701
702
        NSString *o_url = [o_net_http_url stringValue];

703
704
705
706
707
        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;
708
    }
709
710

    [o_mrl setStringValue: o_mrl_string];
711
712
}

Christophe Massiot's avatar
Christophe Massiot committed
713
- (IBAction)soutChanged:(id)sender;
714
{
Christophe Massiot's avatar
Christophe Massiot committed
715
    [self soutModeChanged: nil];
716

Christophe Massiot's avatar
Christophe Massiot committed
717
    if ( [o_sout_cbox state] )
718
    {
Christophe Massiot's avatar
Christophe Massiot committed
719
720
721
722
723
724
725
726
727
        NSPoint s_point;
        s_point.x = 0;
        s_point.y = 0;
        [[o_panel contentView] setBoundsOrigin: s_point];
        [[o_panel contentView] setNeedsDisplay: YES];

        NSRect s_rect = [o_panel frame];
        s_rect.size.height = OPEN_PANEL_FULL_HEIGHT + WINDOW_TITLE_HEIGHT;
        s_rect.origin.y -= OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
hartman's avatar
hartman committed
728
        [o_panel setFrame: s_rect display: YES animate: NO];
Christophe Massiot's avatar
Christophe Massiot committed
729
730
731
732
733
734
735
736
737
738
739
740
    }
    else
    {
        NSPoint s_point;
        s_point.x = 0;
        s_point.y = OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
        [[o_panel contentView] setBoundsOrigin: s_point];
        [[o_panel contentView] setNeedsDisplay: YES];

        NSRect s_rect = [o_panel frame];
        s_rect.size.height = OPEN_PANEL_SHORT_HEIGHT + WINDOW_TITLE_HEIGHT;
        s_rect.origin.y += OPEN_PANEL_FULL_HEIGHT - OPEN_PANEL_SHORT_HEIGHT;
hartman's avatar
hartman committed
741
        [o_panel setFrame: s_rect display: YES animate:NO];
742
743
744
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
745
- (IBAction)soutFileBrowse:(id)sender
746
{
Christophe Massiot's avatar
Christophe Massiot committed
747
748
749
750
751
752
    NSSavePanel *o_save_panel = [NSSavePanel savePanel];
    NSString *o_mux_string;
    if ( [[[o_sout_mux selectedCell] title] isEqualToString: _NS("PS")] )
        o_mux_string = @"vob";
    else
        o_mux_string = @"ts";
753

Christophe Massiot's avatar
Christophe Massiot committed
754
755
    NSString * o_name = [NSString stringWithFormat: @"vlc-output.%@",
                         o_mux_string];
756

Christophe Massiot's avatar
Christophe Massiot committed
757
758
759
760
761
    [o_save_panel setTitle: _NS("Save File")];
    [o_save_panel setPrompt: _NS("Save")];

    if( [o_save_panel runModalForDirectory: nil
            file: o_name] == NSOKButton )
762
    {
Christophe Massiot's avatar
Christophe Massiot committed
763
764
765
        NSString *o_filename = [o_save_panel filename];
        [o_sout_file_path setStringValue: o_filename];
        [self soutInfoChanged: nil];
766
767
768
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
769
770
771
772
- (void)soutModeChanged:(NSNotification *)o_notification
{
    NSString *o_mode;
    BOOL b_file = FALSE;
773
    BOOL b_net = FALSE;
Christophe Massiot's avatar
Christophe Massiot committed
774
775
776
777

    o_mode = [[o_sout_access selectedCell] title];

    if( [o_mode isEqualToString: _NS("File")] ) b_file = TRUE;   
778
779
    else if( [o_mode isEqualToString: _NS("UDP")] ) b_net = TRUE;
    else if( [o_mode isEqualToString: _NS("RTP")] ) b_net = TRUE;
Christophe Massiot's avatar
Christophe Massiot committed
780
781
782

    [o_sout_file_path setEnabled: b_file];
    [o_sout_file_btn_browse setEnabled: b_file];
783
784
785
786
    [o_sout_udp_addr setEnabled: b_net];
    [o_sout_udp_port setEnabled: b_net];
    [o_sout_udp_port_stp setEnabled: b_net];
    [[o_sout_mux cellAtRow:0 column: 0] setEnabled: !b_net];
787
    [[o_sout_mux cellAtRow:0 column: 1] setEnabled: !b_net];
Christophe Massiot's avatar
Christophe Massiot committed
788

789
    if ( b_net )
Christophe Massiot's avatar
Christophe Massiot committed
790
    {
791
        [[o_sout_mux cellAtRow: 0 column:2] setState: YES];
Christophe Massiot's avatar
Christophe Massiot committed
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
    }

    [self soutInfoChanged: nil];
}

- (void)soutInfoChanged:(NSNotification *)o_notification
{
    NSString *o_mode;
    NSString *o_mux;
    NSString *o_mrl_string;
    NSString *o_mux_string;

    o_mode = [[o_sout_access selectedCell] title];
    o_mux = [[o_sout_mux selectedCell] title];

807
808
    if ( [o_mux isEqualToString: _NS("AVI")] ) o_mux_string = @"avi";
    else if ( [o_mux isEqualToString: _NS("PS")] ) o_mux_string = @"ps";
Christophe Massiot's avatar
Christophe Massiot committed
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
    else o_mux_string = @"ts";

    if ( [o_mode isEqualToString: _NS("File")] )
    {
        o_mrl_string = [NSString stringWithFormat: @"file/%@://%@",
                        o_mux_string, [o_sout_file_path stringValue]];
    }
    else if ( [o_mode isEqualToString: _NS("UDP")] )
    {
        o_mrl_string = [NSString stringWithFormat: @"udp/%@://%@:%i",
                        o_mux_string, [o_sout_udp_addr stringValue],
                        [o_sout_udp_port intValue]];
    }
    else
    {
        o_mrl_string = [NSString stringWithFormat: @"rtp/%@://%@:%i",
                        o_mux_string, [o_sout_udp_addr stringValue],
                        [o_sout_udp_port intValue]];
    }


    [o_sout_mrl setStringValue: o_mrl_string];
}

- (IBAction)soutStepperChanged:(id)sender
{
    [o_sout_udp_port setIntValue: [o_net_udp_port_stp intValue]];

    [self soutInfoChanged: nil];
}

840
841
- (IBAction)openFile:(id)sender
{
842
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
hartman's avatar
hartman committed
843
844
    
    [o_open_panel setAllowsMultipleSelection: YES];
845
846
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];
hartman's avatar
hartman committed
847
    
848
849
850
851
852
    if( [o_open_panel runModalForDirectory: nil
            file: nil types: nil] == NSOKButton )
    {
        intf_thread_t * p_intf = [NSApp getIntf];
        config_PutPsz( p_intf, "sout", NULL );
853
        [o_playlist appendArray: [o_open_panel filenames] atPos: -1 enqueue:NO];
854
    }
855
856
}

857
858
859
860
861
862
863
- (IBAction)panelCancel:(id)sender
{
    [NSApp stopModalWithCode: 0];
}

- (IBAction)panelOk:(id)sender
{
864
865
866
867
868
869
870
871
    if( [[o_mrl stringValue] length] )
    {
        [NSApp stopModalWithCode: 1];
    }
    else
    {
        NSBeep();
    }
872
873
874
}

@end
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902

@implementation VLGetURLScriptCommand

- (id)performDefaultImplementation {
    NSString *command = [[self commandDescription] commandName];
    NSString *urlString = [self directParameter];

    if ( [command isEqualToString:@"GetURL"] )
    {
        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;
        }

        [p_playlist appendArray: 
            [NSArray arrayWithObject: urlString] atPos: -1 enqueue:NO];
        
        vlc_object_release( p_playlist );
    }
    return nil;
}

@end