macOS: Use dark appearance for panel modals
[vlc.git] / modules / gui / macosx / VLCVideoEffectsWindowController.m
bloba95e28f2097c30f45ab5575af511de304408b201
1 /*****************************************************************************
2  * VLCVideoEffectsWindowController.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2011-2015 Felix Paul Kühne
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
24 #import "CompatibilityFixes.h"
25 #import "VLCMain.h"
26 #import "VLCVideoEffectsWindowController.h"
27 #import "VLCPopupPanelController.h"
28 #import "VLCTextfieldPanelController.h"
29 #import "VLCCoreInteraction.h"
31 @interface VLCVideoEffectsWindowController()
33     NSInteger i_old_profile_index;
35 @end
37 #pragma mark -
38 #pragma mark Initialization
40 @implementation VLCVideoEffectsWindowController
42 + (void)initialize
44     NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:@";;;0;1.000000;1.000000;1.000000;1.000000;0.050000;16;2.000000;OTA=;4;4;16711680;20;15;120;Z3JhZGllbnQ=;1;0;16711680;6;80;VkxD;-1;;-1;255;2;3;3"], @"VideoEffectProfiles",
45                                  [NSArray arrayWithObject:_NS("Default")], @"VideoEffectProfileNames", nil];
46     [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
49 - (id)init
51     self = [super initWithWindowNibName:@"VideoEffects"];
52     if (self) {
53         i_old_profile_index = -1;
55         self.popupPanel = [[VLCPopupPanelController alloc] init];
56         self.textfieldPanel = [[VLCTextfieldPanelController alloc] init];
57     }
59     return self;
62 - (void)windowDidLoad
64     [self.window setTitle: _NS("Video Effects")];
65     [self.window setExcludedFromWindowsMenu:YES];
66     [self.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
68     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"basic"]] setLabel:_NS("Basic")];
69     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"crop"]] setLabel:_NS("Crop")];
70     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"geometry"]] setLabel:_NS("Geometry")];
71     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"color"]] setLabel:_NS("Color")];
72     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"misc"]] setLabel:_NS("Miscellaneous")];
74     [self resetProfileSelector];
76     [_adjustCheckbox setTitle:_NS("Image Adjust")];
77     [_adjustHueLabel setStringValue:_NS("Hue")];
78     [_adjustContrastLabel setStringValue:_NS("Contrast")];
79     [_adjustBrightnessLabel setStringValue:_NS("Brightness")];
80     [_adjustBrightnessCheckbox setTitle:_NS("Brightness Threshold")];
81     [_adjustSaturationLabel setStringValue:_NS("Saturation")];
82     [_adjustGammaLabel setStringValue:_NS("Gamma")];
83     [_adjustResetButton setTitle: _NS("Reset")];
84     [_sharpenCheckbox setTitle:_NS("Sharpen")];
85     [_sharpenLabel setStringValue:_NS("Sigma")];
86     [_bandingCheckbox setTitle:_NS("Banding removal")];
87     [_bandingLabel setStringValue:_NS("Radius")];
88     [_grainCheckbox setTitle:_NS("Film Grain")];
89     [_grainLabel setStringValue:_NS("Variance")];
90     [_cropTopLabel setStringValue:_NS("Top")];
91     [_cropLeftLabel setStringValue:_NS("Left")];
92     [_cropRightLabel setStringValue:_NS("Right")];
93     [_cropBottomLabel setStringValue:_NS("Bottom")];
94     [_cropSyncTopBottomCheckbox setTitle:_NS("Synchronize top and bottom")];
95     [_cropSyncLeftRightCheckbox setTitle:_NS("Synchronize left and right")];
97     [_transformCheckbox setTitle:_NS("Transform")];
98     [_transformPopup removeAllItems];
99     [_transformPopup addItemWithTitle: _NS("Rotate by 90 degrees")];
100     [[_transformPopup lastItem] setTag: 90];
101     [_transformPopup addItemWithTitle: _NS("Rotate by 180 degrees")];
102     [[_transformPopup lastItem] setTag: 180];
103     [_transformPopup addItemWithTitle: _NS("Rotate by 270 degrees")];
104     [[_transformPopup lastItem] setTag: 270];
105     [_transformPopup addItemWithTitle: _NS("Flip horizontally")];
106     [[_transformPopup lastItem] setTag: 1];
107     [_transformPopup addItemWithTitle: _NS("Flip vertically")];
108     [[_transformPopup lastItem] setTag: 2];
109     [_zoomCheckbox setTitle:_NS("Magnification/Zoom")];
110     [_puzzleCheckbox setTitle:_NS("Puzzle game")];
111     [_puzzleRowsLabel setStringValue:_NS("Rows")];
112     [_puzzleColumnsLabel setStringValue:_NS("Columns")];
113     [_cloneCheckbox setTitle:_NS("Clone")];
114     [_cloneNumberLabel setStringValue:_NS("Number of clones")];
115     [_wallCheckbox setTitle:_NS("Wall")];
116     [_wallNumbersOfRowsLabel setStringValue:_NS("Rows")];
117     [_wallNumberOfColumnsLabel setStringValue:_NS("Columns")];
119     [_thresholdCheckbox setTitle:_NS("Color threshold")];
120     [_thresholdColorLabel setStringValue:_NS("Color")];
121     [_thresholdSaturationLabel setStringValue:_NS("Saturation")];
122     [_thresholdSimilarityLabel setStringValue:_NS("Similarity")];
123     [_sepiaCheckbox setTitle:_NS("Sepia")];
124     [_sepiaLabel setStringValue:_NS("Intensity")];
125     [_noiseCheckbox setTitle:_NS("Noise")];
126     [_gradientCheckbox setTitle:_NS("Gradient")];
127     [_gradientModeLabel setStringValue:_NS("Mode")];
128     [_gradientModePopup removeAllItems];
129     [_gradientModePopup addItemWithTitle: _NS("Gradient")];
130     [[_gradientModePopup lastItem] setTag: 1];
131     [_gradientModePopup addItemWithTitle: _NS("Edge")];
132     [[_gradientModePopup lastItem] setTag: 2];
133     [_gradientModePopup addItemWithTitle: _NS("Hough")];
134     [[_gradientModePopup lastItem] setTag: 3];
135     [_gradientColorCheckbox setTitle:_NS("Color")];
136     [_gradientCartoonCheckbox setTitle:_NS("Cartoon")];
137     [_extractCheckbox setTitle:_NS("Color extraction")];
138     [_extractLabel setStringValue:_NS("Color")];
139     [_invertCheckbox setTitle:_NS("Invert colors")];
140     [_posterizeCheckbox setTitle:_NS("Posterize")];
141     [_posterizeLabel setStringValue:_NS("Posterize level")];
142     [_blurCheckbox setTitle:_NS("Motion blur")];
143     [_blurLabel setStringValue:_NS("Factor")];
144     [_motiondetectCheckbox setTitle:_NS("Motion Detect")];
145     [_watereffectCheckbox setTitle:_NS("Water effect")];
146     [_wavesCheckbox setTitle:_NS("Waves")];
147     [_psychedelicCheckbox setTitle:_NS("Psychedelic")];
148     [_anaglyphCheckbox setTitle:_NS("Anaglyph")];
150     [_addTextCheckbox setTitle:_NS("Add text")];
151     [_addTextTextLabel setStringValue:_NS("Text")];
152     [_addTextPositionLabel setStringValue:_NS("Position")];
153     [_addTextPositionPopup removeAllItems];
154     [_addTextPositionPopup addItemWithTitle: _NS("Center")];
155     [[_addTextPositionPopup lastItem] setTag: 0];
156     [_addTextPositionPopup addItemWithTitle: _NS("Left")];
157     [[_addTextPositionPopup lastItem] setTag: 1];
158     [_addTextPositionPopup addItemWithTitle: _NS("Right")];
159     [[_addTextPositionPopup lastItem] setTag: 2];
160     [_addTextPositionPopup addItemWithTitle: _NS("Top")];
161     [[_addTextPositionPopup lastItem] setTag: 4];
162     [_addTextPositionPopup addItemWithTitle: _NS("Bottom")];
163     [[_addTextPositionPopup lastItem] setTag: 8];
164     [_addTextPositionPopup addItemWithTitle: _NS("Top-Left")];
165     [[_addTextPositionPopup lastItem] setTag: 5];
166     [_addTextPositionPopup addItemWithTitle: _NS("Top-Right")];
167     [[_addTextPositionPopup lastItem] setTag: 6];
168     [_addTextPositionPopup addItemWithTitle: _NS("Bottom-Left")];
169     [[_addTextPositionPopup lastItem] setTag: 9];
170     [_addTextPositionPopup addItemWithTitle: _NS("Bottom-Right")];
171     [[_addTextPositionPopup lastItem] setTag: 10];
172     [_addLogoCheckbox setTitle:_NS("Add logo")];
173     [_addLogoLogoLabel setStringValue:_NS("Logo")];
174     [_addLogoPositionLabel setStringValue:_NS("Position")];
175     [_addLogoPositionPopup removeAllItems];
176     [_addLogoPositionPopup addItemWithTitle: _NS("Center")];
177     [[_addLogoPositionPopup lastItem] setTag: 0];
178     [_addLogoPositionPopup addItemWithTitle: _NS("Left")];
179     [[_addLogoPositionPopup lastItem] setTag: 1];
180     [_addLogoPositionPopup addItemWithTitle: _NS("Right")];
181     [[_addLogoPositionPopup lastItem] setTag: 2];
182     [_addLogoPositionPopup addItemWithTitle: _NS("Top")];
183     [[_addLogoPositionPopup lastItem] setTag: 4];
184     [_addLogoPositionPopup addItemWithTitle: _NS("Bottom")];
185     [[_addLogoPositionPopup lastItem] setTag: 8];
186     [_addLogoPositionPopup addItemWithTitle: _NS("Top-Left")];
187     [[_addLogoPositionPopup lastItem] setTag: 5];
188     [_addLogoPositionPopup addItemWithTitle: _NS("Top-Right")];
189     [[_addLogoPositionPopup lastItem] setTag: 6];
190     [_addLogoPositionPopup addItemWithTitle: _NS("Bottom-Left")];
191     [[_addLogoPositionPopup lastItem] setTag: 9];
192     [_addLogoPositionPopup addItemWithTitle: _NS("Bottom-Right")];
193     [[_addLogoPositionPopup lastItem] setTag: 10];
194     [_addLogoTransparencyLabel setStringValue:_NS("Transparency")];
196     [_tabView selectFirstTabViewItem:self];
198     [[NSNotificationCenter defaultCenter] addObserver:self
199                                              selector:@selector(inputChangedEvent:)
200                                                  name:VLCInputChangedNotification
201                                                object:nil];
204     [self resetValues];
207 - (void)dealloc
209     [[NSNotificationCenter defaultCenter] removeObserver:self];
212 - (void)updateCocoaWindowLevel:(NSInteger)i_level
214     if (self.isWindowLoaded && [self.window isVisible] && [self.window level] != i_level)
215         [self.window setLevel: i_level];
218 #pragma mark -
219 #pragma mark internal functions
221 -(void)inputChangedEvent:(NSNotification *)o_notification
223     // reset crop values when input changed
224     [self setCropBottomValue:0];
225     [self setCropTopValue:0];
226     [self setCropLeftValue:0];
227     [self setCropRightValue:0];
230 - (void)resetProfileSelector
232     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
233     [_profilePopup removeAllItems];
235     NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"];
236     [_profilePopup addItemsWithTitles:profileNames];
238     [[_profilePopup menu] addItem:[NSMenuItem separatorItem]];
239     [_profilePopup addItemWithTitle:_NS("Duplicate current profile...")];
240     [[_profilePopup lastItem] setTarget: self];
241     [[_profilePopup lastItem] setAction: @selector(addProfile:)];
243     if ([profileNames count] > 1) {
244         [_profilePopup addItemWithTitle:_NS("Organize profiles...")];
245         [[_profilePopup lastItem] setTarget: self];
246         [[_profilePopup lastItem] setAction: @selector(removeProfile:)];
247     }
249     [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
250     [self profileSelectorAction:self];
253 - (void)resetValues
255     intf_thread_t *p_intf = getIntf();
256     NSString *tmpString;
257     char *tmpChar;
258     BOOL b_state;
260     /* do we have any filter enabled? if yes, show it. */
261     char * psz_vfilters;
262     psz_vfilters = config_GetPsz(p_intf, "video-filter");
263     if (psz_vfilters) {
264         [_adjustCheckbox setState: (NSInteger)strstr(psz_vfilters, "adjust")];
265         [_sharpenCheckbox setState: (NSInteger)strstr(psz_vfilters, "sharpen")];
266         [_bandingCheckbox setState: (NSInteger)strstr(psz_vfilters, "gradfun")];
267         [_grainCheckbox setState: (NSInteger)strstr(psz_vfilters, "grain")];
268         [_transformCheckbox setState: (NSInteger)strstr(psz_vfilters, "transform")];
269         [_zoomCheckbox setState: (NSInteger)strstr(psz_vfilters, "magnify")];
270         [_puzzleCheckbox setState: (NSInteger)strstr(psz_vfilters, "puzzle")];
271         [_thresholdCheckbox setState: (NSInteger)strstr(psz_vfilters, "colorthres")];
272         [_sepiaCheckbox setState: (NSInteger)strstr(psz_vfilters, "sepia")];
273         [_noiseCheckbox setState: (NSInteger)strstr(psz_vfilters, "noise")];
274         [_gradientCheckbox setState: (NSInteger)strstr(psz_vfilters, "gradient")];
275         [_extractCheckbox setState: (NSInteger)strstr(psz_vfilters, "extract")];
276         [_invertCheckbox setState: (NSInteger)strstr(psz_vfilters, "invert")];
277         [_posterizeCheckbox setState: (NSInteger)strstr(psz_vfilters, "posterize")];
278         [_blurCheckbox setState: (NSInteger)strstr(psz_vfilters, "motionblur")];
279         [_motiondetectCheckbox setState: (NSInteger)strstr(psz_vfilters, "motiondetect")];
280         [_watereffectCheckbox setState: (NSInteger)strstr(psz_vfilters, "ripple")];
281         [_wavesCheckbox setState: (NSInteger)strstr(psz_vfilters, "wave")];
282         [_psychedelicCheckbox setState: (NSInteger)strstr(psz_vfilters, "psychedelic")];
283         [_anaglyphCheckbox setState: (NSInteger)strstr(psz_vfilters, "anaglyph")];
284         free(psz_vfilters);
285     } else {
286         [_adjustCheckbox setState: NSOffState];
287         [_sharpenCheckbox setState: NSOffState];
288         [_bandingCheckbox setState: NSOffState];
289         [_grainCheckbox setState: NSOffState];
290         [_transformCheckbox setState: NSOffState];
291         [_zoomCheckbox setState: NSOffState];
292         [_puzzleCheckbox setState: NSOffState];
293         [_thresholdCheckbox setState: NSOffState];
294         [_sepiaCheckbox setState: NSOffState];
295         [_noiseCheckbox setState: NSOffState];
296         [_gradientCheckbox setState: NSOffState];
297         [_extractCheckbox setState: NSOffState];
298         [_invertCheckbox setState: NSOffState];
299         [_posterizeCheckbox setState: NSOffState];
300         [_blurCheckbox setState: NSOffState];
301         [_motiondetectCheckbox setState: NSOffState];
302         [_watereffectCheckbox setState: NSOffState];
303         [_wavesCheckbox setState: NSOffState];
304         [_psychedelicCheckbox setState: NSOffState];
305         [_anaglyphCheckbox setState: NSOffState];
306     }
308     psz_vfilters = config_GetPsz(p_intf, "sub-source");
309     if (psz_vfilters) {
310         [_addTextCheckbox setState: (NSInteger)strstr(psz_vfilters, "marq")];
311         [_addLogoCheckbox setState: (NSInteger)strstr(psz_vfilters, "logo")];
312         free(psz_vfilters);
313     } else {
314         [_addTextCheckbox setState: NSOffState];
315         [_addLogoCheckbox setState: NSOffState];
316     }
318     psz_vfilters = config_GetPsz(p_intf, "video-splitter");
319     if (psz_vfilters) {
320         [_cloneCheckbox setState: (NSInteger)strstr(psz_vfilters, "clone")];
321         [_wallCheckbox setState: (NSInteger)strstr(psz_vfilters, "wall")];
322         free(psz_vfilters);
323     } else {
324         [_cloneCheckbox setState: NSOffState];
325         [_wallCheckbox setState: NSOffState];
326     }
328     /* fetch and show the various values */
329     [_adjustHueSlider setFloatValue: config_GetFloat(p_intf, "hue")];
330     [_adjustContrastSlider setFloatValue: config_GetFloat(p_intf, "contrast")];
331     [_adjustBrightnessSlider setFloatValue: config_GetFloat(p_intf, "brightness")];
332     [_adjustSaturationSlider setFloatValue: config_GetFloat(p_intf, "saturation")];
333     [_adjustBrightnessCheckbox setState:(config_GetInt(p_intf, "brightness-threshold") != 0 ? NSOnState : NSOffState)];
334     [_adjustGammaSlider setFloatValue: config_GetFloat(p_intf, "gamma")];
335     [_adjustBrightnessSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "brightness")]];
336     [_adjustContrastSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "contrast")]];
337     [_adjustGammaSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "gamma")]];
338     [_adjustHueSlider setToolTip: [NSString stringWithFormat:@"%.0f", config_GetFloat(p_intf, "hue")]];
339     [_adjustSaturationSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "saturation")]];
340     b_state = [_adjustCheckbox state];
342     [_adjustBrightnessSlider setEnabled: b_state];
343     [_adjustBrightnessCheckbox setEnabled: b_state];
344     [_adjustContrastSlider setEnabled: b_state];
345     [_adjustGammaSlider setEnabled: b_state];
346     [_adjustHueSlider setEnabled: b_state];
347     [_adjustSaturationSlider setEnabled: b_state];
348     [_adjustBrightnessLabel setEnabled: b_state];
349     [_adjustContrastLabel setEnabled: b_state];
350     [_adjustGammaLabel setEnabled: b_state];
351     [_adjustHueLabel setEnabled: b_state];
352     [_adjustSaturationLabel setEnabled: b_state];
353     [_adjustResetButton setEnabled: b_state];
355     [_sharpenSlider setFloatValue: config_GetFloat(p_intf, "sharpen-sigma")];
356     [_sharpenSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "sharpen-sigma")]];
357     [_sharpenSlider setEnabled: [_sharpenCheckbox state]];
358     [_sharpenLabel setEnabled: [_sharpenCheckbox state]];
360     [_bandingSlider setIntValue: config_GetInt(p_intf, "gradfun-radius")];
361     [_bandingSlider setToolTip: [NSString stringWithFormat:@"%lli", config_GetInt(p_intf, "gradfun-radius")]];
362     [_bandingSlider setEnabled: [_bandingCheckbox state]];
363     [_bandingLabel setEnabled: [_bandingCheckbox state]];
365     [_grainSlider setFloatValue: config_GetFloat(p_intf, "grain-variance")];
366     [_grainSlider setToolTip: [NSString stringWithFormat:@"%0.3f", config_GetFloat(p_intf, "grain-variance")]];
367     [_grainSlider setEnabled: [_grainCheckbox state]];
368     [_grainLabel setEnabled: [_grainCheckbox state]];
370     [self setCropLeftValue: 0];
371     [self setCropTopValue: 0];
372     [self setCropRightValue: 0];
373     [self setCropBottomValue: 0];
374     [_cropSyncTopBottomCheckbox setState: NSOffState];
375     [_cropSyncLeftRightCheckbox setState: NSOffState];
377     tmpChar = config_GetPsz(p_intf, "transform-type");
378     tmpString = toNSStr(tmpChar);
379     if ([tmpString isEqualToString:@"hflip"])
380         [_transformPopup selectItemWithTag: 1];
381     else if ([tmpString isEqualToString:@"vflip"])
382         [_transformPopup selectItemWithTag: 2];
383     else
384         [_transformPopup selectItemWithTag:[tmpString intValue]];
385     FREENULL(tmpChar);
386     [_transformPopup setEnabled: [_transformCheckbox state]];
388     [self setPuzzleColumnsValue: config_GetInt(p_intf, "puzzle-cols")];
389     [self setPuzzleRowsValue: config_GetInt(p_intf, "puzzle-rows")];
390     b_state = [_puzzleCheckbox state];
391     [_puzzleRowsTextField setEnabled: b_state];
392     [_puzzleRowsStepper setEnabled: b_state];
393     [_puzzleRowsLabel setEnabled: b_state];
394     [_puzzleColumnsTextField setEnabled: b_state];
395     [_puzzleColumnsStepper setEnabled: b_state];
396     [_puzzleColumnsLabel setEnabled: b_state];
398     [self setCloneValue: config_GetInt(p_intf, "clone-count")];
399     b_state = [_cloneCheckbox state];
400     [_cloneNumberLabel setEnabled: b_state];
401     [_cloneNumberTextField setEnabled: b_state];
402     [_cloneNumberStepper setEnabled: b_state];
404     b_state = [_wallCheckbox state];
405     [self setWallRowsValue: config_GetInt(p_intf, "wall-rows")];
406     [_wallNumbersOfRowsLabel setEnabled: b_state];
407     [_wallNumbersOfRowsTextField setEnabled: b_state];
408     [_wallNumbersOfRowsStepper setEnabled: b_state];
409     [self setWallColumnsValue: config_GetInt(p_intf, "wall-cols")];
410     [_wallNumberOfColumnsLabel setEnabled: b_state];
411     [_wallNumberOfColumnsTextField setEnabled: b_state];
412     [_wallNumberOfColumnsStepper setEnabled: b_state];
414     [_thresholdColorTextField setStringValue: [[NSString stringWithFormat:@"%llx", config_GetInt(p_intf, "colorthres-color")] uppercaseString]];
415     [_thresholdSaturationSlider setIntValue: config_GetInt(p_intf, "colorthres-saturationthres")];
416     [_thresholdSaturationSlider setToolTip: [NSString stringWithFormat:@"%lli", config_GetInt(p_intf, "colorthres-saturationthres")]];
417     [_thresholdSimilaritySlider setIntValue: config_GetInt(p_intf, "colorthres-similaritythres")];
418     [_thresholdSimilaritySlider setToolTip: [NSString stringWithFormat:@"%lli", config_GetInt(p_intf, "colorthres-similaritythres")]];
420     b_state = [_thresholdCheckbox state];
421     [_thresholdColorTextField setEnabled: b_state];
422     [_thresholdColorLabel setEnabled: b_state];
423     [_thresholdSaturationSlider setEnabled: b_state];
424     [_thresholdSaturationLabel setEnabled: b_state];
425     [_thresholdSimilaritySlider setEnabled: b_state];
426     [_thresholdSimilarityLabel setEnabled: b_state];
428     [self setSepiaValue: config_GetInt(p_intf, "sepia-intensity")];
429     b_state = [_sepiaCheckbox state];
430     [_sepiaTextField setEnabled: b_state];
431     [_sepiaStepper setEnabled: b_state];
432     [_sepiaLabel setEnabled: b_state];
434     tmpChar = config_GetPsz(p_intf, "gradient-mode");
435     tmpString = toNSStr(tmpChar);
436     if ([tmpString isEqualToString:@"hough"])
437         [_gradientModePopup selectItemWithTag: 3];
438     else if ([tmpString isEqualToString:@"edge"])
439         [_gradientModePopup selectItemWithTag: 2];
440     else
441         [_gradientModePopup selectItemWithTag: 1];
442     FREENULL(tmpChar);
443     [_gradientCartoonCheckbox setState: config_GetInt(p_intf, "gradient-cartoon")];
444     [_gradientColorCheckbox setState: config_GetInt(p_intf, "gradient-type")];
445     b_state = [_gradientCheckbox state];
446     [_gradientModePopup setEnabled: b_state];
447     [_gradientModeLabel setEnabled: b_state];
448     [_gradientCartoonCheckbox setEnabled: b_state];
449     [_gradientColorCheckbox setEnabled: b_state];
451     [_extractTextField setStringValue: [[NSString stringWithFormat:@"%llx", config_GetInt(p_intf, "extract-component")] uppercaseString]];
452     [_extractTextField setEnabled: [_extractCheckbox state]];
453     [_extractLabel setEnabled: [_extractCheckbox state]];
455     [self setPosterizeValue: config_GetInt(p_intf, "posterize-level")];
456     b_state = [_posterizeCheckbox state];
457     [_posterizeTextField setEnabled: b_state];
458     [_posterizeStepper setEnabled: b_state];
459     [_posterizeLabel setEnabled: b_state];
461     [_blurSlider setIntValue: config_GetInt(p_intf, "blur-factor")];
462     [_blurSlider setToolTip: [NSString stringWithFormat:@"%lli", config_GetInt(p_intf, "blur-factor")]];
463     [_blurSlider setEnabled: [_blurCheckbox state]];
464     [_blurLabel setEnabled: [_blurCheckbox state]];
466     tmpChar = config_GetPsz(p_intf, "marq-marquee");
467     [_addTextTextTextField setStringValue:toNSStr(tmpChar)];
468     if (tmpChar)
469         FREENULL(tmpChar);
470     [_addTextPositionPopup selectItemWithTag: config_GetInt(p_intf, "marq-position")];
471     b_state = [_addTextCheckbox state];
472     [_addTextPositionPopup setEnabled: b_state];
473     [_addTextPositionLabel setEnabled: b_state];
474     [_addTextTextLabel setEnabled: b_state];
475     [_addTextTextTextField setEnabled: b_state];
477     tmpChar = config_GetPsz(p_intf, "logo-file");
478     [_addLogoLogoTextField setStringValue: toNSStr(tmpChar)];
479     if (tmpChar)
480         FREENULL(tmpChar);
481     [_addLogoPositionPopup selectItemWithTag: config_GetInt(p_intf, "logo-position")];
482     [_addLogoTransparencySlider setIntValue: config_GetInt(p_intf, "logo-opacity")];
483     [_addLogoTransparencySlider setToolTip: [NSString stringWithFormat:@"%lli", config_GetInt(p_intf, "logo-opacity")]];
484     b_state = [_addLogoCheckbox state];
485     [_addLogoPositionPopup setEnabled: b_state];
486     [_addLogoPositionLabel setEnabled: b_state];
487     [_addLogoLogoTextField setEnabled: b_state];
488     [_addLogoLogoLabel setEnabled: b_state];
489     [_addLogoTransparencySlider setEnabled: b_state];
490     [_addLogoTransparencyLabel setEnabled: b_state];
493 - (NSString *)generateProfileString
495     intf_thread_t *p_intf = getIntf();
496     return [NSString stringWithFormat:@"%@;%@;%@;%lli;%f;%f;%f;%f;%f;%lli;%f;%@;%lli;%lli;%lli;%lli;%lli;%lli;%@;%lli;%lli;%lli;%lli;%lli;%@;%lli;%@;%lli;%lli;%lli;%lli;%lli;%lli;%f",
497             B64EncAndFree(config_GetPsz(p_intf, "video-filter")),
498             B64EncAndFree(config_GetPsz(p_intf, "sub-source")),
499             B64EncAndFree(config_GetPsz(p_intf, "video-splitter")),
500             0LL, // former "hue" value, deprecated since 3.0.0
501             config_GetFloat(p_intf, "contrast"),
502             config_GetFloat(p_intf, "brightness"),
503             config_GetFloat(p_intf, "saturation"),
504             config_GetFloat(p_intf, "gamma"),
505             config_GetFloat(p_intf, "sharpen-sigma"),
506             config_GetInt(p_intf, "gradfun-radius"),
507             config_GetFloat(p_intf, "grain-variance"),
508             B64EncAndFree(config_GetPsz(p_intf, "transform-type")),
509             config_GetInt(p_intf, "puzzle-rows"),
510             config_GetInt(p_intf, "puzzle-cols"),
511             config_GetInt(p_intf, "colorthres-color"),
512             config_GetInt(p_intf, "colorthres-saturationthres"),
513             config_GetInt(p_intf, "colorthres-similaritythres"),
514             config_GetInt(p_intf, "sepia-intensity"),
515             B64EncAndFree(config_GetPsz(p_intf, "gradient-mode")),
516             config_GetInt(p_intf, "gradient-cartoon"),
517             config_GetInt(p_intf, "gradient-type"),
518             config_GetInt(p_intf, "extract-component"),
519             config_GetInt(p_intf, "posterize-level"),
520             config_GetInt(p_intf, "blur-factor"),
521             B64EncAndFree(config_GetPsz(p_intf, "marq-marquee")),
522             config_GetInt(p_intf, "marq-position"),
523             B64EncAndFree(config_GetPsz(p_intf, "logo-file")),
524             config_GetInt(p_intf, "logo-position"),
525             config_GetInt(p_intf, "logo-opacity"),
526             config_GetInt(p_intf, "clone-count"),
527             config_GetInt(p_intf, "wall-rows"),
528             config_GetInt(p_intf, "wall-cols"),
529             // version 2 of profile string:
530             config_GetInt(p_intf, "brightness-threshold"), // index: 32
531             // version 3 of profile string: (vlc-3.0.0)
532             config_GetFloat(p_intf, "hue") // index: 33
533             ];
536 #pragma mark -
537 #pragma mark generic UI code
539 - (void)saveCurrentProfile
541     if (i_old_profile_index == -1)
542         return;
544     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
545     /* fetch all the current settings in a uniform string */
546     NSString *newProfile = [self generateProfileString];
548     NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]];
549     if (i_old_profile_index >= [workArray count])
550         return;
552     [workArray replaceObjectAtIndex:i_old_profile_index withObject:newProfile];
553     [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"];
554     [defaults synchronize];
557 - (IBAction)toggleWindow:(id)sender
559     if ([self.window isKeyWindow])
560         [self.window orderOut:sender];
561     else {
562         [self.window setLevel: [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel]];
563         [self.window makeKeyAndOrderFront:sender];
564     }
567 - (IBAction)profileSelectorAction:(id)sender
569     intf_thread_t *p_intf = getIntf();
570     [self saveCurrentProfile];
571     i_old_profile_index = [_profilePopup indexOfSelectedItem];
572     VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
574     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
575     NSUInteger selectedProfile = [_profilePopup indexOfSelectedItem];
577     /* fetch preset */
578     NSArray *items = [[[defaults objectForKey:@"VideoEffectProfiles"] objectAtIndex:selectedProfile] componentsSeparatedByString:@";"];
580     // version 1 of profile string has 32 entries
581     if ([items count] < 32) {
582         msg_Err(p_intf, "Error in parsing profile string");
583         [self resetValues];
584         return;
585     }
587     /* filter handling */
588     NSString *tempString = B64DecNSStr([items firstObject]);
589     vout_thread_t *p_vout = getVout();
591     /* enable the new filters */
592     config_PutPsz(p_intf, "video-filter", [tempString UTF8String]);
593     if (p_vout) {
594         var_SetString(p_vout, "video-filter", [tempString UTF8String]);
595     }
597     tempString = B64DecNSStr([items objectAtIndex:1]);
598     /* enable another round of new filters */
599     config_PutPsz(p_intf, "sub-source", [tempString UTF8String]);
600     if (p_vout) {
601         var_SetString(p_vout, "sub-source", [tempString UTF8String]);
602     }
604     if (p_vout) {
605         vlc_object_release(p_vout);
606     }
608     tempString = B64DecNSStr([items objectAtIndex:2]);
609     /* enable another round of new filters */
610     char *psz_current_splitter = var_GetString(pl_Get(p_intf), "video-splitter");
611     bool b_filter_changed = ![tempString isEqualToString:toNSStr(psz_current_splitter)];
612     free(psz_current_splitter);
614     if (b_filter_changed) {
615         config_PutPsz(p_intf, "video-splitter", [tempString UTF8String]);
616         var_SetString(pl_Get(p_intf), "video-splitter", [tempString UTF8String]);
617     }
619     /* try to set filter values on-the-fly and store them appropriately */
620     // index 3 is deprecated
621     [vci_si setVideoFilterProperty:"contrast" forFilter:"adjust" float:[[items objectAtIndex:4] floatValue]];
622     [vci_si setVideoFilterProperty:"brightness" forFilter:"adjust" float:[[items objectAtIndex:5] floatValue]];
623     [vci_si setVideoFilterProperty:"saturation" forFilter:"adjust" float:[[items objectAtIndex:6] floatValue]];
624     [vci_si setVideoFilterProperty:"gamma" forFilter:"adjust" float:[[items objectAtIndex:7] floatValue]];
625     [vci_si setVideoFilterProperty:"sharpen-sigma" forFilter:"sharpen" float:[[items objectAtIndex:8] floatValue]];
626     [vci_si setVideoFilterProperty:"gradfun-radius" forFilter:"gradfun" integer:[[items objectAtIndex:9] intValue]];
627     [vci_si setVideoFilterProperty:"grain-variance" forFilter:"grain" float:[[items objectAtIndex:10] floatValue]];
628     [vci_si setVideoFilterProperty:"transform-type" forFilter:"transform" string:[B64DecNSStr([items objectAtIndex:11]) UTF8String]];
629     [vci_si setVideoFilterProperty:"puzzle-rows" forFilter:"puzzle" integer:[[items objectAtIndex:12] intValue]];
630     [vci_si setVideoFilterProperty:"puzzle-cols" forFilter:"puzzle" integer:[[items objectAtIndex:13] intValue]];
631     [vci_si setVideoFilterProperty:"colorthres-color" forFilter:"colorthres" integer:[[items objectAtIndex:14] intValue]];
632     [vci_si setVideoFilterProperty:"colorthres-saturationthres" forFilter:"colorthres" integer:[[items objectAtIndex:15] intValue]];
633     [vci_si setVideoFilterProperty:"colorthres-similaritythres" forFilter:"colorthres" integer:[[items objectAtIndex:16] intValue]];
634     [vci_si setVideoFilterProperty:"sepia-intensity" forFilter:"sepia" integer:[[items objectAtIndex:17] intValue]];
635     [vci_si setVideoFilterProperty:"gradient-mode" forFilter:"gradient" string:[B64DecNSStr([items objectAtIndex:18]) UTF8String]];
636     [vci_si setVideoFilterProperty:"gradient-cartoon" forFilter:"gradient" boolean:[[items objectAtIndex:19] intValue]];
637     [vci_si setVideoFilterProperty:"gradient-type" forFilter:"gradient" integer:[[items objectAtIndex:20] intValue]];
638     [vci_si setVideoFilterProperty:"extract-component" forFilter:"extract" integer:[[items objectAtIndex:21] intValue]];
639     [vci_si setVideoFilterProperty:"posterize-level" forFilter:"posterize" integer:[[items objectAtIndex:22] intValue]];
640     [vci_si setVideoFilterProperty:"blur-factor" forFilter:"motionblur" integer:[[items objectAtIndex:23] intValue]];
641     [vci_si setVideoFilterProperty:"marq-marquee" forFilter:"marq" string:[B64DecNSStr([items objectAtIndex:24]) UTF8String]];
642     [vci_si setVideoFilterProperty:"marq-position" forFilter:"marq" integer:[[items objectAtIndex:25] intValue]];
643     [vci_si setVideoFilterProperty:"logo-file" forFilter:"logo" string:[B64DecNSStr([items objectAtIndex:26]) UTF8String]];
644     [vci_si setVideoFilterProperty:"logo-position" forFilter:"logo" integer:[[items objectAtIndex:27] intValue]];
645     [vci_si setVideoFilterProperty:"logo-opacity" forFilter:"logo" integer:[[items objectAtIndex:28] intValue]];
646     [vci_si setVideoFilterProperty:"clone-count" forFilter:"clone" integer:[[items objectAtIndex:29] intValue]];
647     [vci_si setVideoFilterProperty:"wall-rows" forFilter:"wall" integer:[[items objectAtIndex:30] intValue]];
648     [vci_si setVideoFilterProperty:"wall-cols" forFilter:"wall" integer:[[items objectAtIndex:31] intValue]];
650     if ([items count] >= 33) { // version >=2 of profile string
651         [vci_si setVideoFilterProperty: "brightness-threshold" forFilter: "adjust" boolean: [[items objectAtIndex:32] intValue]];
652     }
654     float hueValue;
655     if ([items count] >= 34) { // version >=3 of profile string
656         hueValue = [[items objectAtIndex:33] floatValue];
657     } else {
658         hueValue = [[items objectAtIndex:3] intValue]; // deprecated since 3.0.0
659         // convert to new scale ([0,360] --> [-180,180])
660         hueValue -= 180;
661     }
662     [vci_si setVideoFilterProperty:"hue" forFilter:"adjust" float:hueValue];
664     [defaults setInteger:selectedProfile forKey:@"VideoEffectSelectedProfile"];
665     [defaults synchronize];
667     [self resetValues];
670 - (void)addProfile:(id)sender
672     /* show panel */
673 #pragma clang diagnostic push
674 #pragma clang diagnostic ignored "-Wpartial-availability"
675 #ifdef MAC_OS_X_VERSION_10_10
676     if (OSX_YOSEMITE_AND_HIGHER) {
677         [[_textfieldPanel window] setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]];
678     }
679 #endif
680 #pragma clang diagnostic pop
681     [_textfieldPanel setTitleString:_NS("Duplicate current profile for a new profile")];
682     [_textfieldPanel setSubTitleString:_NS("Enter a name for the new profile:")];
683     [_textfieldPanel setCancelButtonString:_NS("Cancel")];
684     [_textfieldPanel setOkButtonString:_NS("Save")];
686     __weak typeof(self) _self = self;
687     [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
689         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
691         if (returnCode != NSOKButton) {
692             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
693             return;
694         }
696         NSArray *profileNames = [defaults objectForKey:@"VideoEffectProfileNames"];
698         // duplicate names are not allowed in the popup control
699         if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) {
700             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
702             NSAlert *alert = [[NSAlert alloc] init];
703             [alert setAlertStyle:NSCriticalAlertStyle];
704             [alert setMessageText:_NS("Please enter a unique name for the new profile.")];
705             [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")];
707             [alert beginSheetModalForWindow:_self.window
708                               modalDelegate:nil
709                              didEndSelector:nil
710                                 contextInfo:nil];
711             return;
712         }
714         /* fetch all the current settings in a uniform string */
715         NSString *newProfile = [_self generateProfileString];
717         /* add string to user defaults as well as a label */
719         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfiles"]];
720         [workArray addObject:newProfile];
721         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"];
722         [defaults setInteger:[workArray count] - 1 forKey:@"VideoEffectSelectedProfile"];
724         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"VideoEffectProfileNames"]];
725         [workArray addObject:resultingText];
726         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"];
728         /* save defaults */
729         [defaults synchronize];
731         /* refresh UI */
732         [_self resetProfileSelector];
733     }];
736 - (void)removeProfile:(id)sender
738     /* show panel */
739 #pragma clang diagnostic push
740 #pragma clang diagnostic ignored "-Wpartial-availability"
741 #ifdef MAC_OS_X_VERSION_10_10
742     if (OSX_YOSEMITE_AND_HIGHER) {
743         [[_popupPanel window] setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantDark]];
744     }
745 #endif
746 #pragma clang diagnostic pop
747     [_popupPanel setTitleString:_NS("Remove a preset")];
748     [_popupPanel setSubTitleString:_NS("Select the preset you would like to remove:")];
749     [_popupPanel setOkButtonString:_NS("Remove")];
750     [_popupPanel setCancelButtonString:_NS("Cancel")];
751     [_popupPanel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"VideoEffectProfileNames"]];
753     __weak typeof(self) _self = self;
754     [_popupPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSInteger selectedIndex) {
756         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
758         if (returnCode != NSOKButton) {
759             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"VideoEffectSelectedProfile"]];
760             return;
761         }
763         /* remove selected profile from settings */
764         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray: [defaults objectForKey:@"VideoEffectProfiles"]];
765         [workArray removeObjectAtIndex:selectedIndex];
766         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfiles"];
768         workArray = [[NSMutableArray alloc] initWithArray: [defaults objectForKey:@"VideoEffectProfileNames"]];
769         [workArray removeObjectAtIndex:selectedIndex];
770         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"VideoEffectProfileNames"];
772         if (i_old_profile_index >= selectedIndex)
773             [defaults setInteger:i_old_profile_index - 1 forKey:@"VideoEffectSelectedProfile"];
775         /* save defaults */
776         [defaults synchronize];
778         /* do not save deleted profile */
779         i_old_profile_index = -1;
780         /* refresh UI */
781         [_self resetProfileSelector];
782     }];
785 #pragma mark -
786 #pragma mark basic
787 - (IBAction)enableAdjust:(id)sender
789     BOOL b_state = [_adjustCheckbox state];
791     [[VLCCoreInteraction sharedInstance] setVideoFilter: "adjust" on: b_state];
792     [_adjustBrightnessSlider setEnabled: b_state];
793     [_adjustBrightnessCheckbox setEnabled: b_state];
794     [_adjustBrightnessLabel setEnabled: b_state];
795     [_adjustContrastSlider setEnabled: b_state];
796     [_adjustContrastLabel setEnabled: b_state];
797     [_adjustGammaSlider setEnabled: b_state];
798     [_adjustGammaLabel setEnabled: b_state];
799     [_adjustHueSlider setEnabled: b_state];
800     [_adjustHueLabel setEnabled: b_state];
801     [_adjustSaturationSlider setEnabled: b_state];
802     [_adjustSaturationLabel setEnabled: b_state];
803     [_adjustResetButton setEnabled: b_state];
806 - (IBAction)adjustSliderChanged:(id)sender
808     if (sender == _adjustBrightnessSlider)
809         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "brightness" forFilter: "adjust" float: [_adjustBrightnessSlider floatValue]];
810     else if (sender == _adjustContrastSlider)
811         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "contrast" forFilter: "adjust" float: [_adjustContrastSlider floatValue]];
812     else if (sender == _adjustGammaSlider)
813         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gamma" forFilter: "adjust" float: [_adjustGammaSlider floatValue]];
814     else if (sender == _adjustHueSlider)
815         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "hue" forFilter: "adjust" float: [_adjustHueSlider floatValue]];
816     else if (sender == _adjustSaturationSlider)
817         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "saturation" forFilter: "adjust" float: [_adjustSaturationSlider floatValue]];
819     if (sender == _adjustHueSlider)
820         [_adjustHueSlider setToolTip: [NSString stringWithFormat:@"%.0f", [_adjustHueSlider floatValue]]];
821     else
822         [sender setToolTip: [NSString stringWithFormat:@"%0.3f", [sender floatValue]]];
825 - (IBAction)enableAdjustBrightnessThreshold:(id)sender
827     VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
829     if (sender == _adjustResetButton) {
830         [_adjustBrightnessSlider setFloatValue: 1.0];
831         [_adjustContrastSlider setFloatValue: 1.0];
832         [_adjustGammaSlider setFloatValue: 1.0];
833         [_adjustHueSlider setFloatValue: 0];
834         [_adjustSaturationSlider setFloatValue: 1.0];
835         [_adjustBrightnessSlider setToolTip: [NSString stringWithFormat:@"%0.3f", 1.0]];
836         [_adjustContrastSlider setToolTip: [NSString stringWithFormat:@"%0.3f", 1.0]];
837         [_adjustGammaSlider setToolTip: [NSString stringWithFormat:@"%0.3f", 1.0]];
838         [_adjustHueSlider setToolTip: [NSString stringWithFormat:@"%.0f", 0.0]];
839         [_adjustSaturationSlider setToolTip: [NSString stringWithFormat:@"%0.3f", 1.0]];
840         [vci_si setVideoFilterProperty: "brightness" forFilter: "adjust" float: 1.0];
841         [vci_si setVideoFilterProperty: "contrast" forFilter: "adjust" float: 1.0];
842         [vci_si setVideoFilterProperty: "gamma" forFilter: "adjust" float: 1.0];
843         [vci_si setVideoFilterProperty: "hue" forFilter: "adjust" float: 0.0];
844         [vci_si setVideoFilterProperty: "saturation" forFilter: "adjust" float: 1.0];
845     } else
846         [vci_si setVideoFilterProperty: "brightness-threshold" forFilter: "adjust" boolean: [_adjustBrightnessCheckbox state]];
850 - (IBAction)enableSharpen:(id)sender
852     BOOL b_state = [_sharpenCheckbox state];
854     [[VLCCoreInteraction sharedInstance] setVideoFilter: "sharpen" on: b_state];
855     [_sharpenSlider setEnabled: b_state];
856     [_sharpenLabel setEnabled: b_state];
859 - (IBAction)sharpenSliderChanged:(id)sender
861     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "sharpen-sigma" forFilter: "sharpen" float: [sender floatValue]];
862     [sender setToolTip: [NSString stringWithFormat:@"%0.3f", [sender floatValue]]];
865 - (IBAction)enableBanding:(id)sender
867     BOOL b_state = [_bandingCheckbox state];
869     [[VLCCoreInteraction sharedInstance] setVideoFilter: "gradfun" on: b_state];
870     [_bandingSlider setEnabled: b_state];
871     [_bandingLabel setEnabled: b_state];
874 - (IBAction)bandingSliderChanged:(id)sender
876     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradfun-radius" forFilter: "gradfun" integer: [sender intValue]];
877     [sender setToolTip: [NSString stringWithFormat:@"%i", [sender intValue]]];
880 - (IBAction)enableGrain:(id)sender
882     BOOL b_state = [_grainCheckbox state];
884     [[VLCCoreInteraction sharedInstance] setVideoFilter: "grain" on: b_state];
885     [_grainSlider setEnabled: b_state];
886     [_grainLabel setEnabled: b_state];
889 - (IBAction)grainSliderChanged:(id)sender
891     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "grain-variance" forFilter: "grain" float: [sender floatValue]];
892     [sender setToolTip: [NSString stringWithFormat:@"%0.3f", [sender floatValue]]];
896 #pragma mark -
897 #pragma mark crop
899 - (IBAction)cropObjectChanged:(id)sender
901     if ([_cropSyncTopBottomCheckbox state]) {
902         if (sender == _cropBottomTextField || sender == _cropBottomStepper)
903             [self setCropTopValue: [self cropBottomValue]];
904         else
905             [self setCropBottomValue: [self cropTopValue]];
906     }
907     if ([_cropSyncLeftRightCheckbox state]) {
908         if (sender == _cropRightTextField || sender == _cropRightStepper)
909             [self setCropLeftValue: [self cropRightValue]];
910         else
911             [self setCropRightValue: [self cropLeftValue]];
912     }
914     vout_thread_t *p_vout = getVout();
915     if (p_vout) {
916         var_SetInteger(p_vout, "crop-top", [_cropTopTextField intValue]);
917         var_SetInteger(p_vout, "crop-bottom", [_cropBottomTextField intValue]);
918         var_SetInteger(p_vout, "crop-left", [_cropLeftTextField intValue]);
919         var_SetInteger(p_vout, "crop-right", [_cropRightTextField intValue]);
920         vlc_object_release(p_vout);
921     }
924 #pragma mark -
925 #pragma mark geometry
926 - (IBAction)enableTransform:(id)sender
928     [[VLCCoreInteraction sharedInstance] setVideoFilter: "transform" on: [_transformCheckbox state]];
929     [_transformPopup setEnabled: [_transformCheckbox state]];
932 - (IBAction)transformModifierChanged:(id)sender
934     NSInteger tag = [[_transformPopup selectedItem] tag];
935     const char *psz_string = [[NSString stringWithFormat:@"%li", tag] UTF8String];
936     if (tag == 1)
937         psz_string = "hflip";
938     else if (tag == 2)
939         psz_string = "vflip";
941     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "transform-type" forFilter: "transform" string: psz_string];
944 - (IBAction)enableZoom:(id)sender
946     [[VLCCoreInteraction sharedInstance] setVideoFilter: "magnify" on: [_zoomCheckbox state]];
949 - (IBAction)enablePuzzle:(id)sender
951     BOOL b_state = [_puzzleCheckbox state];
953     [[VLCCoreInteraction sharedInstance] setVideoFilter: "puzzle" on: b_state];
954     [_puzzleColumnsTextField setEnabled: b_state];
955     [_puzzleColumnsStepper setEnabled: b_state];
956     [_puzzleColumnsLabel setEnabled: b_state];
957     [_puzzleRowsTextField setEnabled: b_state];
958     [_puzzleRowsStepper setEnabled: b_state];
959     [_puzzleRowsLabel setEnabled: b_state];
962 - (IBAction)puzzleModifierChanged:(id)sender
964     if (sender == _puzzleColumnsTextField || sender == _puzzleColumnsStepper)
965         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "puzzle-cols" forFilter: "puzzle" integer: [sender intValue]];
966     else
967         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "puzzle-rows" forFilter: "puzzle" integer: [sender intValue]];
970 - (IBAction)enableClone:(id)sender
972     BOOL b_state = [_cloneCheckbox state];
974     if (b_state && [_wallCheckbox state]) {
975         [_wallCheckbox setState: NSOffState];
976         [self enableWall:_wallCheckbox];
977     }
979     [[VLCCoreInteraction sharedInstance] setVideoFilter: "clone" on: b_state];
980     [_cloneNumberLabel setEnabled: b_state];
981     [_cloneNumberTextField setEnabled: b_state];
982     [_cloneNumberStepper setEnabled: b_state];
985 - (IBAction)cloneModifierChanged:(id)sender
987     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "clone-count" forFilter: "clone" integer: [_cloneNumberTextField intValue]];
990 - (IBAction)enableWall:(id)sender
992     BOOL b_state = [_wallCheckbox state];
994     if (b_state && [_cloneCheckbox state]) {
995         [_cloneCheckbox setState: NSOffState];
996         [self enableClone:_cloneCheckbox];
997     }
999     [[VLCCoreInteraction sharedInstance] setVideoFilter: "wall" on: b_state];
1000     [_wallNumberOfColumnsTextField setEnabled: b_state];
1001     [_wallNumberOfColumnsStepper setEnabled: b_state];
1002     [_wallNumberOfColumnsLabel setEnabled: b_state];
1004     [_wallNumbersOfRowsTextField setEnabled: b_state];
1005     [_wallNumbersOfRowsStepper setEnabled: b_state];
1006     [_wallNumbersOfRowsLabel setEnabled: b_state];
1009 - (IBAction)wallModifierChanged:(id)sender
1011     if (sender == _wallNumberOfColumnsTextField || sender == _wallNumberOfColumnsStepper)
1012         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "wall-cols" forFilter: "wall" integer: [sender intValue]];
1013     else
1014         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "wall-rows" forFilter: "wall" integer: [sender intValue]];
1017 #pragma mark -
1018 #pragma mark color
1019 - (IBAction)enableThreshold:(id)sender
1021     BOOL b_state = [_thresholdCheckbox state];
1023     [[VLCCoreInteraction sharedInstance] setVideoFilter: "colorthres" on: b_state];
1024     [_thresholdColorTextField setEnabled: b_state];
1025     [_thresholdColorLabel setEnabled: b_state];
1026     [_thresholdSaturationSlider setEnabled: b_state];
1027     [_thresholdSaturationLabel setEnabled: b_state];
1028     [_thresholdSimilaritySlider setEnabled: b_state];
1029     [_thresholdSimilarityLabel setEnabled: b_state];
1032 - (IBAction)thresholdModifierChanged:(id)sender
1034     if (sender == _thresholdColorTextField)
1035         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-color" forFilter: "colorthres" integer: [_thresholdColorTextField intValue]];
1036     else if (sender == _thresholdSaturationSlider) {
1037         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-saturationthres" forFilter: "colorthres" integer: [_thresholdSaturationSlider intValue]];
1038         [_thresholdSaturationSlider setToolTip: [NSString stringWithFormat:@"%i", [_thresholdSaturationSlider intValue]]];
1039     } else {
1040         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-similaritythres" forFilter: "colorthres" integer: [_thresholdSimilaritySlider intValue]];
1041         [_thresholdSimilaritySlider setToolTip: [NSString stringWithFormat:@"%i", [_thresholdSimilaritySlider intValue]]];
1042     }
1045 - (IBAction)enableSepia:(id)sender
1047     BOOL b_state = [_sepiaCheckbox state];
1049     [[VLCCoreInteraction sharedInstance] setVideoFilter: "sepia" on: b_state];
1050     [_sepiaTextField setEnabled: b_state];
1051     [_sepiaStepper setEnabled: b_state];
1052     [_sepiaLabel setEnabled: b_state];
1055 - (IBAction)sepiaModifierChanged:(id)sender
1057     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "sepia-intensity" forFilter: "sepia" integer: [_sepiaTextField intValue]];
1060 - (IBAction)enableNoise:(id)sender
1062     [[VLCCoreInteraction sharedInstance] setVideoFilter: "noise" on: [_noiseCheckbox state]];
1065 - (IBAction)enableGradient:(id)sender
1067     BOOL b_state = [_gradientCheckbox state];
1069     [[VLCCoreInteraction sharedInstance] setVideoFilter: "gradient" on: b_state];
1070     [_gradientModePopup setEnabled: b_state];
1071     [_gradientModeLabel setEnabled: b_state];
1072     [_gradientColorCheckbox setEnabled: b_state];
1073     [_gradientCartoonCheckbox setEnabled: b_state];
1076 - (IBAction)gradientModifierChanged:(id)sender
1078     if (sender == _gradientModePopup) {
1079         if ([[_gradientModePopup selectedItem] tag] == 3)
1080             [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-mode" forFilter: "gradient" string: "hough"];
1081         else if ([[_gradientModePopup selectedItem] tag] == 2)
1082             [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-mode" forFilter: "gradient" string: "edge"];
1083         else
1084             [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-mode" forFilter: "gradient" string: "gradient"];
1085     } else if (sender == _gradientColorCheckbox)
1086         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-type" forFilter: "gradient" integer: [_gradientColorCheckbox state]];
1087     else
1088         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-cartoon" forFilter: "gradient" boolean: [_gradientCartoonCheckbox state]];
1091 - (IBAction)enableExtract:(id)sender
1093     BOOL b_state = [_extractCheckbox state];
1094     [[VLCCoreInteraction sharedInstance] setVideoFilter: "extract" on: b_state];
1095     [_extractTextField setEnabled: b_state];
1096     [_extractLabel setEnabled: b_state];
1099 - (IBAction)extractModifierChanged:(id)sender
1101     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "extract-component" forFilter: "extract" integer: [_extractTextField intValue]];
1104 - (IBAction)enableInvert:(id)sender
1106     [[VLCCoreInteraction sharedInstance] setVideoFilter: "invert" on: [_invertCheckbox state]];
1109 - (IBAction)enablePosterize:(id)sender
1111     BOOL b_state = [_posterizeCheckbox state];
1113     [[VLCCoreInteraction sharedInstance] setVideoFilter: "posterize" on: b_state];
1114     [_posterizeTextField setEnabled: b_state];
1115     [_posterizeStepper setEnabled: b_state];
1116     [_posterizeLabel setEnabled: b_state];
1119 - (IBAction)posterizeModifierChanged:(id)sender
1121     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "posterize-level" forFilter: "posterize" integer: [_posterizeTextField intValue]];
1124 - (IBAction)enableBlur:(id)sender
1126     BOOL b_state = [_blurCheckbox state];
1128     [[VLCCoreInteraction sharedInstance] setVideoFilter: "motionblur" on: b_state];
1129     [_blurSlider setEnabled: b_state];
1130     [_blurLabel setEnabled: b_state];
1133 - (IBAction)blurModifierChanged:(id)sender
1135     [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "blur-factor" forFilter: "motionblur" integer: [sender intValue]];
1136     [sender setToolTip: [NSString stringWithFormat:@"%i", [sender intValue]]];
1139 - (IBAction)enableMotionDetect:(id)sender
1141     [[VLCCoreInteraction sharedInstance] setVideoFilter: "motiondetect" on: [_motiondetectCheckbox state]];
1144 - (IBAction)enableWaterEffect:(id)sender
1146     [[VLCCoreInteraction sharedInstance] setVideoFilter: "ripple" on: [_watereffectCheckbox state]];
1149 - (IBAction)enableWaves:(id)sender
1151     [[VLCCoreInteraction sharedInstance] setVideoFilter: "wave" on: [_wavesCheckbox state]];
1154 - (IBAction)enablePsychedelic:(id)sender
1156     [[VLCCoreInteraction sharedInstance] setVideoFilter: "psychedelic" on: [_psychedelicCheckbox state]];
1159 #pragma mark -
1160 #pragma mark Miscellaneous
1161 - (IBAction)enableAddText:(id)sender
1163     BOOL b_state = [_addTextCheckbox state];
1164     VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
1166     [_addTextPositionPopup setEnabled: b_state];
1167     [_addTextPositionLabel setEnabled: b_state];
1168     [_addTextTextLabel setEnabled: b_state];
1169     [_addTextTextTextField setEnabled: b_state];
1170     [vci_si setVideoFilter: "marq" on: b_state];
1171     [vci_si setVideoFilterProperty: "marq-marquee" forFilter: "marq" string: [[_addTextTextTextField stringValue] UTF8String]];
1172     [vci_si setVideoFilterProperty: "marq-position" forFilter: "marq" integer: [[_addTextPositionPopup selectedItem] tag]];
1175 - (IBAction)addTextModifierChanged:(id)sender
1177     if (sender == _addTextTextTextField)
1178         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "marq-marquee" forFilter: "marq" string:[[_addTextTextTextField stringValue] UTF8String]];
1179     else
1180         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "marq-position" forFilter: "marq" integer: [[_addTextPositionPopup selectedItem] tag]];
1183 - (IBAction)enableAddLogo:(id)sender
1185     BOOL b_state = [_addLogoCheckbox state];
1187     [_addLogoPositionPopup setEnabled: b_state];
1188     [_addLogoPositionLabel setEnabled: b_state];
1189     [_addLogoLogoTextField setEnabled: b_state];
1190     [_addLogoLogoLabel setEnabled: b_state];
1191     [_addLogoTransparencySlider setEnabled: b_state];
1192     [_addLogoTransparencyLabel setEnabled: b_state];
1193     [[VLCCoreInteraction sharedInstance] setVideoFilter: "logo" on: b_state];
1196 - (IBAction)addLogoModifierChanged:(id)sender
1198     if (sender == _addLogoLogoTextField)
1199         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-file" forFilter: "logo" string: [[_addLogoLogoTextField stringValue] UTF8String]];
1200     else if (sender == _addLogoPositionPopup)
1201         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-position" forFilter: "logo" integer: [[_addLogoPositionPopup selectedItem] tag]];
1202     else {
1203         [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-opacity" forFilter: "logo" integer: [_addLogoTransparencySlider intValue]];
1204         [_addLogoTransparencySlider setToolTip: [NSString stringWithFormat:@"%i", [_addLogoTransparencySlider intValue]]];
1205     }
1208 - (IBAction)enableAnaglyph:(id)sender
1210     [[VLCCoreInteraction sharedInstance] setVideoFilter: "anaglyph" on: [_anaglyphCheckbox state]];
1213 @end