open.m 25.7 KB
Newer Older
1
2
3
/*****************************************************************************
 * open.m: MacOS X plugin for vlc
 *****************************************************************************
hartman's avatar
hartman committed
4
5
 * Copyright (C) 2002-2003 VideoLAN
 * $Id: open.m,v 1.24 2003/03/06 11:43:07 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

hartman's avatar
hartman committed
352
353
354
355
356
357
358
359
360
361
362
363
364
    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];
    }
365
366
367
    [o_mrl setStringValue: o_mrl_string]; 
}

Christophe Massiot's avatar
Christophe Massiot committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
- (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];
    }
}

385
386
387
388
389
- (IBAction)openFileStreamChanged:(id)sender
{
    [self openFilePathChanged: nil];
}

390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
- (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];
    }
}

420
421
422
- (IBAction)openDiscTypeChanged:(id)sender
{
    NSString *o_type;
423
    vlc_bool_t b_device, b_menus, b_title_chapter;
424
425
    
    [o_disc_device removeAllItems];
426
    b_title_chapter = ![o_disc_dvd_menus state];
427
428
429
    
    o_type = [[o_disc_type selectedCell] title];

430
    if ( [o_type isEqualToString: _NS("VIDEO_TS folder")] )
431
    {
432
        b_device = 0; b_menus = 1;
433
434
435
    }
    else
    {
436
437
438
        NSArray *o_devices;
        NSString *o_disc;
        const char *psz_class = NULL;
439
        b_device = 1;
440
441
442
443
444

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

480
481
482
483
484
    [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];
485
486
487
    [o_disc_videots_folder setEnabled: !b_device];
    [o_disc_videots_btn_browse setEnabled: !b_device];
    [o_disc_dvd_menus setEnabled: b_menus];
488

489
    [self openDiscInfoChanged: nil];
490
491
}

492
- (IBAction)openDiscStepperChanged:(id)sender
493
{
494
    int i_tag = [sender tag];
495

496
    if( i_tag == 0 )
497
    {
498
        [o_disc_title setIntValue: [o_disc_title_stp intValue]];
499
    }
500
    else if( i_tag == 1 )
501
    {
502
503
        [o_disc_chapter setIntValue: [o_disc_chapter_stp intValue]];
    }
504

505
506
    [self openDiscInfoChanged: nil];
}
507

508
509
510
511
- (void)openDiscInfoChanged:(NSNotification *)o_notification
{
    NSString *o_type;
    NSString *o_device;
512
    NSString *o_videots;
513
514
    NSString *o_mrl_string;
    int i_title, i_chapter;
515
    vlc_bool_t b_menus;
516

517
518
519
520
    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];
521
    o_videots = [o_disc_videots_folder stringValue];
522
    b_menus = [o_disc_dvd_menus state];
523
524

    if ( [o_type isEqualToString: _NS("VCD")] )
525
    {
526
527
528
529
530
        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]; 
531
    }
532
    else if ( [o_type isEqualToString: _NS("DVD")] )
533
    {
534
535
536
        if ( [o_device isEqualToString:
                [NSString stringWithFormat: _NS("No %@s found"), o_type]] )
            o_device = @"";
537
538
539
540
541
542
        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]; 
543
544
545
    }
    else /* VIDEO_TS folder */
    {
546
547
548
549
550
551
        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]; 
552
    }
553

554
    [o_mrl setStringValue: o_mrl_string]; 
555
556
}

557
558
559
560
561
562
- (IBAction)openDiscMenusChanged:(id)sender
{
    [self openDiscInfoChanged: nil];
    [self openDiscTypeChanged: nil];
}

Christophe Massiot's avatar
Christophe Massiot committed
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
- (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];
    }
}

582
583
- (IBAction)openNetModeChanged:(id)sender
{
584
585
586
587
    NSString *o_mode;
    BOOL b_udp = FALSE;
    BOOL b_udpm = FALSE;
    BOOL b_http = FALSE;
588
589
590

    o_mode = [[o_net_mode selectedCell] title];

Christophe Massiot's avatar
Christophe Massiot committed
591
592
593
    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;
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

    [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 )
610
    {
611
        [o_net_udp_port setIntValue: [o_net_udp_port_stp intValue]];
612
    }
613
    else if( i_tag == 1 )
614
    {
615
        [o_net_udpm_port setIntValue: [o_net_udpm_port_stp intValue]];
616
617
    }

618
619
620
621
622
623
624
625
626
627
628
    [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];

629
    if( [o_mode isEqualToString: _NS("UDP/RTP")] )
630
    {
631
632
633
634
        int i_port = [o_net_udp_port intValue];

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

635
        if( i_port != config_GetInt( p_intf, "server-port" ) )
636
637
638
639
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @"@:%i", i_port]; 
        } 
640
    }
641
    else if( [o_mode isEqualToString: _NS("UDP/RTP Multicast")] ) 
642
    {
643
644
645
646
        NSString *o_addr = [o_net_udpm_addr stringValue];
        int i_port = [o_net_udpm_port intValue];

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

648
        if( i_port != config_GetInt( p_intf, "server-port" ) )
649
650
651
652
653
        {
            o_mrl_string = 
                [o_mrl_string stringByAppendingFormat: @":%i", i_port]; 
        } 
    }
654
    else if( [o_mode isEqualToString: _NS("HTTP/FTP/MMS")] )
655
    {
656
657
        NSString *o_url = [o_net_http_url stringValue];

658
659
660
661
662
        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;
663
    }
664
665

    [o_mrl setStringValue: o_mrl_string];
666
667
}

Christophe Massiot's avatar
Christophe Massiot committed
668
- (IBAction)soutChanged:(id)sender;
669
{
Christophe Massiot's avatar
Christophe Massiot committed
670
    [self soutModeChanged: nil];
671

Christophe Massiot's avatar
Christophe Massiot committed
672
    if ( [o_sout_cbox state] )
673
    {
Christophe Massiot's avatar
Christophe Massiot committed
674
675
676
677
678
679
680
681
682
        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
683
        [o_panel setFrame: s_rect display: YES animate: NO];
Christophe Massiot's avatar
Christophe Massiot committed
684
685
686
687
688
689
690
691
692
693
694
695
    }
    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
696
        [o_panel setFrame: s_rect display: YES animate:NO];
697
698
699
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
700
- (IBAction)soutFileBrowse:(id)sender
701
{
Christophe Massiot's avatar
Christophe Massiot committed
702
703
704
705
706
707
    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";
708

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

Christophe Massiot's avatar
Christophe Massiot committed
712
713
714
715
716
    [o_save_panel setTitle: _NS("Save File")];
    [o_save_panel setPrompt: _NS("Save")];

    if( [o_save_panel runModalForDirectory: nil
            file: o_name] == NSOKButton )
717
    {
Christophe Massiot's avatar
Christophe Massiot committed
718
719
720
        NSString *o_filename = [o_save_panel filename];
        [o_sout_file_path setStringValue: o_filename];
        [self soutInfoChanged: nil];
721
722
723
    }
}

Christophe Massiot's avatar
Christophe Massiot committed
724
725
726
727
- (void)soutModeChanged:(NSNotification *)o_notification
{
    NSString *o_mode;
    BOOL b_file = FALSE;
728
    BOOL b_net = FALSE;
Christophe Massiot's avatar
Christophe Massiot committed
729
730
731
732

    o_mode = [[o_sout_access selectedCell] title];

    if( [o_mode isEqualToString: _NS("File")] ) b_file = TRUE;   
733
734
    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
735
736
737

    [o_sout_file_path setEnabled: b_file];
    [o_sout_file_btn_browse setEnabled: b_file];
738
739
740
741
    [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];
742
    [[o_sout_mux cellAtRow:0 column: 1] setEnabled: !b_net];
Christophe Massiot's avatar
Christophe Massiot committed
743

744
    if ( b_net )
Christophe Massiot's avatar
Christophe Massiot committed
745
    {
746
        [[o_sout_mux cellAtRow: 0 column:2] setState: YES];
Christophe Massiot's avatar
Christophe Massiot committed
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
    }

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

762
763
    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
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
    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];
}

795
796
- (IBAction)openFile:(id)sender
{
797
    NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
hartman's avatar
hartman committed
798
799
    
    [o_open_panel setAllowsMultipleSelection: YES];
800
801
    [o_open_panel setTitle: _NS("Open File")];
    [o_open_panel setPrompt: _NS("Open")];
hartman's avatar
hartman committed
802
    
803
804
805
806
807
    if( [o_open_panel runModalForDirectory: nil
            file: nil types: nil] == NSOKButton )
    {
        intf_thread_t * p_intf = [NSApp getIntf];
        config_PutPsz( p_intf, "sout", NULL );
808
        [o_playlist appendArray: [o_open_panel filenames] atPos: -1 enqueue:NO];
809
    }
810
811
}

812
813
814
815
816
817
818
- (IBAction)panelCancel:(id)sender
{
    [NSApp stopModalWithCode: 0];
}

- (IBAction)panelOk:(id)sender
{
819
820
821
822
823
824
825
826
    if( [[o_mrl stringValue] length] )
    {
        [NSApp stopModalWithCode: 1];
    }
    else
    {
        NSBeep();
    }
827
828
829
}

@end