open.m 26.1 KB
Newer Older
1
2
3
/*****************************************************************************
 * open.m: MacOS X plugin for vlc
 *****************************************************************************
hartman's avatar
hartman committed
4
 * Copyright (C) 2002-2003 VideoLAN
5
 * $Id: open.m,v 1.25 2003/03/24 15:20:26 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
    [o_file_sub_btn_browse setTitle: _NS("Browse...")];
180
    [o_file_sub_ckbox setTitle: _NS("Load subtitles file:")];
181

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

    [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_http_url_lbl setStringValue: _NS("URL")];

197
198
    [[o_net_mode cellAtRow:0 column:0] setTitle: _NS("UDP/RTP")];
    [[o_net_mode cellAtRow:1 column:0] setTitle: _NS("UDP/RTP Multicast")];
199
    [[o_net_mode cellAtRow:2 column:0] setTitle: _NS("HTTP/FTP/MMS")];
200
201
202
203

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

Christophe Massiot's avatar
Christophe Massiot committed
204
205
206
207
208
209
    [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")];

210
    [o_sout_file_btn_browse setTitle: _NS("Browse...")];
Christophe Massiot's avatar
Christophe Massiot committed
211
212
213
    [o_sout_udp_addr_lbl setStringValue: _NS("Address")];
    [o_sout_udp_port_lbl setStringValue: _NS("Port")];

214
215
216
    [[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
217

218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    [[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];
235
236
237
238
    [[NSNotificationCenter defaultCenter] addObserver: self
        selector: @selector(openDiscInfoChanged:)
        name: NSControlTextDidChangeNotification
        object: o_disc_videots_folder];
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

    [[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_http_url];
Christophe Massiot's avatar
Christophe Massiot committed
256
257
258
259
260
261
262
263
264
265
266
267
268

    [[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];
269
270
}

271
- (void)openTarget:(int)i_type
272
273
274
{
    int i_result;

275
    [o_tabview selectTabViewItemAtIndex: i_type];
276
    [o_ckbox_enqueue setState: NSOnState];
277
    [o_file_sub_path setStringValue: @""];
278
    [o_file_sub_ckbox setState: NSOffState];
279
280
281
    [o_file_sub_path setEnabled: NO];
    [o_file_sub_btn_browse setEnabled: NO];
    
282
283
    i_result = [NSApp runModalForWindow: o_panel];
    [o_panel close];
284
285
286

    if( i_result )
    {
Christophe Massiot's avatar
Christophe Massiot committed
287
        NSString *o_sout = [o_sout_mrl stringValue];
288
289
        intf_thread_t * p_intf = [NSApp getIntf];
        
Christophe Massiot's avatar
Christophe Massiot committed
290
291
292
293
294
        if ( [o_sout_cbox state] )
        {
            config_PutPsz( p_intf, "sout", [o_sout lossyCString] );
        }

295
        NSString *o_source = [o_mrl stringValue];
296
297
298
        BOOL b_enq = [o_ckbox_enqueue state] == NSOnState ? YES : NO;
        NSString *subPath = [o_file_sub_path stringValue];
        
299
        [o_playlist appendArray: 
300
301
302
303
            [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] ) );
304
    }
Christophe Massiot's avatar
Christophe Massiot committed
305
306

    [self soutModeChanged: nil];
307
308
}

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
- (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];
    }  
}

327
- (IBAction)openFileGeneric:(id)sender
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
{
    [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
349
    NSString *o_ext = [o_filename pathExtension];
350
    vlc_bool_t b_stream = [o_file_stream state];
351
352
353
    BOOL b_dir = NO;
    
    [[NSFileManager defaultManager] fileExistsAtPath:o_filename isDirectory:&b_dir];
354

355
356
357
358
359
    if( b_dir )
    {
        o_mrl_string = [NSString stringWithFormat: @"dir:%@", o_filename];
    }
    else if( [o_ext isEqualToString: @"bin"] ||
hartman's avatar
hartman committed
360
361
        [o_ext isEqualToString: @"cue"] ||
        [o_ext isEqualToString: @"vob"] ||
362
        [o_ext isEqualToString: @"iso"] )
hartman's avatar
hartman committed
363
364
365
366
367
368
369
370
371
    {
        o_mrl_string = o_filename;
    }
    else
    {
        o_mrl_string = [NSString stringWithFormat: @"%s://%@",
                        b_stream ? "stream" : "file",
                        o_filename];
    }
372
373
374
    [o_mrl setStringValue: o_mrl_string]; 
}

Christophe Massiot's avatar
Christophe Massiot committed
375
376
377
378
379
- (IBAction)openFileBrowse:(id)sender
{
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
    
    [o_open_panel setAllowsMultipleSelection: NO];
380
    [o_open_panel setCanChooseDirectories: YES];
Christophe Massiot's avatar
Christophe Massiot committed
381
382
383
384
385
386
387
388
389
390
391
392
    [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];
    }
}

393
394
395
396
397
- (IBAction)openFileStreamChanged:(id)sender
{
    [self openFilePathChanged: nil];
}

398
399
400
401
402
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
- (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];
    }
}

428
429
430
- (IBAction)openDiscTypeChanged:(id)sender
{
    NSString *o_type;
431
    vlc_bool_t b_device, b_menus, b_title_chapter;
432
433
    
    [o_disc_device removeAllItems];
434
    b_title_chapter = ![o_disc_dvd_menus state];
435
436
437
    
    o_type = [[o_disc_type selectedCell] title];

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

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

488
489
490
491
492
    [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];
493
494
495
    [o_disc_videots_folder setEnabled: !b_device];
    [o_disc_videots_btn_browse setEnabled: !b_device];
    [o_disc_dvd_menus setEnabled: b_menus];
496

497
    [self openDiscInfoChanged: nil];
498
499
}

500
- (IBAction)openDiscStepperChanged:(id)sender
501
{
502
    int i_tag = [sender tag];
503

504
    if( i_tag == 0 )
505
    {
506
        [o_disc_title setIntValue: [o_disc_title_stp intValue]];
507
    }
508
    else if( i_tag == 1 )
509
    {
510
511
        [o_disc_chapter setIntValue: [o_disc_chapter_stp intValue]];
    }
512

513
514
    [self openDiscInfoChanged: nil];
}
515

516
517
518
519
- (void)openDiscInfoChanged:(NSNotification *)o_notification
{
    NSString *o_type;
    NSString *o_device;
520
    NSString *o_videots;
521
522
    NSString *o_mrl_string;
    int i_title, i_chapter;
523
    vlc_bool_t b_menus;
524

525
526
527
528
    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];
529
    o_videots = [o_disc_videots_folder stringValue];
530
    b_menus = [o_disc_dvd_menus state];
531
532

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

562
    [o_mrl setStringValue: o_mrl_string]; 
563
564
}

565
566
567
568
569
570
- (IBAction)openDiscMenusChanged:(id)sender
{
    [self openDiscInfoChanged: nil];
    [self openDiscTypeChanged: nil];
}

Christophe Massiot's avatar
Christophe Massiot committed
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
- (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];
    }
}

590
591
- (IBAction)openNetModeChanged:(id)sender
{
592
593
594
595
    NSString *o_mode;
    BOOL b_udp = FALSE;
    BOOL b_udpm = FALSE;
    BOOL b_http = FALSE;
596
597
598

    o_mode = [[o_net_mode selectedCell] title];

Christophe Massiot's avatar
Christophe Massiot committed
599
600
601
    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("HTTP/FTP/MMS")] ) b_http = TRUE;
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617

    [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_http_url setEnabled: b_http];

    [self openNetInfoChanged: nil];
}

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

    if( i_tag == 0 )
618
    {
619
        [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
620
    }
621
    else if( i_tag == 1 )
622
    {
623
        [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
624
625
    }

626
627
628
629
630
631
632
633
634
635
636
    [self openNetInfoChanged: nil];
}

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

    o_mode = [[o_net_mode selectedCell] title];

637
    if( [o_mode isEqualToString: _NS("UDP/RTP")] )
638
    {
639
640
641
642
        int i_port = [o_net_udp_port intValue];

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

643
        if( i_port != config_GetInt( p_intf, "server-port" ) )
644
645
646
647
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @"@:%i", i_port]; 
        } 
648
    }
649
    else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) 
650
    {
651
652
653
654
        NSString *o_addr = [o_net_udpm_addr stringValue];
        int i_port = [o_net_udpm_port intValue];

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

656
        if( i_port != config_GetInt( p_intf, "server-port" ) )
657
658
659
660
661
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @":%i", i_port]; 
        } 
    }
662
    else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] )
663
    {
664
665
        NSString *o_url = [o_net_http_url stringValue];

666
667
668
669
670
        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;
671
    }
672
673

    [o_mrl setStringValue: o_mrl_string];
674
675
}

Christophe Massiot's avatar
Christophe Massiot committed
676
- (IBAction)soutChanged:(id)sender;
677
{
Christophe Massiot's avatar
Christophe Massiot committed
678
    [self soutModeChanged: nil];
679

Christophe Massiot's avatar
Christophe Massiot committed
680
    if ( [o_sout_cbox state] )
681
    {
Christophe Massiot's avatar
Christophe Massiot committed
682
683
684
685
686
687
688
689
690
        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
691
        [o_panel setFrame: s_rect display: YES animate: NO];
Christophe Massiot's avatar
Christophe Massiot committed
692
693
694
695
696
697
698
699
700
701
702
703
    }
    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
704
        [o_panel setFrame: s_rect display: YES animate:NO];
705
706
707
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
708
- (IBAction)soutFileBrowse:(id)sender
709
{
Christophe Massiot's avatar
Christophe Massiot committed
710
711
712
713
714
715
    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";
716

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

Christophe Massiot's avatar
Christophe Massiot committed
720
721
722
723
724
    [o_save_panel setTitle: _NS("Save File")];
    [o_save_panel setPrompt: _NS("Save")];

    if( [o_save_panel runModalForDirectory: nil
            file: o_name] == NSOKButton )
725
    {
Christophe Massiot's avatar
Christophe Massiot committed
726
727
728
        NSString *o_filename = [o_save_panel filename];
        [o_sout_file_path setStringValue: o_filename];
        [self soutInfoChanged: nil];
729
730
731
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
732
733
734
735
- (void)soutModeChanged:(NSNotification *)o_notification
{
    NSString *o_mode;
    BOOL b_file = FALSE;
736
    BOOL b_net = FALSE;
Christophe Massiot's avatar
Christophe Massiot committed
737
738
739
740

    o_mode = [[o_sout_access selectedCell] title];

    if( [o_mode isEqualToString: _NS("File")] ) b_file = TRUE;   
741
742
    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
743
744
745

    [o_sout_file_path setEnabled: b_file];
    [o_sout_file_btn_browse setEnabled: b_file];
746
747
748
749
    [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];
750
    [[o_sout_mux cellAtRow:0 column: 1] setEnabled: !b_net];
Christophe Massiot's avatar
Christophe Massiot committed
751

752
    if ( b_net )
Christophe Massiot's avatar
Christophe Massiot committed
753
    {
754
        [[o_sout_mux cellAtRow: 0 column:2] setState: YES];
Christophe Massiot's avatar
Christophe Massiot committed
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
    }

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

770
771
    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
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
    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];
}

803
804
- (IBAction)openFile:(id)sender
{
805
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
hartman's avatar
hartman committed
806
807
    
    [o_open_panel setAllowsMultipleSelection: YES];
808
    [o_open_panel setCanChooseDirectories: YES];
809
810
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];
hartman's avatar
hartman committed
811
    
812
813
814
815
816
    if( [o_open_panel runModalForDirectory: nil
            file: nil types: nil] == NSOKButton )
    {
        intf_thread_t * p_intf = [NSApp getIntf];
        config_PutPsz( p_intf, "sout", NULL );
817
        [o_playlist appendArray: [o_open_panel filenames] atPos: -1 enqueue:NO];
818
    }
819
820
}

821
822
823
824
825
826
827
- (IBAction)panelCancel:(id)sender
{
    [NSApp stopModalWithCode: 0];
}

- (IBAction)panelOk:(id)sender
{
828
829
830
831
832
833
834
835
    if( [[o_mrl stringValue] length] )
    {
        [NSApp stopModalWithCode: 1];
    }
    else
    {
        NSBeep();
    }
836
837
838
}

@end