CoreInteraction.m 23.4 KB
Newer Older
1
2
3
/*****************************************************************************
 * CoreInteraction.m: MacOS X interface module
 *****************************************************************************
4
 * Copyright (C) 2011-2014 Felix Paul Kühne
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 * $Id$
 *
 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#import "CoreInteraction.h"
#import "intf.h"
#import "open.h"
27
#import "playlist.h"
28
#import <math.h>
29
30
31
#import <vlc_playlist.h>
#import <vlc_input.h>
#import <vlc_keys.h>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
32
33
#import <vlc_vout.h>
#import <vlc_vout_osd.h>
34
35
#import <vlc/vlc.h>
#import <vlc_strings.h>
36
#import <vlc_url.h>
37
38
#import <vlc_modules.h>
#import <vlc_charset.h>
39

40

41
42
43
44
45
46
47
48
@implementation VLCCoreInteraction
static VLCCoreInteraction *_o_sharedInstance = nil;

+ (VLCCoreInteraction *)sharedInstance
{
    return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
}

49
#pragma mark - Initialization
50
51
52

- (id)init
{
53
    if (_o_sharedInstance) {
54
55
        [self dealloc];
        return _o_sharedInstance;
56
    } else
57
        _o_sharedInstance = [super init];
58

59
60
61
62
63
64
65
66
67
68
    return _o_sharedInstance;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver: self];
    [super dealloc];
}


69
#pragma mark - Playback Controls
70

71
- (void)playOrPause
72
{
73
74
    input_thread_t *p_input = pl_CurrentInput(VLCIntf);
    playlist_t *p_playlist = pl_Get(VLCIntf);
75

76
    if (p_input) {
77
        playlist_TogglePause(p_playlist);
78
        vlc_object_release(p_input);
79

80
    } else {
David's avatar
David committed
81
82
        PLRootType root = [[[[VLCMain sharedInstance] playlist] model] currentRootType];
        if ([[[VLCMain sharedInstance] playlist] isSelectionEmpty] && (root == ROOT_TYPE_PLAYLIST || root == ROOT_TYPE_MEDIALIBRARY))
83
84
85
86
            [[[VLCMain sharedInstance] open] openFileGeneric];
        else
            [[[VLCMain sharedInstance] playlist] playItem:nil];
    }
87
88
}

89
90
- (void)pause
{
91
92
    playlist_t *p_playlist = pl_Get(VLCIntf);

93
    playlist_Pause(p_playlist);
94
95
}

96
97
- (void)stop
{
98
    playlist_Stop(pl_Get(VLCIntf));
99
100
101
102
}

- (void)faster
{
103
    var_TriggerCallback(pl_Get(VLCIntf), "rate-faster");
104
105
106
107
}

- (void)slower
{
108
    var_TriggerCallback(pl_Get(VLCIntf), "rate-slower");
109
110
111
112
}

- (void)normalSpeed
{
113
    var_SetFloat(pl_Get(VLCIntf), "rate", 1.);
114
115
}

116
117
- (void)toggleRecord
{
118
    intf_thread_t *p_intf = VLCIntf;
119
    if (!p_intf)
120
        return;
121

122
    input_thread_t * p_input;
123
124
125
126
    p_input = pl_CurrentInput(p_intf);
    if (p_input) {
        var_ToggleBool(p_input, "record");
        vlc_object_release(p_input);
127
128
129
    }
}

130
131
- (void)setPlaybackRate:(int)i_value
{
132
    playlist_t * p_playlist = pl_Get(VLCIntf);
133

134
    double speed = pow(2, (double)i_value / 17);
135
    int rate = INPUT_RATE_DEFAULT / speed;
136
137
    if (i_currentPlaybackRate != rate)
        var_SetFloat(p_playlist, "rate", (float)INPUT_RATE_DEFAULT / (float)rate);
138
139
140
141
142
    i_currentPlaybackRate = rate;
}

- (int)playbackRate
{
143
144
    float f_rate;

145
    intf_thread_t *p_intf = VLCIntf;
146
    if (!p_intf)
147
        return 0;
148

149
    input_thread_t * p_input;
150
151
152
153
    p_input = pl_CurrentInput(p_intf);
    if (p_input) {
        f_rate = var_GetFloat(p_input, "rate");
        vlc_object_release(p_input);
154
155
156
    }
    else
    {
157
158
        playlist_t * p_playlist = pl_Get(VLCIntf);
        f_rate = var_GetFloat(p_playlist, "rate");
159
    }
160

161
162
    double value = 17 * log(f_rate) / log(2.);
    int returnValue = (int) ((value > 0) ? value + .5 : value - .5);
163

164
    if (returnValue < -34)
165
        returnValue = -34;
166
    else if (returnValue > 34)
167
        returnValue = 34;
168

169
170
171
172
    i_currentPlaybackRate = returnValue;
    return returnValue;
}

173
174
- (void)previous
{
175
    playlist_Prev(pl_Get(VLCIntf));
176
177
178
179
}

- (void)next
{
180
    playlist_Next(pl_Get(VLCIntf));
181
182
}

183
184
- (int)durationOfCurrentPlaylistItem
{
185
    intf_thread_t *p_intf = VLCIntf;
186
    if (!p_intf)
187
        return 0;
188

189
    input_thread_t * p_input = pl_CurrentInput(p_intf);
190
    int64_t i_duration = -1;
191
    if (!p_input)
192
        return i_duration;
193

194
195
    input_Control(p_input, INPUT_GET_LENGTH, &i_duration);
    vlc_object_release(p_input);
196

197
    return (int)(i_duration / 1000000);
198
199
200
201
}

- (NSURL*)URLOfCurrentPlaylistItem
{
202
    intf_thread_t *p_intf = VLCIntf;
203
    if (!p_intf)
204
        return nil;
205

206
207
    input_thread_t *p_input = pl_CurrentInput(p_intf);
    if (!p_input)
208
        return nil;
209

210
211
212
    input_item_t *p_item = input_GetItem(p_input);
    if (!p_item) {
        vlc_object_release(p_input);
213
214
        return nil;
    }
215

216
217
218
    char *psz_uri = input_item_GetURI(p_item);
    if (!psz_uri) {
        vlc_object_release(p_input);
219
220
        return nil;
    }
221
222

    NSURL *o_url;
223
    o_url = [NSURL URLWithString:[NSString stringWithUTF8String:psz_uri]];
224
    vlc_object_release(p_input);
225
226

    return o_url;
227
228
229
230
}

- (NSString*)nameOfCurrentPlaylistItem
{
231
    intf_thread_t *p_intf = VLCIntf;
232
    if (!p_intf)
233
        return nil;
234

235
236
    input_thread_t *p_input = pl_CurrentInput(p_intf);
    if (!p_input)
237
        return nil;
238

239
240
241
    input_item_t *p_item = input_GetItem(p_input);
    if (!p_item) {
        vlc_object_release(p_input);
242
243
        return nil;
    }
244

245
246
247
    char *psz_uri = input_item_GetURI(p_item);
    if (!psz_uri) {
        vlc_object_release(p_input);
248
249
        return nil;
    }
250
251

    NSString *o_name;
252
    char *format = var_InheritString(VLCIntf, "input-title-format");
253
    char *formated = str_format_meta(p_input, format);
254
    free(format);
255
    o_name = [NSString stringWithUTF8String:formated];
256
    free(formated);
257

258
    NSURL * o_url = [NSURL URLWithString:[NSString stringWithUTF8String:psz_uri]];
259
    free(psz_uri);
260

261
262
    if ([o_name isEqualToString:@""]) {
        if ([o_url isFileURL])
263
            o_name = [[NSFileManager defaultManager] displayNameAtPath:[o_url path]];
264
265
266
        else
            o_name = [o_url absoluteString];
    }
267
    vlc_object_release(p_input);
268
    return o_name;
269
270
}

271
272
- (void)forward
{
273
274
    //LEGACY SUPPORT
    [self forwardShort];
275
276
277
278
}

- (void)backward
{
279
280
    //LEGACY SUPPORT
    [self backwardShort];
281
282
}

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
- (void)jumpWithValue:(char *)p_value forward:(BOOL)b_value
{
    input_thread_t *p_input = pl_CurrentInput(VLCIntf);
    if (!p_input)
        return;

    int i_interval = var_InheritInteger( p_input, p_value );
    if (i_interval > 0) {
        mtime_t val = CLOCK_FREQ * i_interval;
        if (!b_value)
            val = val * -1;
        var_SetTime( p_input, "time-offset", val );
    }
    vlc_object_release(p_input);
}

299
- (void)forwardExtraShort
300
{
301
    [self jumpWithValue:"extrashort-jump-size" forward:YES];
302
}
303

304
305
- (void)backwardExtraShort
{
306
    [self jumpWithValue:"extrashort-jump-size" forward:NO];
307
308
309
310
}

- (void)forwardShort
{
311
    [self jumpWithValue:"short-jump-size" forward:YES];
312
313
314
315
}

- (void)backwardShort
{
316
    [self jumpWithValue:"short-jump-size" forward:NO];
317
318
319
320
}

- (void)forwardMedium
{
321
    [self jumpWithValue:"medium-jump-size" forward:YES];
322
323
324
325
}

- (void)backwardMedium
{
326
    [self jumpWithValue:"medium-jump-size" forward:NO];
327
328
329
330
}

- (void)forwardLong
{
331
    [self jumpWithValue:"long-jump-size" forward:YES];
332
333
334
335
}

- (void)backwardLong
{
336
    [self jumpWithValue:"long-jump-size" forward:NO];
337
338
339
340
}

- (void)shuffle
{
341
    intf_thread_t *p_intf = VLCIntf;
342
    if (!p_intf)
343
        return;
344

345
    vlc_value_t val;
346
    playlist_t * p_playlist = pl_Get(p_intf);
347
348
    vout_thread_t *p_vout = getVout();

349
    var_Get(p_playlist, "random", &val);
350
    val.b_bool = !val.b_bool;
351
352
353
354
355
    var_Set(p_playlist, "random", val);
    if (val.b_bool) {
        if (p_vout) {
            vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Random On"));
            vlc_object_release(p_vout);
356
        }
357
        config_PutInt(p_playlist, "random", 1);
358
359
360
    }
    else
    {
361
362
363
        if (p_vout) {
            vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Random Off"));
            vlc_object_release(p_vout);
364
        }
365
        config_PutInt(p_playlist, "random", 0);
366
    }
367
368
369
370
}

- (void)repeatAll
{
371
    intf_thread_t *p_intf = VLCIntf;
372
    if (!p_intf)
373
        return;
374

375
    playlist_t * p_playlist = pl_Get(p_intf);
376

377
378
379
380
    var_SetBool(p_playlist, "repeat", NO);
    var_SetBool(p_playlist, "loop", YES);
    config_PutInt(p_playlist, "repeat", NO);
    config_PutInt(p_playlist, "loop", YES);
381
382

    vout_thread_t *p_vout = getVout();
383
384
385
    if (p_vout) {
        vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat All"));
        vlc_object_release(p_vout);
386
    }
387
388
389
390
}

- (void)repeatOne
{
391
    intf_thread_t *p_intf = VLCIntf;
392
    if (!p_intf)
393
        return;
394

395
    playlist_t * p_playlist = pl_Get(p_intf);
396

397
398
399
400
    var_SetBool(p_playlist, "repeat", YES);
    var_SetBool(p_playlist, "loop", NO);
    config_PutInt(p_playlist, "repeat", YES);
    config_PutInt(p_playlist, "loop", NO);
401
402

    vout_thread_t *p_vout = getVout();
403
404
405
    if (p_vout) {
        vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat One"));
        vlc_object_release(p_vout);
406
    }
407
408
409
410
}

- (void)repeatOff
{
411
    intf_thread_t *p_intf = VLCIntf;
412
    if (!p_intf)
413
        return;
414

415
    playlist_t * p_playlist = pl_Get(p_intf);
416

417
418
419
420
    var_SetBool(p_playlist, "repeat", NO);
    var_SetBool(p_playlist, "loop", NO);
    config_PutInt(p_playlist, "repeat", NO);
    config_PutInt(p_playlist, "loop", NO);
421
422

    vout_thread_t *p_vout = getVout();
423
424
425
    if (p_vout) {
        vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat Off"));
        vlc_object_release(p_vout);
426
    }
427
428
}

429
430
431
432
433
434
435
436
437
438
439
440
441
442
- (void)setAtoB
{
    if (!timeA) {
        input_thread_t * p_input = pl_CurrentInput(VLCIntf);
        if (p_input) {
            timeA = var_GetTime(p_input, "time");
            vlc_object_release(p_input);
        }
    } else if (!timeB) {
        input_thread_t * p_input = pl_CurrentInput(VLCIntf);
        if (p_input) {
            timeB = var_GetTime(p_input, "time");
            vlc_object_release(p_input);
        }
443
444
445
446
447
448
449
450
    } else
        [self resetAtoB];
}

- (void)resetAtoB
{
    timeA = 0;
    timeB = 0;
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
}

- (void)updateAtoB
{
    if (timeB) {
        input_thread_t * p_input = pl_CurrentInput(VLCIntf);
        if (p_input) {
            mtime_t currentTime = var_GetTime(p_input, "time");
            if ( currentTime >= timeB || currentTime < timeA)
                var_SetTime(p_input, "time", timeA);
            vlc_object_release(p_input);
        }
    }
}

466
467
- (void)volumeUp
{
468
    intf_thread_t *p_intf = VLCIntf;
469
    if (!p_intf)
470
        return;
471

472
    playlist_VolumeUp(pl_Get(p_intf), 1, NULL);
473
474
475
476
}

- (void)volumeDown
{
477
    intf_thread_t *p_intf = VLCIntf;
478
    if (!p_intf)
479
        return;
480

481
    playlist_VolumeDown(pl_Get(p_intf), 1, NULL);
482
483
}

484
485
486
- (void)toggleMute
{
    intf_thread_t *p_intf = VLCIntf;
487
    if (!p_intf)
488
489
        return;

490
    playlist_MuteToggle(pl_Get(p_intf));
491
492
}

493
- (BOOL)mute
494
495
{
    intf_thread_t *p_intf = VLCIntf;
496
    if (!p_intf)
497
        return NO;
498

499
    BOOL b_is_muted = NO;
500
    b_is_muted = playlist_MuteGet(pl_Get(p_intf)) > 0;
501
502

    return b_is_muted;
503
504
505
}

- (int)volume
506
{
507
    intf_thread_t *p_intf = VLCIntf;
508
    if (!p_intf)
509
        return 0;
510

511
    float volume = playlist_VolumeGet(pl_Get(p_intf));
512

513
    return lroundf(volume * AOUT_VOLUME_DEFAULT);
514
}
515

516
517
- (void)setVolume: (int)i_value
{
518
    intf_thread_t *p_intf = VLCIntf;
519
    if (!p_intf)
520
        return;
521

522
523
524
    if (i_value >= self.maxVolume)
        i_value = self.maxVolume;

525
526
527
    float f_value = i_value / (float)AOUT_VOLUME_DEFAULT;

    playlist_VolumeSet(pl_Get(p_intf), f_value);
528
529
}

530
531
- (float)maxVolume
{
532
533
534
535
536
    if (f_maxVolume == 0.) {
        f_maxVolume = (float)var_InheritInteger(VLCIntf, "macosx-max-volume") / 100. * AOUT_VOLUME_DEFAULT;
    }

    return f_maxVolume;
537
538
}

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
- (void)addSubtitlesToCurrentInput:(NSArray *)paths
{
    input_thread_t * p_input = pl_CurrentInput(VLCIntf);
    if (!p_input)
        return;

    NSUInteger count = [paths count];

    for (int i = 0; i < count ; i++) {
        const char *path = [[[paths objectAtIndex:i] path] UTF8String];
        msg_Dbg(VLCIntf, "loading subs from %s", path);

        int i_result = input_AddSubtitleOSD(p_input, path, true, true);
        if (i_result != VLC_SUCCESS)
            msg_Warn(VLCIntf, "unable to load subtitles from '%s'", path);
    }
    vlc_object_release(p_input);
}

558
#pragma mark - drag and drop support for VLCVoutView, VLCDragDropView and VLCThreePartDropView
559
560
561
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
    NSPasteboard *o_paste = [sender draggingPasteboard];
562
    NSArray *o_types = [NSArray arrayWithObject:NSFilenamesPboardType];
563
564
565
    NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
    NSData *o_carried_data = [o_paste dataForType:o_desired_type];

566
567
    if (o_carried_data) {
        if ([o_desired_type isEqualToString:NSFilenamesPboardType]) {
568
569
570
571
            NSArray *o_array = [NSArray array];
            NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
            NSUInteger count = [o_values count];

572
            input_thread_t * p_input = pl_CurrentInput(VLCIntf);
573

574
            if (count == 1 && p_input) {
575
                int i_result = input_AddSubtitleOSD(p_input, [[o_values objectAtIndex:0] UTF8String], true, true);
576
                vlc_object_release(p_input);
577
                if (i_result == VLC_SUCCESS)
578
579
                    return YES;
            }
580
581
            else if (p_input)
                vlc_object_release(p_input);
582

583
            for (NSUInteger i = 0; i < count; i++) {
584
                NSDictionary *o_dic;
585
                char *psz_uri = vlc_path2uri([[o_values objectAtIndex:i] UTF8String], NULL);
586
                if (!psz_uri)
587
588
589
                    continue;

                o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
590
                free(psz_uri);
591
592
593
594

                o_array = [o_array arrayByAddingObject: o_dic];
            }

595
            [[[VLCMain sharedInstance] playlist] addPlaylistItems:o_array];
596
597
598
599
600
601
            return YES;
        }
    }
    return NO;
}

602
#pragma mark - video output stuff
603

604
- (void)setAspectRatioIsLocked:(BOOL)b_value
605
{
606
    config_PutInt(VLCIntf, "macosx-lock-aspect-ratio", b_value);
607
608
609
610
}

- (BOOL)aspectRatioIsLocked
{
611
    return config_GetInt(VLCIntf, "macosx-lock-aspect-ratio");
612
613
614
615
}

- (void)toggleFullscreen
{
616
    intf_thread_t *p_intf = VLCIntf;
617
    if (!p_intf)
618
        return;
619

620
    vout_thread_t *p_vout = getVoutForActiveWindow();
621
    if (p_vout) {
622
623
        BOOL b_fs = var_ToggleBool(p_vout, "fullscreen");
        var_SetBool(pl_Get(p_intf), "fullscreen", b_fs);
624
        vlc_object_release(p_vout);
625
    } else { // e.g. lion fullscreen toggle
626
        BOOL b_fs = var_ToggleBool(pl_Get(p_intf), "fullscreen");
627
        [[[VLCMain sharedInstance] voutController] setFullscreen:b_fs forWindow:nil withAnimation:YES];
628
    }
629
}
630

631
#pragma mark - uncommon stuff
632
633
634
635
636
637
638
639

- (BOOL)fixPreferences
{
    NSMutableString * o_workString;
    NSRange returnedRange;
    NSRange fullRange;
    BOOL b_needsRestart = NO;

640
641
    #define fixpref(pref) \
    o_workString = [[NSMutableString alloc] initWithFormat:@"%s", config_GetPsz(VLCIntf, pref)]; \
642
643
644
645
646
647
648
    if ([o_workString length] > 0) \
    { \
        returnedRange = [o_workString rangeOfString:@"macosx" options: NSCaseInsensitiveSearch]; \
        if (returnedRange.location != NSNotFound) \
        { \
            if ([o_workString isEqualToString:@"macosx"]) \
                [o_workString setString:@""]; \
649
            fullRange = NSMakeRange(0, [o_workString length]); \
650
            [o_workString replaceOccurrencesOfString:@":macosx" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
651
            fullRange = NSMakeRange(0, [o_workString length]); \
652
653
            [o_workString replaceOccurrencesOfString:@"macosx:" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
            \
654
            config_PutPsz(VLCIntf, pref, [o_workString UTF8String]); \
655
656
657
658
659
            b_needsRestart = YES; \
        } \
    } \
    [o_workString release]

660
661
    fixpref("control");
    fixpref("extraintf");
662
663
664
665
666
    #undef fixpref

    return b_needsRestart;
}

667
668
#pragma mark - video filter handling

669
- (const char *)getFilterType:(const char *)psz_name
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
{
    module_t *p_obj = module_find(psz_name);
    if (!p_obj) {
        return NULL;
    }

    if (module_provides(p_obj, "video splitter")) {
        return "video-splitter";
    } else if (module_provides(p_obj, "video filter2")) {
        return "video-filter";
    } else if (module_provides(p_obj, "sub source")) {
        return "sub-source";
    } else if (module_provides(p_obj, "sub filter")) {
        return "sub-filter";
    } else {
        msg_Err(VLCIntf, "Unknown video filter type.");
        return NULL;
    }
}

690
- (void)setVideoFilter: (const char *)psz_name on:(BOOL)b_on
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
{
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;
    char *psz_string, *psz_parser;

    const char *psz_filter_type = [self getFilterType:psz_name];
    if (!psz_filter_type) {
        msg_Err(p_intf, "Unable to find filter module \"%s\".", psz_name);
        return;
    }

    msg_Dbg(p_intf, "will set filter '%s'", psz_name);


    psz_string = config_GetPsz(p_intf, psz_filter_type);

    if (b_on) {
        if (psz_string == NULL) {
            psz_string = strdup(psz_name);
        } else if (strstr(psz_string, psz_name) == NULL) {
            char *psz_tmp = strdup([[NSString stringWithFormat: @"%s:%s", psz_string, psz_name] UTF8String]);
            free(psz_string);
            psz_string = psz_tmp;
        }
    } else {
        if (!psz_string)
            return;

        psz_parser = strstr(psz_string, psz_name);
        if (psz_parser) {
            if (*(psz_parser + strlen(psz_name)) == ':') {
                memmove(psz_parser, psz_parser + strlen(psz_name) + 1,
                        strlen(psz_parser + strlen(psz_name) + 1) + 1);
            } else {
                *psz_parser = '\0';
            }

            /* Remove trailing : : */
            if (strlen(psz_string) > 0 && *(psz_string + strlen(psz_string) -1) == ':')
                *(psz_string + strlen(psz_string) -1) = '\0';
        } else {
            free(psz_string);
            return;
        }
    }
    config_PutPsz(p_intf, psz_filter_type, psz_string);

    /* Try to set on the fly */
    if (!strcmp(psz_filter_type, "video-splitter")) {
        playlist_t *p_playlist = pl_Get(p_intf);
        var_SetString(p_playlist, psz_filter_type, psz_string);
    } else {
        vout_thread_t *p_vout = getVout();
        if (p_vout) {
            var_SetString(p_vout, psz_filter_type, psz_string);
            vlc_object_release(p_vout);
        }
    }

    free(psz_string);
}

754
- (void)restartFilterIfNeeded: (const char *)psz_filter option: (const char *)psz_name
755
756
757
758
759
760
761
762
763
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
795
796
797
798
799
800
801
802
803
804
805
806
807
{
    vout_thread_t *p_vout = getVout();
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;

    if (p_vout == NULL)
        return;
    else
        vlc_object_release(p_vout);

    vlc_object_t *p_filter = vlc_object_find_name(pl_Get(p_intf), psz_filter);
    if (p_filter) {

        /* we cannot rely on the p_filter existence.
         This filter might be just
         disabled, but the object still exists. Therefore, the string
         is checked, additionally.
         */
        const char *psz_filter_type = [self getFilterType:psz_filter];
        if (!psz_filter_type) {
            msg_Err(p_intf, "Unable to find filter module \"%s\".", psz_name);
            goto out;
        }

        char *psz_string = config_GetPsz(p_intf, psz_filter_type);
        if (!psz_string) {
            goto out;
        }
        if (strstr(psz_string, psz_filter) == NULL) {
            free(psz_string);
            goto out;
        }
        free(psz_string);

        int i_type;
        i_type = var_Type(p_filter, psz_name);
        if (i_type == 0)
            i_type = config_GetType(p_intf, psz_name);

        if (!(i_type & VLC_VAR_ISCOMMAND)) {
            msg_Warn(p_intf, "Brute-restarting filter '%s', because the last changed option isn't a command", psz_name);

            [self setVideoFilter: psz_filter on: NO];
            [self setVideoFilter: psz_filter on: YES];
        } else
            msg_Dbg(p_intf, "restart not needed");

        out:
        vlc_object_release(p_filter);
    }
}

808
- (void)setVideoFilterProperty: (const char *)psz_name forFilter: (const char *)psz_filter integer: (int)i_value
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
{
    vout_thread_t *p_vout = getVout();
    vlc_object_t *p_filter;
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;

    config_PutInt(p_intf, psz_name, i_value);

    if (p_vout) {
        p_filter = vlc_object_find_name(pl_Get(p_intf), psz_filter);

        if (!p_filter) {
            msg_Warn(p_intf, "filter '%s' isn't enabled", psz_filter);
            vlc_object_release(p_vout);
            return;
        }
        var_SetInteger(p_filter, psz_name, i_value);
        vlc_object_release(p_vout);
        vlc_object_release(p_filter);

        [self restartFilterIfNeeded: psz_filter option: psz_name];
    }
}

834
- (void)setVideoFilterProperty: (const char *)psz_name forFilter: (const char *)psz_filter float: (float)f_value
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
{
    vout_thread_t *p_vout = getVout();
    vlc_object_t *p_filter;
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;

    config_PutFloat(p_intf, psz_name, f_value);

    if (p_vout) {
        p_filter = vlc_object_find_name(pl_Get(p_intf), psz_filter);

        if (!p_filter) {
            msg_Warn(p_intf, "filter '%s' isn't enabled", psz_filter);
            vlc_object_release(p_vout);
            return;
        }
        var_SetFloat(p_filter, psz_name, f_value);
        vlc_object_release(p_vout);
        vlc_object_release(p_filter);

        [self restartFilterIfNeeded: psz_filter option: psz_name];
    }
}

860
- (void)setVideoFilterProperty: (const char *)psz_name forFilter: (const char *)psz_filter string: (const char *)psz_value
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
{
    char *psz_new_value = strdup(psz_value);
    vout_thread_t *p_vout = getVout();
    vlc_object_t *p_filter;
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;

    config_PutPsz(p_intf, psz_name, EnsureUTF8(psz_new_value));

    if (p_vout) {
        p_filter = vlc_object_find_name(pl_Get(p_intf), psz_filter);

        if (!p_filter) {
            msg_Warn(p_intf, "filter '%s' isn't enabled", psz_filter);
            vlc_object_release(p_vout);
            return;
        }
        var_SetString(p_filter, psz_name, EnsureUTF8(psz_new_value));
        vlc_object_release(p_vout);
        vlc_object_release(p_filter);

        [self restartFilterIfNeeded: psz_filter option: psz_name];
    }

    free(psz_new_value);
}

889
- (void)setVideoFilterProperty: (const char *)psz_name forFilter: (const char *)psz_filter boolean: (BOOL)b_value
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
{
    vout_thread_t *p_vout = getVout();
    vlc_object_t *p_filter;
    intf_thread_t *p_intf = VLCIntf;
    if (!p_intf)
        return;

    config_PutInt(p_intf, psz_name, b_value);

    if (p_vout) {
        p_filter = vlc_object_find_name(pl_Get(p_intf), psz_filter);

        if (!p_filter) {
            msg_Warn(p_intf, "filter '%s' isn't enabled", psz_filter);
            vlc_object_release(p_vout);
            return;
        }
        var_SetBool(p_filter, psz_name, b_value);
        vlc_object_release(p_vout);
        vlc_object_release(p_filter);
    }
}

913
@end