[vlc-commits] macosx/coreinteraction: split apple remote, media key and video filter handling as those don't belong there

Felix Paul Kühne git at videolan.org
Tue Jan 29 18:48:46 CET 2019


vlc | branch: master | Felix Paul Kühne <felix at feepk.net> | Tue Jan 29 18:47:42 2019 +0100| [9609740bfa5dd79d87130f8a3bfe4a72b1c3f819] | committer: Felix Paul Kühne

macosx/coreinteraction: split apple remote, media key and video filter handling as those don't belong there

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9609740bfa5dd79d87130f8a3bfe4a72b1c3f819
---

 .../package/macosx/VLC.xcodeproj/project.pbxproj   |  22 +-
 modules/gui/macosx/Makefile.am                     |   2 +
 modules/gui/macosx/VLCClickerManager.h             |  27 ++
 modules/gui/macosx/VLCClickerManager.m             | 301 +++++++++++++
 modules/gui/macosx/VLCCoreInteraction.h            |  11 +-
 modules/gui/macosx/VLCCoreInteraction.m            | 472 ++-------------------
 modules/gui/macosx/VLCMain+OldPrefs.m              |   3 +-
 modules/gui/macosx/VLCMain.h                       |   1 +
 modules/gui/macosx/VLCMain.m                       |  17 -
 modules/gui/macosx/VLCMainMenu.m                   |  11 +-
 modules/gui/macosx/VLCSimplePrefsController.m      |  15 +-
 modules/gui/macosx/VLCStringUtility.h              |   5 +
 modules/gui/macosx/VLCStringUtility.m              |  33 ++
 .../VLCTrackSynchronizationWindowController.m      |   4 +-
 .../gui/macosx/VLCVideoEffectsWindowController.m   | 175 ++++----
 modules/gui/macosx/VLCVideoFilterHelper.h          |  31 ++
 modules/gui/macosx/VLCVideoFilterHelper.m          | 177 ++++++++
 modules/gui/macosx/prefs.m                         |   2 +-
 18 files changed, 723 insertions(+), 586 deletions(-)

diff --git a/extras/package/macosx/VLC.xcodeproj/project.pbxproj b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
index 08d0ad2f97..4df4f3c775 100644
--- a/extras/package/macosx/VLC.xcodeproj/project.pbxproj
+++ b/extras/package/macosx/VLC.xcodeproj/project.pbxproj
@@ -122,6 +122,8 @@
 		6BF5C5041EFE66EF008A9C12 /* VLCHUDTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BF5C5031EFE66EF008A9C12 /* VLCHUDTableView.m */; };
 		7D2E0EDB20CD204D0033A221 /* VLCWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D2E0ED920CD204D0033A221 /* VLCWindow.m */; };
 		7D2E0EDE20CD206F0033A221 /* VLCVideoWindowCommon.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D2E0EDD20CD206F0033A221 /* VLCVideoWindowCommon.m */; };
+		7D66D4362200BC340040D04A /* VLCClickerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D66D4352200BC340040D04A /* VLCClickerManager.m */; };
+		7D66D4392200C5B80040D04A /* VLCVideoFilterHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D66D4382200C5B80040D04A /* VLCVideoFilterHelper.m */; };
 		7DB40D2A20CBCEB500F63173 /* VLCMainMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB40D2920CBCEB500F63173 /* VLCMainMenu.m */; };
 		7DB40D2D20CBCEC200F63173 /* VLCStatusBarIcon.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB40D2B20CBCEC200F63173 /* VLCStatusBarIcon.m */; };
 		7DB7F1EC20CC036D00C2CAED /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7DB7F1EB20CC036D00C2CAED /* AudioUnit.framework */; };
@@ -437,6 +439,10 @@
 		7D5678EC1D5BA1DC002698F3 /* VLCApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCApplication.m; sourceTree = "<group>"; };
 		7D5678EE1D5BA397002698F3 /* VLCMainWindowControlsBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VLCMainWindowControlsBar.h; sourceTree = "<group>"; };
 		7D5678EF1D5BA397002698F3 /* VLCMainWindowControlsBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCMainWindowControlsBar.m; sourceTree = "<group>"; };
+		7D66D4342200BC340040D04A /* VLCClickerManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCClickerManager.h; sourceTree = "<group>"; };
+		7D66D4352200BC340040D04A /* VLCClickerManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCClickerManager.m; sourceTree = "<group>"; };
+		7D66D4372200C5B80040D04A /* VLCVideoFilterHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCVideoFilterHelper.h; sourceTree = "<group>"; };
+		7D66D4382200C5B80040D04A /* VLCVideoFilterHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCVideoFilterHelper.m; sourceTree = "<group>"; };
 		7D871D371B5E6844000B56C0 /* VLCMain+OldPrefs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VLCMain+OldPrefs.h"; sourceTree = "<group>"; };
 		7D871D381B5E6844000B56C0 /* VLCMain+OldPrefs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "VLCMain+OldPrefs.m"; sourceTree = "<group>"; };
 		7D871D391B5E684D000B56C0 /* helpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = helpers.h; sourceTree = "<group>"; };
@@ -998,6 +1004,8 @@
 				6B397C4E216C8EB200403ED0 /* NSString+Helpers.m */,
 				6B7F1FDD1F07DA920002BDD8 /* VLCHexNumberFormatter.h */,
 				6B7F1FDE1F07DA920002BDD8 /* VLCHexNumberFormatter.m */,
+				7D66D4372200C5B80040D04A /* VLCVideoFilterHelper.h */,
+				7D66D4382200C5B80040D04A /* VLCVideoFilterHelper.m */,
 			);
 			name = Helpers;
 			sourceTree = "<group>";
@@ -1051,6 +1059,8 @@
 				7D349C9820CBC881003359A1 /* Core Dialog Provider */,
 				CC448A6013B68A0B009F72E0 /* VLCCoreInteraction.h */,
 				CC448A6113B68A0B009F72E0 /* VLCCoreInteraction.m */,
+				7D66D4342200BC340040D04A /* VLCClickerManager.h */,
+				7D66D4352200BC340040D04A /* VLCClickerManager.m */,
 				7DF812ED1B555A340052293C /* VLCInputManager.h */,
 				7DF812EE1B555A340052293C /* VLCInputManager.m */,
 			);
@@ -1551,7 +1561,7 @@
 					};
 				};
 			};
-			buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */;
+			buildConfigurationList = C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */;
 			compatibilityVersion = "Xcode 6.3";
 			developmentRegion = English;
 			hasScannedForEncodings = 1;
@@ -1587,6 +1597,7 @@
 				1CCC88F42078A3D500E5626F /* Bookmarks.xib in Sources */,
 				1CCC88F52078A3D500E5626F /* SyncTracks.xib in Sources */,
 				1CCC88F62078A3D500E5626F /* MediaInfo.xib in Sources */,
+				7D66D4392200C5B80040D04A /* VLCVideoFilterHelper.m in Sources */,
 				1CCC88F72078A3D500E5626F /* ConvertAndSave.xib in Sources */,
 				1CCC88F82078A3D500E5626F /* CoreDialogs.xib in Sources */,
 				1CCC88F92078A3D500E5626F /* DetachedVideoWindow.xib in Sources */,
@@ -1648,6 +1659,7 @@
 				1C3113AB1E508C6900D4DD76 /* VLCExtensionsDialogProvider.m in Sources */,
 				1C3113AD1E508C6900D4DD76 /* VLCExtensionsManager.m in Sources */,
 				1C3113AF1E508C6900D4DD76 /* VLCFSPanelController.m in Sources */,
+				7D66D4362200BC340040D04A /* VLCClickerManager.m in Sources */,
 				1C3113B11E508C6900D4DD76 /* VLCFSPanelDraggableView.m in Sources */,
 				1C3113B41E508C6900D4DD76 /* VLCInputManager.m in Sources */,
 				1C3113B61E508C6900D4DD76 /* VLCMain+OldPrefs.m in Sources */,
@@ -1855,7 +1867,7 @@
 				ONLY_ACTIVE_ARCH = YES;
 				PATH = $VLC_PATH;
 				PRODUCT_NAME = VLC;
-				VLC_BUILD_TRIPLET = "x86_64-apple-darwin17";
+				VLC_BUILD_TRIPLET = "x86_64-apple-darwin18";
 				VLC_PATH = "${VLC_SRC_DIR}/contrib/${VLC_BUILD_TRIPLET}/bin:${VLC_SRC_DIR}/extras/tools/build/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin";
 				VLC_SRC_DIR = "$(PROJECT_DIR)/../../..";
 			};
@@ -1903,7 +1915,7 @@
 				MACOSX_DEPLOYMENT_TARGET = 10.11;
 				PATH = $VLC_PATH;
 				PRODUCT_NAME = VLC;
-				VLC_BUILD_TRIPLET = "x86_64-apple-darwin17";
+				VLC_BUILD_TRIPLET = "x86_64-apple-darwin18";
 				VLC_PATH = "${VLC_SRC_DIR}/contrib/${VLC_BUILD_TRIPLET}/bin:${VLC_SRC_DIR}/extras/tools/build/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin";
 				VLC_SRC_DIR = "$(PROJECT_DIR)/../../..";
 			};
@@ -1951,7 +1963,7 @@
 				MACOSX_DEPLOYMENT_TARGET = 10.11;
 				PATH = $VLC_PATH;
 				PRODUCT_NAME = VLC;
-				VLC_BUILD_TRIPLET = "x86_64-apple-darwin17";
+				VLC_BUILD_TRIPLET = "x86_64-apple-darwin18";
 				VLC_PATH = "${VLC_SRC_DIR}/contrib/${VLC_BUILD_TRIPLET}/bin:${VLC_SRC_DIR}/extras/tools/build/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin";
 				VLC_SRC_DIR = "$(PROJECT_DIR)/../../..";
 			};
@@ -1970,7 +1982,7 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Default;
 		};
-		C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "vlc" */ = {
+		C2F2A6EA09588F1B00018C74 /* Build configuration list for PBXProject "VLC" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
 				C2F2A6EB09588F1B00018C74 /* Development */,
diff --git a/modules/gui/macosx/Makefile.am b/modules/gui/macosx/Makefile.am
index fde34dcdc2..4d543ae115 100644
--- a/modules/gui/macosx/Makefile.am
+++ b/modules/gui/macosx/Makefile.am
@@ -38,6 +38,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/VLCMainWindowControlsBar.m gui/macosx/VLCMainWindowControlsBar.h \
 	gui/macosx/VLCConvertAndSaveWindowController.h gui/macosx/VLCConvertAndSaveWindowController.m \
 	gui/macosx/VLCCoreInteraction.h gui/macosx/VLCCoreInteraction.m \
+	gui/macosx/VLCClickerManager.h gui/macosx/VLCClickerManager.m \
+	gui/macosx/VLCVideoFilterHelper.h gui/macosx/VLCVideoFilterHelper.m \
 	gui/macosx/VLCErrorWindowController.h gui/macosx/VLCErrorWindowController.m \
 	gui/macosx/VLCExtensionsDialogProvider.h gui/macosx/VLCExtensionsDialogProvider.m \
 	gui/macosx/VLCExtensionsManager.h gui/macosx/VLCExtensionsManager.m \
diff --git a/modules/gui/macosx/VLCClickerManager.h b/modules/gui/macosx/VLCClickerManager.h
new file mode 100644
index 0000000000..13f09de528
--- /dev/null
+++ b/modules/gui/macosx/VLCClickerManager.h
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * VLCClickerManager.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2011-2019 Felix Paul Kühne
+ *
+ * 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 <Foundation/Foundation.h>
+
+ at interface VLCClickerManager : NSObject
+
+ at end
diff --git a/modules/gui/macosx/VLCClickerManager.m b/modules/gui/macosx/VLCClickerManager.m
new file mode 100644
index 0000000000..2682d066b5
--- /dev/null
+++ b/modules/gui/macosx/VLCClickerManager.m
@@ -0,0 +1,301 @@
+/*****************************************************************************
+ * VLCClickerManager.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2011-2019 Felix Paul Kühne
+ *
+ * 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 "VLCClickerManager.h"
+#import "SPMediaKeyTap.h"
+#import "AppleRemote.h"
+#import "VLCMain.h"
+#import "VLCPlaylist.h"
+#import "VLCInputManager.h"
+#import "VLCCoreInteraction.h"
+#import "NSSound+VLCAdditions.h"
+#import <vlc_actions.h>
+
+ at interface VLCClickerManager()
+{
+    /* media key support */
+    BOOL b_mediaKeySupport;
+    BOOL b_mediakeyJustJumped;
+    SPMediaKeyTap *_mediaKeyController;
+    BOOL b_mediaKeyTrapEnabled;
+
+    AppleRemote *_remote;
+    BOOL b_remote_button_hold; /* true as long as the user holds the left,right,plus or minus on the remote control */
+}
+ at end
+
+ at implementation VLCClickerManager
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        /* init media key support */
+        b_mediaKeySupport = var_InheritBool(getIntf(), "macosx-mediakeys");
+        if (b_mediaKeySupport) {
+            _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
+        }
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        [notificationCenter addObserver:self
+                               selector:@selector(coreChangedMediaKeySupportSetting:)
+                                   name:VLCMediaKeySupportSettingChangedNotification
+                                 object:nil];
+        [notificationCenter addObserver:self
+                               selector:@selector(coreChangedAppleRemoteSetting:)
+                                   name:VLCAppleRemoteSettingChangedNotification
+                                 object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(startListeningWithAppleRemote)
+                                                     name:NSApplicationDidBecomeActiveNotification
+                                                   object:nil];
+
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(stopListeningWithAppleRemote)
+                                                     name:NSApplicationDidResignActiveNotification
+                                                   object:nil];
+
+        /* init Apple Remote support */
+        _remote = [[AppleRemote alloc] init];
+        [_remote setClickCountEnabledButtons: kRemoteButtonPlay];
+        [_remote setDelegate: self];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    _mediaKeyController = nil;
+    _remote = nil;
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark -
+#pragma mark Media Key support
+
+- (void)resetMediaKeyJump
+{
+    b_mediakeyJustJumped = NO;
+}
+
+- (void)coreChangedMediaKeySupportSetting: (NSNotification *)o_notification
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf)
+        return;
+
+    b_mediaKeySupport = var_InheritBool(p_intf, "macosx-mediakeys");
+    if (b_mediaKeySupport && !_mediaKeyController)
+        _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
+
+    VLCMain *main = [VLCMain sharedInstance];
+    if (b_mediaKeySupport && ([[[main playlist] model] hasChildren] ||
+                              [[main inputManager] hasInput])) {
+        if (!b_mediaKeyTrapEnabled) {
+            msg_Dbg(p_intf, "Enabling media key support");
+            if ([_mediaKeyController startWatchingMediaKeys]) {
+                b_mediaKeyTrapEnabled = YES;
+            } else {
+                msg_Warn(p_intf, "Failed to enable media key support, likely "
+                         "app needs to be whitelisted in Security Settings.");
+            }
+        }
+    } else {
+        if (b_mediaKeyTrapEnabled) {
+            b_mediaKeyTrapEnabled = NO;
+            msg_Dbg(p_intf, "Disabling media key support");
+            [_mediaKeyController stopWatchingMediaKeys];
+        }
+    }
+}
+
+-(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event
+{
+    if (b_mediaKeySupport) {
+        assert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys);
+
+        int keyCode = (([event data1] & 0xFFFF0000) >> 16);
+        int keyFlags = ([event data1] & 0x0000FFFF);
+        int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
+        int keyRepeat = (keyFlags & 0x1);
+
+        if (keyCode == NX_KEYTYPE_PLAY && keyState == 0)
+            [[VLCCoreInteraction sharedInstance] playOrPause];
+
+        if ((keyCode == NX_KEYTYPE_FAST || keyCode == NX_KEYTYPE_NEXT) && !b_mediakeyJustJumped) {
+            if (keyState == 0 && keyRepeat == 0)
+                [[VLCCoreInteraction sharedInstance] next];
+            else if (keyRepeat == 1) {
+                [[VLCCoreInteraction sharedInstance] forwardShort];
+                b_mediakeyJustJumped = YES;
+                [self performSelector:@selector(resetMediaKeyJump)
+                           withObject: NULL
+                           afterDelay:0.25];
+            }
+        }
+
+        if ((keyCode == NX_KEYTYPE_REWIND || keyCode == NX_KEYTYPE_PREVIOUS) && !b_mediakeyJustJumped) {
+            if (keyState == 0 && keyRepeat == 0)
+                [[VLCCoreInteraction sharedInstance] previous];
+            else if (keyRepeat == 1) {
+                [[VLCCoreInteraction sharedInstance] backwardShort];
+                b_mediakeyJustJumped = YES;
+                [self performSelector:@selector(resetMediaKeyJump)
+                           withObject: NULL
+                           afterDelay:0.25];
+            }
+        }
+    }
+}
+
+#pragma mark -
+#pragma mark Apple Remote Control
+
+- (void)coreChangedAppleRemoteSetting: (NSNotification *)notification
+{
+    if (var_InheritBool(getIntf(), "macosx-appleremote") == YES) {
+        [_remote startListening: self];
+    } else {
+        [_remote stopListening:self];
+    }
+}
+
+- (void)startListeningWithAppleRemote
+{
+    if (var_InheritBool(getIntf(), "macosx-appleremote") == YES)
+        [_remote startListening: self];
+}
+
+- (void)stopListeningWithAppleRemote
+{
+    [_remote stopListening:self];
+}
+
+/* Helper method for the remote control interface in order to trigger forward/backward and volume
+ increase/decrease as long as the user holds the left/right, plus/minus button */
+- (void) executeHoldActionForRemoteButton: (NSNumber*) buttonIdentifierNumber
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf)
+        return;
+
+    if (b_remote_button_hold) {
+        switch([buttonIdentifierNumber intValue]) {
+            case kRemoteButtonRight_Hold:
+                [[VLCCoreInteraction sharedInstance] forwardShort];
+                break;
+            case kRemoteButtonLeft_Hold:
+                [[VLCCoreInteraction sharedInstance] backwardShort];
+                break;
+            case kRemoteButtonVolume_Plus_Hold:
+                if (p_intf)
+                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_UP);
+                break;
+            case kRemoteButtonVolume_Minus_Hold:
+                if (p_intf)
+                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_DOWN);
+                break;
+        }
+        if (b_remote_button_hold) {
+            /* trigger event */
+            [self performSelector:@selector(executeHoldActionForRemoteButton:)
+                       withObject:buttonIdentifierNumber
+                       afterDelay:0.25];
+        }
+    }
+}
+
+/* Apple Remote callback */
+- (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier
+               pressedDown: (BOOL) pressedDown
+                clickCount: (unsigned int) count
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf)
+        return;
+
+    switch(buttonIdentifier) {
+        case k2009RemoteButtonFullscreen:
+            [[VLCCoreInteraction sharedInstance] toggleFullscreen];
+            break;
+        case k2009RemoteButtonPlay:
+            [[VLCCoreInteraction sharedInstance] playOrPause];
+            break;
+        case kRemoteButtonPlay:
+            if (count >= 2)
+                [[VLCCoreInteraction sharedInstance] toggleFullscreen];
+            else
+                [[VLCCoreInteraction sharedInstance] playOrPause];
+            break;
+        case kRemoteButtonVolume_Plus:
+            if (config_GetInt("macosx-appleremote-sysvol"))
+                [NSSound increaseSystemVolume];
+            else
+                if (p_intf)
+                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_UP);
+            break;
+        case kRemoteButtonVolume_Minus:
+            if (config_GetInt("macosx-appleremote-sysvol"))
+                [NSSound decreaseSystemVolume];
+            else
+                if (p_intf)
+                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_DOWN);
+            break;
+        case kRemoteButtonRight:
+            if (config_GetInt("macosx-appleremote-prevnext"))
+                [[VLCCoreInteraction sharedInstance] forwardShort];
+            else
+                [[VLCCoreInteraction sharedInstance] next];
+            break;
+        case kRemoteButtonLeft:
+            if (config_GetInt("macosx-appleremote-prevnext"))
+                [[VLCCoreInteraction sharedInstance] backwardShort];
+            else
+                [[VLCCoreInteraction sharedInstance] previous];
+            break;
+        case kRemoteButtonRight_Hold:
+        case kRemoteButtonLeft_Hold:
+        case kRemoteButtonVolume_Plus_Hold:
+        case kRemoteButtonVolume_Minus_Hold:
+            /* simulate an event as long as the user holds the button */
+            b_remote_button_hold = pressedDown;
+            if (pressedDown) {
+                NSNumber* buttonIdentifierNumber = [NSNumber numberWithInt:buttonIdentifier];
+                [self performSelector:@selector(executeHoldActionForRemoteButton:)
+                           withObject:buttonIdentifierNumber];
+            }
+            break;
+        case kRemoteButtonMenu:
+            [[VLCCoreInteraction sharedInstance] showPosition];
+            break;
+        case kRemoteButtonPlay_Sleep:
+        {
+            NSAppleScript * script = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to sleep"];
+            [script executeAndReturnError:nil];
+            break;
+        }
+        default:
+            /* Add here whatever you want other buttons to do */
+            break;
+    }
+}
+
+ at end
diff --git a/modules/gui/macosx/VLCCoreInteraction.h b/modules/gui/macosx/VLCCoreInteraction.h
index b51c48ebd8..0521477f35 100644
--- a/modules/gui/macosx/VLCCoreInteraction.h
+++ b/modules/gui/macosx/VLCCoreInteraction.h
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * CoreInteraction.h: MacOS X interface module
  *****************************************************************************
- * Copyright (C) 2011-2018 Felix Paul Kühne
+ * Copyright (C) 2011-2019 Felix Paul Kühne
  *
  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
  *
@@ -45,8 +45,6 @@
 - (void)toggleRecord;
 - (void)next;
 - (void)previous;
-- (void)forward;        //LEGACY SUPPORT
-- (void)backward;       //LEGACY SUPPORT
 - (void)forwardExtraShort;
 - (void)backwardExtraShort;
 - (void)forwardShort;
@@ -69,8 +67,6 @@
 - (void)volumeDown;
 - (void)toggleMute;
 - (void)showPosition;
-- (void)startListeningWithAppleRemote;
-- (void)stopListeningWithAppleRemote;
 
 - (void)menuFocusActivate;
 - (void)moveMenuFocusLeft;
@@ -84,11 +80,6 @@
 
 - (void)toggleFullscreen;
 
-- (BOOL)fixIntfSettings;
-
-- (void)setVideoFilter: (const char *)psz_name on:(BOOL)b_on;
-- (void)setVideoFilterProperty: (const char *)psz_property forFilter: (const char *)psz_filter withValue: (vlc_value_t)value;
-
 - (BOOL)keyEvent:(NSEvent *)o_event;
 - (void)updateCurrentlyUsedHotkeys;
 - (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event force:(BOOL)b_force;
diff --git a/modules/gui/macosx/VLCCoreInteraction.m b/modules/gui/macosx/VLCCoreInteraction.m
index a32e8b4d60..037e1e184c 100644
--- a/modules/gui/macosx/VLCCoreInteraction.m
+++ b/modules/gui/macosx/VLCCoreInteraction.m
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * CoreInteraction.m: MacOS X interface module
  *****************************************************************************
- * Copyright (C) 2011-2018 Felix Paul Kühne
+ * Copyright (C) 2011-2019 Felix Paul Kühne
  *
  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
  *
@@ -27,7 +27,6 @@
 #import <math.h>
 #import <vlc_playlist_legacy.h>
 #import <vlc_input.h>
-#import <vlc_actions.h>
 #import <vlc_aout.h>
 #import <vlc_vout.h>
 #import <vlc_vout_osd.h>
@@ -35,13 +34,10 @@
 #import <vlc_strings.h>
 #import <vlc_url.h>
 #import <vlc_modules.h>
-#import <vlc_charset.h>
-#include <vlc_plugin.h>
-#import "SPMediaKeyTap.h"
-#import "AppleRemote.h"
+#import <vlc_plugin.h>
+#import <vlc_actions.h>
 #import "VLCInputManager.h"
-
-#import "NSSound+VLCAdditions.h"
+#import "VLCClickerManager.h"
 
 static int BossCallback(vlc_object_t *p_this, const char *psz_var,
                         vlc_value_t oldval, vlc_value_t new_val, void *param)
@@ -63,16 +59,9 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
 
     float f_maxVolume;
 
-    /* media key support */
-    BOOL b_mediaKeySupport;
-    BOOL b_mediakeyJustJumped;
-    SPMediaKeyTap *_mediaKeyController;
-    BOOL b_mediaKeyTrapEnabled;
-
-    AppleRemote *_remote;
-    BOOL b_remote_button_hold; /* true as long as the user holds the left,right,plus or minus on the remote control */
-
     NSArray *_usedHotkeys;
+
+    VLCClickerManager *_clickerManager;
 }
 @end
 
@@ -98,45 +87,34 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     if (self) {
         intf_thread_t *p_intf = getIntf();
 
-        /* init media key support */
-        b_mediaKeySupport = var_InheritBool(p_intf, "macosx-mediakeys");
-        if (b_mediaKeySupport) {
-            _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
-        }
-        [[NSNotificationCenter defaultCenter] addObserver:self
-                                                 selector:@selector(coreChangedMediaKeySupportSetting:)
-                                                     name:VLCMediaKeySupportSettingChangedNotification
-                                                   object:nil];
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        [notificationCenter addObserver:self
+                          selector:@selector(applicationWillTerminate:)
+                              name:NSApplicationWillTerminateNotification
+                            object:nil];
 
-        /* init Apple Remote support */
-        _remote = [[AppleRemote alloc] init];
-        [_remote setClickCountEnabledButtons: kRemoteButtonPlay];
-        [_remote setDelegate: self];
+        _clickerManager = [[VLCClickerManager alloc] init];
 
         var_AddCallback(pl_Get(p_intf), "intf-boss", BossCallback, (__bridge void *)self);
     }
     return self;
 }
 
-- (void)dealloc
+- (void)applicationWillTerminate:(NSNotification *)notification
 {
-    #warning BUG! This class is a singleton, so dealloc is never called!
-    // Dealloc is never called, which not only means the below code is never
-    // run, but it means that the SPMediaKeyTap object and the AppleRemote object
-    // is not deallocated properly either.
-
+    // Dealloc is never called because this is a singleton, so we should cleanup manually before termination
     intf_thread_t *p_intf = getIntf();
     var_DelCallback(pl_Get(p_intf), "intf-boss", BossCallback, (__bridge void *)self);
     [[NSNotificationCenter defaultCenter] removeObserver: self];
+    _clickerManager = nil;
+    _usedHotkeys = nil;
 }
 
-
 #pragma mark - Playback Controls
 
 - (void)play
 {
     playlist_t *p_playlist = pl_Get(getIntf());
-
     playlist_Play(p_playlist);
 }
 
@@ -148,20 +126,19 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     if (p_input) {
         playlist_TogglePause(p_playlist);
         vlc_object_release(p_input);
-
     } else {
         PLRootType root = [[[[VLCMain sharedInstance] playlist] model] currentRootType];
-        if ([[[VLCMain sharedInstance] playlist] isSelectionEmpty] && (root == ROOT_TYPE_PLAYLIST))
-            [[[VLCMain sharedInstance] open] openFileGeneric];
+        VLCMain *mainInstance = [VLCMain sharedInstance];
+        if ([[mainInstance playlist] isSelectionEmpty] && (root == ROOT_TYPE_PLAYLIST))
+            [[mainInstance open] openFileGeneric];
         else
-            [[[VLCMain sharedInstance] playlist] playItem:nil];
+            [[mainInstance playlist] playItem:nil];
     }
 }
 
 - (void)pause
 {
     playlist_t *p_playlist = pl_Get(getIntf());
-
     playlist_Pause(p_playlist);
 }
 
@@ -223,9 +200,7 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     if (p_input) {
         f_rate = var_GetFloat(p_input, "rate");
         vlc_object_release(p_input);
-    }
-    else
-    {
+    } else {
         playlist_t * p_playlist = pl_Get(getIntf());
         f_rate = var_GetFloat(p_playlist, "rate");
     }
@@ -321,7 +296,7 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
         return nil;
     }
 
-    NSString *o_name = @"";
+    NSString *o_name;
     char *format = var_InheritString(getIntf(), "input-title-format");
     if (format) {
         char *formated = vlc_strfinput(p_input, NULL, format);
@@ -333,7 +308,7 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     NSURL * o_url = [NSURL URLWithString:toNSStr(psz_uri)];
     free(psz_uri);
 
-    if ([o_name isEqualToString:@""]) {
+    if (!o_name) {
         if ([o_url isFileURL])
             o_name = [[NSFileManager defaultManager] displayNameAtPath:[o_url path]];
         else
@@ -343,18 +318,6 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     return o_name;
 }
 
-- (void)forward
-{
-    //LEGACY SUPPORT
-    [self forwardShort];
-}
-
-- (void)backward
-{
-    //LEGACY SUPPORT
-    [self backwardShort];
-}
-
 - (void)jumpWithValue:(char *)p_value forward:(BOOL)b_value
 {
     input_thread_t *p_input = pl_CurrentInput(getIntf());
@@ -632,7 +595,6 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
         return;
 
     NSUInteger count = [paths count];
-
     for (int i = 0; i < count ; i++) {
         char *mrl = vlc_path2uri([[[paths objectAtIndex:i] path] UTF8String], NULL);
         if (!mrl)
@@ -641,7 +603,7 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
 
         int i_result = input_AddSlave(p_input, SLAVE_TYPE_SPU, mrl, true, true, true);
         if (i_result != VLC_SUCCESS)
-            msg_Warn(getIntf(), "unable to load subtitles from '%s'", mrl);
+            msg_Err(getIntf(), "unable to load subtitles from '%s'", mrl);
         free(mrl);
     }
     vlc_object_release(p_input);
@@ -702,280 +664,6 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     }
 }
 
-#pragma mark - uncommon stuff
-
-- (BOOL)fixIntfSettings
-{
-    NSMutableString * o_workString;
-    NSRange returnedRange;
-    NSRange fullRange;
-    BOOL b_needsRestart = NO;
-
-    #define fixpref(pref) \
-    o_workString = [[NSMutableString alloc] initWithFormat:@"%s", config_GetPsz(pref)]; \
-    if ([o_workString length] > 0) \
-    { \
-        returnedRange = [o_workString rangeOfString:@"macosx" options: NSCaseInsensitiveSearch]; \
-        if (returnedRange.location != NSNotFound) \
-        { \
-            if ([o_workString isEqualToString:@"macosx"]) \
-                [o_workString setString:@""]; \
-            fullRange = NSMakeRange(0, [o_workString length]); \
-            [o_workString replaceOccurrencesOfString:@":macosx" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
-            fullRange = NSMakeRange(0, [o_workString length]); \
-            [o_workString replaceOccurrencesOfString:@"macosx:" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
-            \
-            config_PutPsz(pref, [o_workString UTF8String]); \
-            b_needsRestart = YES; \
-        } \
-    }
-
-    fixpref("control");
-    fixpref("extraintf");
-    #undef fixpref
-
-    return b_needsRestart;
-}
-
-#pragma mark - video filter handling
-
-- (const char *)getFilterType:(const char *)psz_name
-{
-    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 filter")) {
-        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(getIntf(), "Unknown video filter type.");
-        return NULL;
-    }
-}
-
-- (void)setVideoFilter: (const char *)psz_name on:(BOOL)b_on
-{
-    intf_thread_t *p_intf = getIntf();
-    if (!p_intf)
-        return;
-    playlist_t *p_playlist = pl_Get(p_intf);
-    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 turn filter '%s' %s", psz_name, b_on ? "on" : "off");
-
-    psz_string = var_InheritString(p_playlist, 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;
-        }
-    }
-    var_SetString(p_playlist, psz_filter_type, psz_string);
-
-    /* Try to set non splitter filters on the fly */
-    if (strcmp(psz_filter_type, "video-splitter")) {
-        NSArray<NSValue *> *vouts = getVouts();
-        if (vouts)
-            for (NSValue * val in vouts) {
-                vout_thread_t *p_vout = [val pointerValue];
-                var_SetString(p_vout, psz_filter_type, psz_string);
-                vlc_object_release(p_vout);
-            }
-    }
-
-    free(psz_string);
-}
-
-- (void)setVideoFilterProperty: (char const *)psz_property
-                     forFilter: (char const *)psz_filter
-                     withValue: (vlc_value_t)value
-{
-    NSArray<NSValue *> *vouts = getVouts();
-    intf_thread_t *p_intf = getIntf();
-    if (!p_intf)
-        return;
-
-    playlist_t *p_playlist = pl_Get(p_intf);
-
-    int i_type = 0;
-    bool b_is_command = false;
-    char const *psz_filter_type = [self getFilterType: psz_filter];
-    if (!psz_filter_type) {
-        msg_Err(p_intf, "Unable to find filter module \"%s\".", psz_filter);
-        return;
-    }
-
-    if (vouts && [vouts count])
-    {
-        i_type = var_Type((vout_thread_t *)[[vouts firstObject] pointerValue], psz_property);
-        b_is_command = i_type & VLC_VAR_ISCOMMAND;
-    }
-    if (!i_type)
-        i_type = config_GetType(psz_property);
-
-    i_type &= VLC_VAR_CLASS;
-    if (i_type == VLC_VAR_BOOL)
-        var_SetBool(p_playlist, psz_property, value.b_bool);
-    else if (i_type == VLC_VAR_INTEGER)
-        var_SetInteger(p_playlist, psz_property, value.i_int);
-    else if (i_type == VLC_VAR_FLOAT)
-        var_SetFloat(p_playlist, psz_property, value.f_float);
-    else if (i_type == VLC_VAR_STRING)
-        var_SetString(p_playlist, psz_property, EnsureUTF8(value.psz_string));
-    else
-    {
-        msg_Err(p_intf,
-                "Module %s's %s variable is of an unsupported type ( %d )",
-                psz_filter, psz_property, i_type);
-        b_is_command = false;
-    }
-
-    if (b_is_command)
-        if (vouts)
-            for (NSValue *ptr in vouts)
-            {
-                vout_thread_t *p_vout = [ptr pointerValue];
-                var_SetChecked(p_vout, psz_property, i_type, value);
-#ifndef NDEBUG
-                int i_cur_type = var_Type(p_vout, psz_property);
-                assert((i_cur_type & VLC_VAR_CLASS) == i_type);
-                assert(i_cur_type & VLC_VAR_ISCOMMAND);
-#endif
-            }
-
-    if (vouts)
-        for (NSValue *ptr in vouts)
-            vlc_object_release((vout_thread_t *)[ptr pointerValue]);
-}
-
-#pragma mark -
-#pragma mark Media Key support
-
-- (void)resetMediaKeyJump
-{
-    b_mediakeyJustJumped = NO;
-}
-
-- (void)coreChangedMediaKeySupportSetting: (NSNotification *)o_notification
-{
-    intf_thread_t *p_intf = getIntf();
-    if (!p_intf)
-        return;
-
-    b_mediaKeySupport = var_InheritBool(p_intf, "macosx-mediakeys");
-    if (b_mediaKeySupport && !_mediaKeyController)
-        _mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
-
-    VLCMain *main = [VLCMain sharedInstance];
-    if (b_mediaKeySupport && ([[[main playlist] model] hasChildren] ||
-                              [[main inputManager] hasInput])) {
-        if (!b_mediaKeyTrapEnabled) {
-            msg_Dbg(p_intf, "Enabling media key support");
-            if ([_mediaKeyController startWatchingMediaKeys]) {
-                b_mediaKeyTrapEnabled = YES;
-            } else {
-                msg_Warn(p_intf, "Failed to enable media key support, likely "
-                    "app needs to be whitelisted in Security Settings.");
-            }
-        }
-    } else {
-        if (b_mediaKeyTrapEnabled) {
-            b_mediaKeyTrapEnabled = NO;
-            msg_Dbg(p_intf, "Disabling media key support");
-            [_mediaKeyController stopWatchingMediaKeys];
-        }
-    }
-}
-
--(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event
-{
-    if (b_mediaKeySupport) {
-        assert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys);
-
-        int keyCode = (([event data1] & 0xFFFF0000) >> 16);
-        int keyFlags = ([event data1] & 0x0000FFFF);
-        int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
-        int keyRepeat = (keyFlags & 0x1);
-
-        if (keyCode == NX_KEYTYPE_PLAY && keyState == 0)
-            [self playOrPause];
-
-        if ((keyCode == NX_KEYTYPE_FAST || keyCode == NX_KEYTYPE_NEXT) && !b_mediakeyJustJumped) {
-            if (keyState == 0 && keyRepeat == 0)
-                [self next];
-            else if (keyRepeat == 1) {
-                [self forwardShort];
-                b_mediakeyJustJumped = YES;
-                [self performSelector:@selector(resetMediaKeyJump)
-                           withObject: NULL
-                           afterDelay:0.25];
-            }
-        }
-
-        if ((keyCode == NX_KEYTYPE_REWIND || keyCode == NX_KEYTYPE_PREVIOUS) && !b_mediakeyJustJumped) {
-            if (keyState == 0 && keyRepeat == 0)
-                [self previous];
-            else if (keyRepeat == 1) {
-                [self backwardShort];
-                b_mediakeyJustJumped = YES;
-                [self performSelector:@selector(resetMediaKeyJump)
-                           withObject: NULL
-                           afterDelay:0.25];
-            }
-        }
-    }
-}
-
-#pragma mark -
-#pragma mark Apple Remote Control
-
-- (void)startListeningWithAppleRemote
-{
-    [_remote startListening: self];
-}
-
-- (void)stopListeningWithAppleRemote
-{
-    [_remote stopListening:self];
-}
-
 #pragma mark - menu navigation
 - (void)menuFocusActivate
 {
@@ -1027,115 +715,6 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
     vlc_object_release(p_input_thread);
 }
 
-/* Helper method for the remote control interface in order to trigger forward/backward and volume
- increase/decrease as long as the user holds the left/right, plus/minus button */
-- (void) executeHoldActionForRemoteButton: (NSNumber*) buttonIdentifierNumber
-{
-    intf_thread_t *p_intf = getIntf();
-    if (!p_intf)
-        return;
-
-    if (b_remote_button_hold) {
-        switch([buttonIdentifierNumber intValue]) {
-            case kRemoteButtonRight_Hold:
-                [self forward];
-                break;
-            case kRemoteButtonLeft_Hold:
-                [self backward];
-                break;
-            case kRemoteButtonVolume_Plus_Hold:
-                if (p_intf)
-                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_UP);
-                break;
-            case kRemoteButtonVolume_Minus_Hold:
-                if (p_intf)
-                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_DOWN);
-                break;
-        }
-        if (b_remote_button_hold) {
-            /* trigger event */
-            [self performSelector:@selector(executeHoldActionForRemoteButton:)
-                       withObject:buttonIdentifierNumber
-                       afterDelay:0.25];
-        }
-    }
-}
-
-/* Apple Remote callback */
-- (void) appleRemoteButton: (AppleRemoteEventIdentifier)buttonIdentifier
-               pressedDown: (BOOL) pressedDown
-                clickCount: (unsigned int) count
-{
-    intf_thread_t *p_intf = getIntf();
-    if (!p_intf)
-        return;
-
-    switch(buttonIdentifier) {
-        case k2009RemoteButtonFullscreen:
-            [self toggleFullscreen];
-            break;
-        case k2009RemoteButtonPlay:
-            [self playOrPause];
-            break;
-        case kRemoteButtonPlay:
-            if (count >= 2)
-                [self toggleFullscreen];
-            else
-                [self playOrPause];
-            break;
-        case kRemoteButtonVolume_Plus:
-            if (config_GetInt("macosx-appleremote-sysvol"))
-                [NSSound increaseSystemVolume];
-            else
-                if (p_intf)
-                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_UP);
-            break;
-        case kRemoteButtonVolume_Minus:
-            if (config_GetInt("macosx-appleremote-sysvol"))
-                [NSSound decreaseSystemVolume];
-            else
-                if (p_intf)
-                    var_SetInteger(p_intf->obj.libvlc, "key-action", ACTIONID_VOL_DOWN);
-            break;
-        case kRemoteButtonRight:
-            if (config_GetInt("macosx-appleremote-prevnext"))
-                [self forward];
-            else
-                [self next];
-            break;
-        case kRemoteButtonLeft:
-            if (config_GetInt("macosx-appleremote-prevnext"))
-                [self backward];
-            else
-                [self previous];
-            break;
-        case kRemoteButtonRight_Hold:
-        case kRemoteButtonLeft_Hold:
-        case kRemoteButtonVolume_Plus_Hold:
-        case kRemoteButtonVolume_Minus_Hold:
-            /* simulate an event as long as the user holds the button */
-            b_remote_button_hold = pressedDown;
-            if (pressedDown) {
-                NSNumber* buttonIdentifierNumber = [NSNumber numberWithInt:buttonIdentifier];
-                [self performSelector:@selector(executeHoldActionForRemoteButton:)
-                           withObject:buttonIdentifierNumber];
-            }
-            break;
-        case kRemoteButtonMenu:
-            [self showPosition];
-            break;
-        case kRemoteButtonPlay_Sleep:
-        {
-            NSAppleScript * script = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to sleep"];
-            [script executeAndReturnError:nil];
-            break;
-        }
-        default:
-            /* Add here whatever you want other buttons to do */
-            break;
-    }
-}
-
 #pragma mark -
 #pragma mark Key Shortcuts
 
@@ -1226,7 +805,8 @@ static int BossCallback(vlc_object_t *p_this, const char *psz_var,
         val.i_int |= CocoaKeyToVLC(key);
 
         BOOL b_found_key = NO;
-        for (NSUInteger i = 0; i < [_usedHotkeys count]; i++) {
+        NSUInteger numberOfUsedHotkeys = [_usedHotkeys count];
+        for (NSUInteger i = 0; i < numberOfUsedHotkeys; i++) {
             NSString *str = [_usedHotkeys objectAtIndex:i];
             unsigned int i_keyModifiers = [[VLCStringUtility sharedInstance] VLCModifiersToCocoa: str];
 
diff --git a/modules/gui/macosx/VLCMain+OldPrefs.m b/modules/gui/macosx/VLCMain+OldPrefs.m
index 41d811b5a9..c382d10ff9 100644
--- a/modules/gui/macosx/VLCMain+OldPrefs.m
+++ b/modules/gui/macosx/VLCMain+OldPrefs.m
@@ -25,6 +25,7 @@
 #import "VLCMain+OldPrefs.h"
 #import "VLCCoreInteraction.h"
 #import "VLCSimplePrefsController.h"
+#import "VLCStringUtility.h"
 
 #include <unistd.h> /* execl() */
 
@@ -73,7 +74,7 @@ static const int kCurrentPreferencesVersion = 4;
         [defaults setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
         [defaults synchronize];
 
-        if (![[VLCCoreInteraction sharedInstance] fixIntfSettings])
+        if (!fixIntfSettings())
             return;
         else
             config_SaveConfigFile(getIntf()); // we need to do manually, since we won't quit libvlc cleanly
diff --git a/modules/gui/macosx/VLCMain.h b/modules/gui/macosx/VLCMain.h
index efc12e71be..e3395aa103 100644
--- a/modules/gui/macosx/VLCMain.h
+++ b/modules/gui/macosx/VLCMain.h
@@ -52,6 +52,7 @@ intf_thread_t *getIntf(void);
 static NSString * VLCInputChangedNotification = @"VLCInputChangedNotification";
 static NSString * VLCConfigurationChangedNotification = @"VLCConfigurationChangedNotification";
 static NSString * VLCMediaKeySupportSettingChangedNotification = @"VLCMediaKeySupportSettingChangedNotification";
+static NSString * VLCAppleRemoteSettingChangedNotification = @"VLCAppleRemoteSettingChangedNotification";
 
 /*****************************************************************************
  * VLCMain interface
diff --git a/modules/gui/macosx/VLCMain.m b/modules/gui/macosx/VLCMain.m
index 09da04c009..631239d25c 100644
--- a/modules/gui/macosx/VLCMain.m
+++ b/modules/gui/macosx/VLCMain.m
@@ -363,7 +363,6 @@ static VLCMain *sharedInstance = nil;
 - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)update
 {
     [NSApp activateIgnoringOtherApps:YES];
-    [_coreinteraction stopListeningWithAppleRemote];
     [_coreinteraction stop];
 }
 
@@ -380,22 +379,6 @@ static VLCMain *sharedInstance = nil;
 #pragma mark -
 #pragma mark Other notification
 
-/* Listen to the remote in exclusive mode, only when VLC is the active
-   application */
-- (void)applicationDidBecomeActive:(NSNotification *)aNotification
-{
-    if (!p_intf)
-        return;
-    if (var_InheritBool(p_intf, "macosx-appleremote") == YES)
-        [_coreinteraction startListeningWithAppleRemote];
-}
-- (void)applicationDidResignActive:(NSNotification *)aNotification
-{
-    if (!p_intf)
-        return;
-    [_coreinteraction stopListeningWithAppleRemote];
-}
-
 /* Triggered when the computer goes to sleep */
 - (void)computerWillSleep: (NSNotification *)notification
 {
diff --git a/modules/gui/macosx/VLCMainMenu.m b/modules/gui/macosx/VLCMainMenu.m
index fc062f7458..de811e52eb 100644
--- a/modules/gui/macosx/VLCMainMenu.m
+++ b/modules/gui/macosx/VLCMainMenu.m
@@ -50,6 +50,7 @@
 #import "VLCTimeSelectionPanelController.h"
 #import "NSScreen+VLCAdditions.h"
 #import "VLCRendererMenuController.h"
+#import "VLCVideoFilterHelper.h"
 
 #ifdef HAVE_SPARKLE
 #import <Sparkle/Sparkle.h>
@@ -761,12 +762,12 @@
 
 - (IBAction)forward:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] forward];
+    [[VLCCoreInteraction sharedInstance] forwardShort];
 }
 
 - (IBAction)backward:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] backward];
+    [[VLCCoreInteraction sharedInstance] backwardShort];
 }
 
 - (IBAction)volumeUp:(id)sender
@@ -984,12 +985,12 @@
 
 - (void)_disablePostProcessing
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:false];
+    [VLCVideoFilterHelper setVideoFilter:"postproc" on:false];
 }
 
 - (void)_enablePostProcessing
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter:"postproc" on:true];
+    [VLCVideoFilterHelper setVideoFilter:"postproc" on:true];
 }
 
 - (void)togglePostProcessing:(id)sender
@@ -1005,7 +1006,7 @@
         [self _enablePostProcessing];
         [sender setState:NSOnState];
 
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty:"postproc-q" forFilter:"postproc" withValue:(vlc_value_t){ .i_int = [sender tag] }];
+        [VLCVideoFilterHelper setVideoFilterProperty:"postproc-q" forFilter:"postproc" withValue:(vlc_value_t){ .i_int = [sender tag] }];
     }
 }
 
diff --git a/modules/gui/macosx/VLCSimplePrefsController.m b/modules/gui/macosx/VLCSimplePrefsController.m
index 6387e3439a..96b1d62833 100644
--- a/modules/gui/macosx/VLCSimplePrefsController.m
+++ b/modules/gui/macosx/VLCSimplePrefsController.m
@@ -35,7 +35,6 @@
 #import "misc.h"
 #import "VLCMain.h"
 #import "VLCMain+OldPrefs.h"
-#import "AppleRemote.h"
 #import "VLCCoreInteraction.h"
 #import "NSScreen+VLCAdditions.h"
 
@@ -911,12 +910,6 @@ static inline void save_string_list(intf_thread_t * p_intf, id object, const cha
 
         SaveIntList(_intf_pauseitunesPopup, "macosx-control-itunes");
         SaveIntList(_intf_continueplaybackPopup, "macosx-continue-playback");
-
-        /* activate stuff without restart */
-        if ([_intf_appleremoteCheckbox state] == YES)
-            [[VLCCoreInteraction sharedInstance] startListeningWithAppleRemote];
-        else
-            [[VLCCoreInteraction sharedInstance] stopListeningWithAppleRemote];
         _intfSettingChanged = NO;
     }
 
@@ -1036,13 +1029,15 @@ static inline void save_string_list(intf_thread_t * p_intf, id object, const cha
         _hotkeyChanged = NO;
     }
 
-    [[VLCCoreInteraction sharedInstance] fixIntfSettings];
+    fixIntfSettings();
 
     /* okay, let's save our changes to vlcrc */
     config_SaveConfigFile(p_intf);
 
-    [[NSNotificationCenter defaultCenter] postNotificationName:VLCMediaKeySupportSettingChangedNotification object:nil];
-    [[NSNotificationCenter defaultCenter] postNotificationName:VLCConfigurationChangedNotification object:nil];
+    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+    [notificationCenter postNotificationName:VLCMediaKeySupportSettingChangedNotification object:nil];
+    [notificationCenter postNotificationName:VLCConfigurationChangedNotification object:nil];
+    [notificationCenter postNotificationName:VLCAppleRemoteSettingChangedNotification object:nil];
 }
 
 - (void)showSettingsForCategory:(NSView *)categoryView
diff --git a/modules/gui/macosx/VLCStringUtility.h b/modules/gui/macosx/VLCStringUtility.h
index cc1802e8c2..9efd7cf26c 100644
--- a/modules/gui/macosx/VLCStringUtility.h
+++ b/modules/gui/macosx/VLCStringUtility.h
@@ -53,6 +53,11 @@ unsigned int CocoaKeyToVLC(unichar i_key);
  */
 NSImage *imageFromRes(NSString *name);
 
+/**
+ * Fix certain settings strings before saving
+ */
+bool fixIntfSettings(void);
+
 @interface VLCStringUtility : NSObject
 
 + (VLCStringUtility *)sharedInstance;
diff --git a/modules/gui/macosx/VLCStringUtility.m b/modules/gui/macosx/VLCStringUtility.m
index dae6cc0a4e..b0169266ff 100644
--- a/modules/gui/macosx/VLCStringUtility.m
+++ b/modules/gui/macosx/VLCStringUtility.m
@@ -360,3 +360,36 @@ NSImage *imageFromRes(NSString *name)
 {
     return [NSImage imageNamed:name];
 }
+
+bool fixIntfSettings(void)
+{
+    NSMutableString * o_workString;
+    NSRange returnedRange;
+    NSRange fullRange;
+    BOOL b_needsRestart = NO;
+
+    #define fixpref(pref) \
+    o_workString = [[NSMutableString alloc] initWithFormat:@"%s", config_GetPsz(pref)]; \
+    if ([o_workString length] > 0) \
+    { \
+        returnedRange = [o_workString rangeOfString:@"macosx" options: NSCaseInsensitiveSearch]; \
+        if (returnedRange.location != NSNotFound) \
+            { \
+            if ([o_workString isEqualToString:@"macosx"]) \
+                [o_workString setString:@""]; \
+            fullRange = NSMakeRange(0, [o_workString length]); \
+            [o_workString replaceOccurrencesOfString:@":macosx" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
+            fullRange = NSMakeRange(0, [o_workString length]); \
+            [o_workString replaceOccurrencesOfString:@"macosx:" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
+            \
+            config_PutPsz(pref, [o_workString UTF8String]); \
+            b_needsRestart = YES; \
+        } \
+    }
+
+    fixpref("control");
+    fixpref("extraintf");
+#undef fixpref
+
+    return b_needsRestart;
+}
diff --git a/modules/gui/macosx/VLCTrackSynchronizationWindowController.m b/modules/gui/macosx/VLCTrackSynchronizationWindowController.m
index ac7f522e7e..1883ac9627 100644
--- a/modules/gui/macosx/VLCTrackSynchronizationWindowController.m
+++ b/modules/gui/macosx/VLCTrackSynchronizationWindowController.m
@@ -25,7 +25,7 @@
 #import "VLCMain.h"
 #import <vlc_common.h>
 #import "VLCTrackSynchronizationWindowController.h"
-#import "VLCCoreInteraction.h"
+#import "VLCVideoFilterHelper.h"
 
 #define SUBSDELAY_CFG_MODE                     "subsdelay-mode"
 #define SUBSDELAY_CFG_FACTOR                   "subsdelay-factor"
@@ -205,7 +205,7 @@
                 var_SetFloat(p_vout, SUBSDELAY_CFG_FACTOR, f_factor);
                 vlc_object_release(p_vout);
             }
-        [[VLCCoreInteraction sharedInstance] setVideoFilter: "subsdelay" on: f_factor > 0];
+        [VLCVideoFilterHelper setVideoFilter: "subsdelay" on: f_factor > 0];
 
         vlc_object_release(p_input);
     }
diff --git a/modules/gui/macosx/VLCVideoEffectsWindowController.m b/modules/gui/macosx/VLCVideoEffectsWindowController.m
index 7953c021f4..e93898aec8 100644
--- a/modules/gui/macosx/VLCVideoEffectsWindowController.m
+++ b/modules/gui/macosx/VLCVideoEffectsWindowController.m
@@ -25,7 +25,7 @@
 #import "VLCVideoEffectsWindowController.h"
 #import "VLCPopupPanelController.h"
 #import "VLCTextfieldPanelController.h"
-#import "VLCCoreInteraction.h"
+#import "VLCVideoFilterHelper.h"
 #import "VLCHexNumberFormatter.h"
 #import "NSString+Helpers.h"
 
@@ -88,7 +88,6 @@
 {
     intf_thread_t *p_intf = getIntf();
     playlist_t *p_playlist = pl_Get(p_intf);
-    VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
     NSInteger profileIndex = [self currentProfileIndex];
 
@@ -139,37 +138,37 @@
 
     /* try to set filter values on-the-fly and store them appropriately */
     // index 3 is deprecated
-    [vci_si setVideoFilterProperty: "contrast" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:4])];
-    [vci_si setVideoFilterProperty: "brightness" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:5])];
-    [vci_si setVideoFilterProperty: "saturation" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:6])];
-    [vci_si setVideoFilterProperty: "gamma" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:7])];
-    [vci_si setVideoFilterProperty: "sharpen-sigma" forFilter: "sharpen" withValue: getWidgetFloatValue([items objectAtIndex:8])];
-    [vci_si setVideoFilterProperty: "gradfun-radius" forFilter: "gradfun" withValue: getWidgetIntValue([items objectAtIndex:9])];
-    [vci_si setVideoFilterProperty: "grain-variance" forFilter: "grain" withValue: getWidgetFloatValue([items objectAtIndex:10])];
-    [vci_si setVideoFilterProperty: "transform-type" forFilter: "transform" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:11]) UTF8String] }];
-    [vci_si setVideoFilterProperty: "puzzle-rows" forFilter: "puzzle" withValue: getWidgetIntValue([items objectAtIndex:12])];
-    [vci_si setVideoFilterProperty: "puzzle-cols" forFilter: "puzzle" withValue: getWidgetIntValue([items objectAtIndex:13])];
-    [vci_si setVideoFilterProperty: "colorthres-color" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:14])];
-    [vci_si setVideoFilterProperty: "colorthres-saturationthres" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:15])];
-    [vci_si setVideoFilterProperty: "colorthres-similaritythres" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:16])];
-    [vci_si setVideoFilterProperty: "sepia-intensity" forFilter: "sepia" withValue: getWidgetIntValue([items objectAtIndex:17])];
-    [vci_si setVideoFilterProperty: "gradient-mode" forFilter: "gradient" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:18]) UTF8String] }];
-    [vci_si setVideoFilterProperty: "gradient-cartoon" forFilter: "gradient" withValue: (vlc_value_t){ .b_bool = [[items objectAtIndex:19] intValue] }];
-    [vci_si setVideoFilterProperty: "gradient-type" forFilter: "gradient" withValue: getWidgetIntValue([items objectAtIndex:20])];
-    [vci_si setVideoFilterProperty: "extract-component" forFilter: "extract" withValue: getWidgetIntValue([items objectAtIndex:21])];
-    [vci_si setVideoFilterProperty: "posterize-level" forFilter: "posterize" withValue: getWidgetIntValue([items objectAtIndex:22])];
-    [vci_si setVideoFilterProperty: "blur-factor" forFilter: "motionblur" withValue: getWidgetIntValue([items objectAtIndex:23])];
-    [vci_si setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:24]) UTF8String] }];
-    [vci_si setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: getWidgetIntValue([items objectAtIndex:25])];
-    [vci_si setVideoFilterProperty: "logo-file" forFilter: "logo" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:26]) UTF8String] }];
-    [vci_si setVideoFilterProperty: "logo-position" forFilter: "logo" withValue: getWidgetIntValue([items objectAtIndex:27])];
-    [vci_si setVideoFilterProperty: "logo-opacity" forFilter: "logo" withValue: getWidgetIntValue([items objectAtIndex:28])];
-    [vci_si setVideoFilterProperty: "clone-count" forFilter: "clone" withValue: getWidgetIntValue([items objectAtIndex:29])];
-    [vci_si setVideoFilterProperty: "wall-rows" forFilter: "wall" withValue: getWidgetIntValue([items objectAtIndex:30])];
-    [vci_si setVideoFilterProperty: "wall-cols" forFilter: "wall" withValue: getWidgetIntValue([items objectAtIndex:31])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "contrast" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:4])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "brightness" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:5])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "saturation" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:6])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gamma" forFilter: "adjust" withValue: getWidgetFloatValue([items objectAtIndex:7])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "sharpen-sigma" forFilter: "sharpen" withValue: getWidgetFloatValue([items objectAtIndex:8])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gradfun-radius" forFilter: "gradfun" withValue: getWidgetIntValue([items objectAtIndex:9])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "grain-variance" forFilter: "grain" withValue: getWidgetFloatValue([items objectAtIndex:10])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "transform-type" forFilter: "transform" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:11]) UTF8String] }];
+    [VLCVideoFilterHelper setVideoFilterProperty: "puzzle-rows" forFilter: "puzzle" withValue: getWidgetIntValue([items objectAtIndex:12])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "puzzle-cols" forFilter: "puzzle" withValue: getWidgetIntValue([items objectAtIndex:13])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-color" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:14])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-saturationthres" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:15])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-similaritythres" forFilter: "colorthres" withValue: getWidgetIntValue([items objectAtIndex:16])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "sepia-intensity" forFilter: "sepia" withValue: getWidgetIntValue([items objectAtIndex:17])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gradient-mode" forFilter: "gradient" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:18]) UTF8String] }];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gradient-cartoon" forFilter: "gradient" withValue: (vlc_value_t){ .b_bool = [[items objectAtIndex:19] intValue] }];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gradient-type" forFilter: "gradient" withValue: getWidgetIntValue([items objectAtIndex:20])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "extract-component" forFilter: "extract" withValue: getWidgetIntValue([items objectAtIndex:21])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "posterize-level" forFilter: "posterize" withValue: getWidgetIntValue([items objectAtIndex:22])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "blur-factor" forFilter: "motionblur" withValue: getWidgetIntValue([items objectAtIndex:23])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:24]) UTF8String] }];
+    [VLCVideoFilterHelper setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: getWidgetIntValue([items objectAtIndex:25])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "logo-file" forFilter: "logo" withValue: (vlc_value_t){ .psz_string = (char *)[B64DecNSStr([items objectAtIndex:26]) UTF8String] }];
+    [VLCVideoFilterHelper setVideoFilterProperty: "logo-position" forFilter: "logo" withValue: getWidgetIntValue([items objectAtIndex:27])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "logo-opacity" forFilter: "logo" withValue: getWidgetIntValue([items objectAtIndex:28])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "clone-count" forFilter: "clone" withValue: getWidgetIntValue([items objectAtIndex:29])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "wall-rows" forFilter: "wall" withValue: getWidgetIntValue([items objectAtIndex:30])];
+    [VLCVideoFilterHelper setVideoFilterProperty: "wall-cols" forFilter: "wall" withValue: getWidgetIntValue([items objectAtIndex:31])];
 
     if ([items count] >= 33) { // version >=2 of profile string
-        [vci_si setVideoFilterProperty: "brightness-threshold" forFilter: "adjust" withValue: (vlc_value_t){ .b_bool = [[items objectAtIndex:32] intValue] }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "brightness-threshold" forFilter: "adjust" withValue: (vlc_value_t){ .b_bool = [[items objectAtIndex:32] intValue] }];
     }
 
     vlc_value_t hueValue;
@@ -180,7 +179,7 @@
         // convert to new scale ([0,360] --> [-180,180])
         hueValue.f_float -= 180;
     }
-    [vci_si setVideoFilterProperty: "hue" forFilter: "adjust" withValue: hueValue];
+    [VLCVideoFilterHelper setVideoFilterProperty: "hue" forFilter: "adjust" withValue: hueValue];
 }
 
 - (void)windowDidLoad
@@ -897,16 +896,15 @@
         [_adjustHueSlider setToolTip: [NSString stringWithFormat:@"%.0f", 0.0]];
         [_adjustSaturationSlider setToolTip: [NSString stringWithFormat:@"%0.3f", 1.0]];
 
-        VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
-        [vci_si setVideoFilterProperty: "brightness" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
-        [vci_si setVideoFilterProperty: "contrast" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
-        [vci_si setVideoFilterProperty: "gamma" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
-        [vci_si setVideoFilterProperty: "hue" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = .0f }];
-        [vci_si setVideoFilterProperty: "saturation" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "brightness" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "contrast" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "gamma" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "hue" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = .0f }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "saturation" forFilter: "adjust" withValue: (vlc_value_t){ .f_float = 1.f }];
     } else {
         BOOL b_state = [_adjustCheckbox state];
 
-        [[VLCCoreInteraction sharedInstance] setVideoFilter: "adjust" on: b_state];
+        [VLCVideoFilterHelper setVideoFilter: "adjust" on: b_state];
         [_adjustBrightnessSlider setEnabled: b_state];
         [_adjustBrightnessCheckbox setEnabled: b_state];
         [_adjustBrightnessLabel setEnabled: b_state];
@@ -937,7 +935,7 @@
         psz_property = "saturation";
     assert(psz_property);
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: psz_property forFilter: "adjust" withValue: getWidgetFloatValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: psz_property forFilter: "adjust" withValue: getWidgetFloatValue(sender)];
 
     if (sender == _adjustHueSlider)
         [_adjustHueSlider setToolTip: [NSString stringWithFormat:@"%.0f", [_adjustHueSlider floatValue]]];
@@ -947,7 +945,7 @@
 
 - (IBAction)enableAdjustBrightnessThreshold:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "brightness-threshold"
+    [VLCVideoFilterHelper setVideoFilterProperty: "brightness-threshold"
                                                       forFilter: "adjust"
                                                       withValue: getWidgetBoolValue(sender)];
 }
@@ -956,14 +954,14 @@
 {
     BOOL b_state = [_sharpenCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "sharpen" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "sharpen" on: b_state];
     [_sharpenSlider setEnabled: b_state];
     [_sharpenLabel setEnabled: b_state];
 }
 
 - (IBAction)sharpenSliderChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "sharpen-sigma" forFilter: "sharpen" withValue: getWidgetFloatValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "sharpen-sigma" forFilter: "sharpen" withValue: getWidgetFloatValue(sender)];
     [sender setToolTip: [NSString stringWithFormat:@"%0.3f", [sender floatValue]]];
 }
 
@@ -971,14 +969,14 @@
 {
     BOOL b_state = [_bandingCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "gradfun" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "gradfun" on: b_state];
     [_bandingSlider setEnabled: b_state];
     [_bandingLabel setEnabled: b_state];
 }
 
 - (IBAction)bandingSliderChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradfun-radius" forFilter: "gradfun" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "gradfun-radius" forFilter: "gradfun" withValue: getWidgetIntValue(sender)];
     [sender setToolTip: [NSString stringWithFormat:@"%i", [sender intValue]]];
 }
 
@@ -986,14 +984,14 @@
 {
     BOOL b_state = [_grainCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "grain" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "grain" on: b_state];
     [_grainSlider setEnabled: b_state];
     [_grainLabel setEnabled: b_state];
 }
 
 - (IBAction)grainSliderChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "grain-variance" forFilter: "grain" withValue: getWidgetFloatValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "grain-variance" forFilter: "grain" withValue: getWidgetFloatValue(sender)];
     [sender setToolTip: [NSString stringWithFormat:@"%0.3f", [sender floatValue]]];
 }
 
@@ -1032,26 +1030,26 @@
 #pragma mark geometry
 - (IBAction)enableTransform:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "transform" on: [_transformCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "transform" on: [_transformCheckbox state]];
     [_transformPopup setEnabled: [_transformCheckbox state]];
 }
 
 - (IBAction)transformModifierChanged:(id)sender
 {
     vlc_value_t value = { .psz_string = (char *)[[[_transformPopup selectedItem] representedObject] UTF8String] };
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "transform-type" forFilter: "transform" withValue: value];
+    [VLCVideoFilterHelper setVideoFilterProperty: "transform-type" forFilter: "transform" withValue: value];
 }
 
 - (IBAction)enableZoom:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "magnify" on: [_zoomCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "magnify" on: [_zoomCheckbox state]];
 }
 
 - (IBAction)enablePuzzle:(id)sender
 {
     BOOL b_state = [_puzzleCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "puzzle" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "puzzle" on: b_state];
     [_puzzleColumnsTextField setEnabled: b_state];
     [_puzzleColumnsStepper setEnabled: b_state];
     [_puzzleColumnsLabel setEnabled: b_state];
@@ -1063,9 +1061,9 @@
 - (IBAction)puzzleModifierChanged:(id)sender
 {
     if (sender == _puzzleColumnsTextField || sender == _puzzleColumnsStepper)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "puzzle-cols" forFilter: "puzzle" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "puzzle-cols" forFilter: "puzzle" withValue: getWidgetIntValue(sender)];
     else
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "puzzle-rows" forFilter: "puzzle" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "puzzle-rows" forFilter: "puzzle" withValue: getWidgetIntValue(sender)];
 }
 
 - (IBAction)enableClone:(id)sender
@@ -1077,7 +1075,7 @@
         [self enableWall:_wallCheckbox];
     }
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "clone" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "clone" on: b_state];
     [_cloneNumberLabel setEnabled: b_state];
     [_cloneNumberTextField setEnabled: b_state];
     [_cloneNumberStepper setEnabled: b_state];
@@ -1085,7 +1083,7 @@
 
 - (IBAction)cloneModifierChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "clone-count" forFilter: "clone" withValue: getWidgetIntValue(_cloneNumberTextField)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "clone-count" forFilter: "clone" withValue: getWidgetIntValue(_cloneNumberTextField)];
 }
 
 - (IBAction)enableWall:(id)sender
@@ -1097,7 +1095,7 @@
         [self enableClone:_cloneCheckbox];
     }
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "wall" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "wall" on: b_state];
     [_wallNumberOfColumnsTextField setEnabled: b_state];
     [_wallNumberOfColumnsStepper setEnabled: b_state];
     [_wallNumberOfColumnsLabel setEnabled: b_state];
@@ -1114,7 +1112,7 @@
         psz_property = "wall-cols";
     else
         psz_property = "wall-rows";
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: psz_property forFilter: "wall" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: psz_property forFilter: "wall" withValue: getWidgetIntValue(sender)];
 }
 
 #pragma mark -
@@ -1123,7 +1121,7 @@
 {
     BOOL b_state = [_thresholdCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "colorthres" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "colorthres" on: b_state];
     [_thresholdColorTextField setEnabled: b_state];
     [_thresholdColorLabel setEnabled: b_state];
     [_thresholdSaturationSlider setEnabled: b_state];
@@ -1135,12 +1133,12 @@
 - (IBAction)thresholdModifierChanged:(id)sender
 {
     if (sender == _thresholdColorTextField)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-color" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-color" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
     else if (sender == _thresholdSaturationSlider) {
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-saturationthres" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-saturationthres" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
         [_thresholdSaturationSlider setToolTip: [NSString stringWithFormat:@"%i", [_thresholdSaturationSlider intValue]]];
     } else {
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "colorthres-similaritythres" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "colorthres-similaritythres" forFilter: "colorthres" withValue: getWidgetIntValue(sender)];
         [_thresholdSimilaritySlider setToolTip: [NSString stringWithFormat:@"%i", [_thresholdSimilaritySlider intValue]]];
     }
 }
@@ -1149,7 +1147,7 @@
 {
     BOOL b_state = [_sepiaCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "sepia" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "sepia" on: b_state];
     [_sepiaTextField setEnabled: b_state];
     [_sepiaStepper setEnabled: b_state];
     [_sepiaLabel setEnabled: b_state];
@@ -1157,14 +1155,14 @@
 
 - (IBAction)sepiaModifierChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "sepia-intensity" forFilter: "sepia" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "sepia-intensity" forFilter: "sepia" withValue: getWidgetIntValue(sender)];
 }
 
 - (IBAction)enableGradient:(id)sender
 {
     BOOL b_state = [_gradientCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "gradient" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "gradient" on: b_state];
     [_gradientModePopup setEnabled: b_state];
     [_gradientModeLabel setEnabled: b_state];
     [_gradientColorCheckbox setEnabled: b_state];
@@ -1175,36 +1173,36 @@
 {
     if (sender == _gradientModePopup) {
         vlc_value_t value = { .psz_string = (char *)[[[sender selectedItem] representedObject] UTF8String] };
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-mode" forFilter: "gradient" withValue: value];
+        [VLCVideoFilterHelper setVideoFilterProperty: "gradient-mode" forFilter: "gradient" withValue: value];
     } else if (sender == _gradientColorCheckbox)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-type" forFilter: "gradient" withValue: getWidgetBoolValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "gradient-type" forFilter: "gradient" withValue: getWidgetBoolValue(sender)];
     else
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "gradient-cartoon" forFilter: "gradient" withValue: getWidgetBoolValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "gradient-cartoon" forFilter: "gradient" withValue: getWidgetBoolValue(sender)];
 }
 
 - (IBAction)enableExtract:(id)sender
 {
     BOOL b_state = [_extractCheckbox state];
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "extract" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "extract" on: b_state];
     [_extractTextField setEnabled: b_state];
     [_extractLabel setEnabled: b_state];
 }
 
 - (IBAction)extractModifierChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "extract-component" forFilter: "extract" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "extract-component" forFilter: "extract" withValue: getWidgetIntValue(sender)];
 }
 
 - (IBAction)enableInvert:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "invert" on: [_invertCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "invert" on: [_invertCheckbox state]];
 }
 
 - (IBAction)enablePosterize:(id)sender
 {
     BOOL b_state = [_posterizeCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "posterize" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "posterize" on: b_state];
     [_posterizeTextField setEnabled: b_state];
     [_posterizeStepper setEnabled: b_state];
     [_posterizeLabel setEnabled: b_state];
@@ -1212,42 +1210,42 @@
 
 - (IBAction)posterizeModifierChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "posterize-level" forFilter: "posterize" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "posterize-level" forFilter: "posterize" withValue: getWidgetIntValue(sender)];
 }
 
 - (IBAction)enableBlur:(id)sender
 {
     BOOL b_state = [_blurCheckbox state];
 
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "motionblur" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "motionblur" on: b_state];
     [_blurSlider setEnabled: b_state];
     [_blurLabel setEnabled: b_state];
 }
 
 - (IBAction)blurModifierChanged:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "blur-factor" forFilter: "motionblur" withValue: getWidgetIntValue(sender)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "blur-factor" forFilter: "motionblur" withValue: getWidgetIntValue(sender)];
     [sender setToolTip: [NSString stringWithFormat:@"%i", [sender intValue]]];
 }
 
 - (IBAction)enableMotionDetect:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "motiondetect" on: [_motiondetectCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "motiondetect" on: [_motiondetectCheckbox state]];
 }
 
 - (IBAction)enableWaterEffect:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "ripple" on: [_watereffectCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "ripple" on: [_watereffectCheckbox state]];
 }
 
 - (IBAction)enableWaves:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "wave" on: [_wavesCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "wave" on: [_wavesCheckbox state]];
 }
 
 - (IBAction)enablePsychedelic:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "psychedelic" on: [_psychedelicCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "psychedelic" on: [_psychedelicCheckbox state]];
 }
 
 #pragma mark -
@@ -1255,23 +1253,22 @@
 - (IBAction)enableAddText:(id)sender
 {
     BOOL b_state = [_addTextCheckbox state];
-    VLCCoreInteraction *vci_si = [VLCCoreInteraction sharedInstance];
 
     [_addTextPositionPopup setEnabled: b_state];
     [_addTextPositionLabel setEnabled: b_state];
     [_addTextTextLabel setEnabled: b_state];
     [_addTextTextTextField setEnabled: b_state];
-    [vci_si setVideoFilter: "marq" on: b_state];
-    [vci_si setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: getWidgetStringValue(_addTextTextTextField)];
-    [vci_si setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: (vlc_value_t){ .i_int = [[_addTextPositionPopup selectedItem] tag] }];
+    [VLCVideoFilterHelper setVideoFilter: "marq" on: b_state];
+    [VLCVideoFilterHelper setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: getWidgetStringValue(_addTextTextTextField)];
+    [VLCVideoFilterHelper setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: (vlc_value_t){ .i_int = [[_addTextPositionPopup selectedItem] tag] }];
 }
 
 - (IBAction)addTextModifierChanged:(id)sender
 {
     if (sender == _addTextTextTextField)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: getWidgetStringValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "marq-marquee" forFilter: "marq" withValue: getWidgetStringValue(sender)];
     else
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: (vlc_value_t){ .i_int = [[sender selectedItem] tag] }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "marq-position" forFilter: "marq" withValue: (vlc_value_t){ .i_int = [[sender selectedItem] tag] }];
 }
 
 - (IBAction)enableAddLogo:(id)sender
@@ -1284,24 +1281,24 @@
     [_addLogoLogoLabel setEnabled: b_state];
     [_addLogoTransparencySlider setEnabled: b_state];
     [_addLogoTransparencyLabel setEnabled: b_state];
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "logo" on: b_state];
+    [VLCVideoFilterHelper setVideoFilter: "logo" on: b_state];
 }
 
 - (IBAction)addLogoModifierChanged:(id)sender
 {
     if (sender == _addLogoLogoTextField)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-file" forFilter: "logo" withValue: getWidgetStringValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "logo-file" forFilter: "logo" withValue: getWidgetStringValue(sender)];
     else if (sender == _addLogoPositionPopup)
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-position" forFilter: "logo" withValue: (vlc_value_t){ .i_int = [[_addLogoPositionPopup selectedItem] tag] }];
+        [VLCVideoFilterHelper setVideoFilterProperty: "logo-position" forFilter: "logo" withValue: (vlc_value_t){ .i_int = [[_addLogoPositionPopup selectedItem] tag] }];
     else {
-        [[VLCCoreInteraction sharedInstance] setVideoFilterProperty: "logo-opacity" forFilter: "logo" withValue: getWidgetIntValue(sender)];
+        [VLCVideoFilterHelper setVideoFilterProperty: "logo-opacity" forFilter: "logo" withValue: getWidgetIntValue(sender)];
         [_addLogoTransparencySlider setToolTip: [NSString stringWithFormat:@"%i", [_addLogoTransparencySlider intValue]]];
     }
 }
 
 - (IBAction)enableAnaglyph:(id)sender
 {
-    [[VLCCoreInteraction sharedInstance] setVideoFilter: "anaglyph" on: [_anaglyphCheckbox state]];
+    [VLCVideoFilterHelper setVideoFilter: "anaglyph" on: [_anaglyphCheckbox state]];
 }
 
 @end
diff --git a/modules/gui/macosx/VLCVideoFilterHelper.h b/modules/gui/macosx/VLCVideoFilterHelper.h
new file mode 100644
index 0000000000..6e69938346
--- /dev/null
+++ b/modules/gui/macosx/VLCVideoFilterHelper.h
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ * VLCVideoFilterHelper.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2006-2019 VLC authors and VideoLAN
+ *
+ * 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 <Foundation/Foundation.h>
+#import <vlc_common.h>
+
+ at interface VLCVideoFilterHelper : NSObject
+
++ (void)setVideoFilter: (const char *)psz_name on:(BOOL)b_on;
++ (void)setVideoFilterProperty: (const char *)psz_property forFilter: (const char *)psz_filter withValue: (vlc_value_t)value;
+
+ at end
diff --git a/modules/gui/macosx/VLCVideoFilterHelper.m b/modules/gui/macosx/VLCVideoFilterHelper.m
new file mode 100644
index 0000000000..e0ecc41139
--- /dev/null
+++ b/modules/gui/macosx/VLCVideoFilterHelper.m
@@ -0,0 +1,177 @@
+/*****************************************************************************
+ * VLCVideoFilterHelper.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2006-2019 VLC authors and VideoLAN
+ *
+ * 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 "VLCVideoFilterHelper.h"
+#import <vlc_modules.h>
+#import <vlc_charset.h>
+#import "VLCMain.h"
+
+ at implementation VLCVideoFilterHelper
+
++ (const char *)getFilterType:(const char *)psz_name
+{
+    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 filter")) {
+        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(getIntf(), "Unknown video filter type.");
+        return NULL;
+    }
+}
+
++ (void)setVideoFilter: (const char *)psz_name on:(BOOL)b_on
+{
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf)
+        return;
+    playlist_t *p_playlist = pl_Get(p_intf);
+    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 turn filter '%s' %s", psz_name, b_on ? "on" : "off");
+
+    psz_string = var_InheritString(p_playlist, 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;
+        }
+    }
+    var_SetString(p_playlist, psz_filter_type, psz_string);
+
+    /* Try to set non splitter filters on the fly */
+    if (strcmp(psz_filter_type, "video-splitter")) {
+        NSArray<NSValue *> *vouts = getVouts();
+        if (vouts)
+            for (NSValue * val in vouts) {
+                vout_thread_t *p_vout = [val pointerValue];
+                var_SetString(p_vout, psz_filter_type, psz_string);
+                vlc_object_release(p_vout);
+            }
+    }
+
+    free(psz_string);
+}
+
++ (void)setVideoFilterProperty: (char const *)psz_property
+                     forFilter: (char const *)psz_filter
+                     withValue: (vlc_value_t)value
+{
+    NSArray<NSValue *> *vouts = getVouts();
+    intf_thread_t *p_intf = getIntf();
+    if (!p_intf)
+        return;
+
+    playlist_t *p_playlist = pl_Get(p_intf);
+
+    int i_type = 0;
+    bool b_is_command = false;
+    char const *psz_filter_type = [self getFilterType: psz_filter];
+    if (!psz_filter_type) {
+        msg_Err(p_intf, "Unable to find filter module \"%s\".", psz_filter);
+        return;
+    }
+
+    if (vouts && [vouts count])
+    {
+        i_type = var_Type((vout_thread_t *)[[vouts firstObject] pointerValue], psz_property);
+        b_is_command = i_type & VLC_VAR_ISCOMMAND;
+    }
+    if (!i_type)
+        i_type = config_GetType(psz_property);
+
+    i_type &= VLC_VAR_CLASS;
+    if (i_type == VLC_VAR_BOOL)
+        var_SetBool(p_playlist, psz_property, value.b_bool);
+    else if (i_type == VLC_VAR_INTEGER)
+        var_SetInteger(p_playlist, psz_property, value.i_int);
+    else if (i_type == VLC_VAR_FLOAT)
+        var_SetFloat(p_playlist, psz_property, value.f_float);
+    else if (i_type == VLC_VAR_STRING)
+        var_SetString(p_playlist, psz_property, EnsureUTF8(value.psz_string));
+    else
+    {
+        msg_Err(p_intf,
+                "Module %s's %s variable is of an unsupported type ( %d )",
+                psz_filter, psz_property, i_type);
+        b_is_command = false;
+    }
+
+    if (b_is_command)
+        if (vouts)
+            for (NSValue *ptr in vouts)
+            {
+                vout_thread_t *p_vout = [ptr pointerValue];
+                var_SetChecked(p_vout, psz_property, i_type, value);
+#ifndef NDEBUG
+                int i_cur_type = var_Type(p_vout, psz_property);
+                assert((i_cur_type & VLC_VAR_CLASS) == i_type);
+                assert(i_cur_type & VLC_VAR_ISCOMMAND);
+#endif
+            }
+
+    if (vouts)
+        for (NSValue *ptr in vouts)
+            vlc_object_release((vout_thread_t *)[ptr pointerValue]);
+}
+
+
+ at end
diff --git a/modules/gui/macosx/prefs.m b/modules/gui/macosx/prefs.m
index 047ca9093a..0893ad480b 100644
--- a/modules/gui/macosx/prefs.m
+++ b/modules/gui/macosx/prefs.m
@@ -214,7 +214,7 @@
 {
     /* TODO: call savePrefs on Root item */
     [_rootTreeItem applyChanges];
-    [[VLCCoreInteraction sharedInstance] fixIntfSettings];
+    fixIntfSettings();
     config_SaveConfigFile(getIntf());
     [self.window orderOut:self];
 }




More information about the vlc-commits mailing list