[vlc-devel] [PATCH v2] Dim MacBook keyboard backlight during video playback on OSX

Maxime Mouchet max at maxmouchet.com
Mon May 18 22:36:19 CEST 2015


This patch adds the option to turn off the keyboard backlight when
a video is playing in fullscreen, to the OSX user interface.
The option is off by default and it works better if the automatic
keyboard backlight adjustment is disabled in System Preferences.

Smooth brightness transitions are implemented, and the "before-playing"
level is saved to be restored on pause.
If the user manually (i.e. using hardware keys) put backlight on,
brightness level is not changed, in order to preserve his choice.
---
This edited version gets rid of the singleton and moves the code concerning
fullscreen transitions in VLCVoutWindowController.
I kept the code to manage play an pause transitions in VLCIntf (in the same
place as the code for iTunes and Spotify).
It should also close the dataPort correctly.

To sum up, the expected behavior is:
* Dim backlight when a video is playing and entering fullscreen (in VLCVoutWindowController).
* Dim backlight when starting video playback in fullscreen (in intf).
* Restore backlight when exiting fullscreen (in VLCVoutWindowController).
* Restore backlight on pause/stop, or when exiting (in intf).

Regards,

 modules/gui/macosx/KeyboardBacklight.h       |  68 ++++++++++++
 modules/gui/macosx/KeyboardBacklight.m       | 158 +++++++++++++++++++++++++++
 modules/gui/macosx/Modules.am                |   3 +
 modules/gui/macosx/VLCVoutWindowController.h |   2 +
 modules/gui/macosx/VLCVoutWindowController.m |  12 +-
 modules/gui/macosx/intf.h                    |   3 +
 modules/gui/macosx/intf.m                    |  19 ++++
 modules/gui/macosx/macosx.m                  |   4 +
 8 files changed, 268 insertions(+), 1 deletion(-)
 create mode 100644 modules/gui/macosx/KeyboardBacklight.h
 create mode 100644 modules/gui/macosx/KeyboardBacklight.m

diff --git a/modules/gui/macosx/KeyboardBacklight.h b/modules/gui/macosx/KeyboardBacklight.h
new file mode 100644
index 0000000..306ecf3
--- /dev/null
+++ b/modules/gui/macosx/KeyboardBacklight.h
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * KeyboardBacklight.h: MacBook keyboard backlight control for VLC
+ *****************************************************************************
+ * Copyright (C) 2015 VLC authors and VideoLAN
+ *
+ *
+ * Authors: Maxime Mouchet <max at maxmouchet.com>
+ *
+ * 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 <IOKit/IOKitLib.h>
+
+enum {
+    kGetSensorReadingID = 0, // getSensorReading(int *, int *)
+    kGetLEDBrightnessID = 1, // getLEDBrightness(int, int *)
+    kSetLEDBrightnessID = 2, // setLEDBrightness(int, int, int *)
+    kSetLEDFadeID = 3        // setLEDFade(int, int, int, int *)
+};
+
+ at interface KeyboardBacklight : NSObject
+
+/*!
+ *  Initialize an instance of KeyboardBacklight.
+ *
+ *  Note: this will return nil if the connection to
+ *  the controller could not be opened.
+ */
+- (id)init;
+
+/*!
+ *  Smoothly turn on backlight on MacBook keyboard.
+ *
+ *  Try to restore the previous brightness level. If the user has put
+ *  the backlight on manually (using hardware keys), nothing will be done.
+ */
+- (void)lightsUp;
+
+/*!
+ *  Smoothly turn off backlight on MacBook keyboard.
+ */
+- (void)lightsDown;
+
+/*!
+ *  Smoothly switch on or off backlight on MacBook keyboard.
+ *  This will return immediately.
+ */
+- (void)switchLightsAsync:(BOOL)on;
+
+/*!
+ *  Instantly switch on or off backlight on MacBook keyboard.
+ */
+- (void)switchLightsInstantly:(BOOL)on;
+
+ at end
diff --git a/modules/gui/macosx/KeyboardBacklight.m b/modules/gui/macosx/KeyboardBacklight.m
new file mode 100644
index 0000000..e747f9d
--- /dev/null
+++ b/modules/gui/macosx/KeyboardBacklight.m
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * KeyboardBacklight.m: MacBook keyboard backlight control for VLC
+ *****************************************************************************
+ * Copyright (C) 2015 VLC authors and VideoLAN
+ *
+ *
+ * Authors: Maxime Mouchet <max at maxmouchet.com>
+ *
+ * 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 "KeyboardBacklight.h"
+
+ at implementation KeyboardBacklight {
+    io_connect_t dataPort;
+}
+
+static float lastBrightnessLevel;
+
+- (id)init {
+    dataPort = [self getDataPort];
+    lastBrightnessLevel = [self getBrightness];
+    return self;
+}
+
+- (void)dealloc {
+    if (dataPort) { IOServiceClose(dataPort); }
+    [super dealloc];
+}
+
+- (io_connect_t)getDataPort {
+    if (dataPort) return dataPort;
+
+    io_service_t serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
+
+    if (!serviceObject) return 0;
+
+    kern_return_t kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &dataPort);
+    IOObjectRelease(serviceObject);
+
+    if (kr != KERN_SUCCESS) return 0;
+
+    return dataPort;
+}
+
+- (void)setBrightness:(float)brightness {
+    if (!dataPort) return;
+
+    UInt32 inputCount = 2;
+    UInt64 inputValues[2] = { 0, brightness * 0xfff };
+
+    UInt32 outputCount = 1;
+    UInt64 outputValues[1];
+
+    kern_return_t kr = IOConnectCallScalarMethod(dataPort,
+                                                 kSetLEDBrightnessID,
+                                                 inputValues,
+                                                 inputCount,
+                                                 outputValues,
+                                                 &outputCount);
+
+    if (kr != KERN_SUCCESS) return;
+}
+
+- (float)getBrightness {
+    if (!dataPort) return 0.0;
+
+    uint32_t inputCount = 1;
+    uint64_t inputValues[1] = { 0 };
+
+    uint32_t outputCount = 1;
+    uint64_t outputValues[1];
+
+    kern_return_t kr = IOConnectCallScalarMethod(dataPort,
+                                                 kGetLEDBrightnessID,
+                                                 inputValues,
+                                                 inputCount,
+                                                 outputValues,
+                                                 &outputCount);
+
+    float brightness = -1.0;
+    if (kr == KERN_SUCCESS) {
+        brightness = (float)outputValues[0] / 0xfff;
+    }
+
+    return brightness;
+}
+
+- (void)lightsUp {
+    if (!dataPort) return;
+
+    @synchronized(self) {
+        float start = [self getBrightness];
+        float target = lastBrightnessLevel;
+
+        // Don't do anything if the user has put
+        // backlight on again during playback.
+        if (start != 0) return;
+
+        for (float i = start; i <= target; i += 0.08) {
+            [self setBrightness:i];
+            [NSThread sleepForTimeInterval:0.05];
+        }
+
+        [self setBrightness:target];
+    }
+}
+
+- (void)lightsDown {
+    if (!dataPort) return;
+
+    @synchronized(self) {
+        float start = [self getBrightness];
+        float target = 0;
+
+        lastBrightnessLevel = start;
+
+        for (float i = start; i >= target; i -= 0.08) {
+            [self setBrightness:i];
+            [NSThread sleepForTimeInterval:0.05];
+        }
+
+        [self setBrightness:target];
+    }
+}
+
+- (void)switchLightsAsync:(BOOL)on {
+    if (on) {
+        [NSThread detachNewThreadSelector:@selector(lightsUp) toTarget:self withObject:nil];
+    } else {
+        [NSThread detachNewThreadSelector:@selector(lightsDown) toTarget:self withObject:nil];
+    }
+}
+
+- (void)switchLightsInstantly:(BOOL)on {
+    if (on) {
+        // Don't do anything if the user has put backlight on again during playback.
+        if ([self getBrightness] == 0) {
+            [self setBrightness:lastBrightnessLevel];
+        }
+    } else {
+        [self setBrightness:0];
+    }
+}
+
+ at end
diff --git a/modules/gui/macosx/Modules.am b/modules/gui/macosx/Modules.am
index c796624..efd8625 100644
--- a/modules/gui/macosx/Modules.am
+++ b/modules/gui/macosx/Modules.am
@@ -1,4 +1,5 @@
 AM_LIBTOOLFLAGS=--tag=CC
+AM_LDFLAGS=-framework IOKit
 
 SOURCES_macosx = \
 	CompatibilityFixes.h \
@@ -99,4 +100,6 @@ SOURCES_macosx = \
 	PLItem.m \
 	PLModel.h \
 	PLModel.m \
+	KeyboardBacklight.h \
+	KeyboardBacklight.m
 	$(NULL)
diff --git a/modules/gui/macosx/VLCVoutWindowController.h b/modules/gui/macosx/VLCVoutWindowController.h
index c6a61dd..9c2164f 100644
--- a/modules/gui/macosx/VLCVoutWindowController.h
+++ b/modules/gui/macosx/VLCVoutWindowController.h
@@ -25,6 +25,7 @@
 #import <Cocoa/Cocoa.h>
 
 #import <vlc_vout_window.h>
+#import "KeyboardBacklight.h"
 
 @class VLCVideoWindowCommon;
 @class VLCVoutView;
@@ -32,6 +33,7 @@
 @interface VLCVoutWindowController : NSObject
 {
     NSMutableDictionary *o_vout_dict;
+    KeyboardBacklight *o_keyboard_backlight;
 
     NSPoint top_left_point;
 
diff --git a/modules/gui/macosx/VLCVoutWindowController.m b/modules/gui/macosx/VLCVoutWindowController.m
index 53ed3fe..5cc235d 100644
--- a/modules/gui/macosx/VLCVoutWindowController.m
+++ b/modules/gui/macosx/VLCVoutWindowController.m
@@ -40,6 +40,7 @@
 {
     self = [super init];
     o_vout_dict = [[NSMutableDictionary alloc] init];
+    o_keyboard_backlight = [[KeyboardBacklight alloc] init];
     i_currentWindowLevel = NSNormalWindowLevel;
     i_currentFloatingWindowLevel = NSFloatingWindowLevel;
     return self;
@@ -51,6 +52,7 @@
     for (NSValue *key in keys)
         [self removeVoutforDisplay:key];
 
+    [o_keyboard_backlight release];
     [o_vout_dict release];
     [super dealloc];
 }
@@ -339,6 +341,15 @@
     if(p_wnd)
         o_current_window = [o_vout_dict objectForKey:[NSValue valueWithPointer:p_wnd]];
 
+    input_thread_t * p_input = pl_CurrentInput(p_intf);
+
+    // Disable keyboard backlight when entering fullscreen and a video is playing.
+    // Restore keyboard backlight when exiting fullscreen.
+    if (p_input != NULL && var_InheritBool(p_intf, "macosx-dim-keyboard")) {
+        BOOL b_backlight_off = (b_fullscreen && var_GetInteger(p_input, "state") == PLAYING_S);
+        [o_keyboard_backlight switchLightsAsync:!b_backlight_off];
+    }
+
     if (b_nativeFullscreenMode) {
         if(!o_current_window)
             o_current_window = [VLCMainWindow sharedInstance];
@@ -355,7 +366,6 @@
         assert(o_current_window);
 
         if (b_fullscreen) {
-            input_thread_t * p_input = pl_CurrentInput(p_intf);
             if (p_input != NULL && [[VLCMain sharedInstance] activeVideoPlayback]) {
                 // activate app, as method can also be triggered from outside the app (prevents nasty window layout)
                 [NSApp activateIgnoringOtherApps:YES];
diff --git a/modules/gui/macosx/intf.h b/modules/gui/macosx/intf.h
index bbb5283..c46ac37 100644
--- a/modules/gui/macosx/intf.h
+++ b/modules/gui/macosx/intf.h
@@ -43,6 +43,7 @@
 #import "MainWindow.h"
 #import "VLCVoutWindowController.h"
 #import "StringUtility.h"
+#import "KeyboardBacklight.h"
 
 #import <IOKit/pwr_mgt/IOPMLib.h>           /* for sleep prevention */
 
@@ -120,6 +121,8 @@ static NSString * VLCInputChangedNotification = @"VLCInputChangedNotification";
     BOOL b_has_spotify_paused;
     NSTimer *o_itunes_play_timer;
 
+    KeyboardBacklight *o_keyboard_backlight;
+
     dispatch_queue_t informInputChangedQueue;
 }
 
diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m
index 678952b..d3071a7 100644
--- a/modules/gui/macosx/intf.m
+++ b/modules/gui/macosx/intf.m
@@ -672,6 +672,7 @@ static VLCMain *_o_sharedMainInstance = nil;
     o_mainmenu = [[VLCMainMenu alloc] init];
     o_coreinteraction = [[VLCCoreInteraction alloc] init];
     o_eyetv = [[VLCEyeTVController alloc] init];
+    o_keyboard_backlight = [[KeyboardBacklight alloc] init];
 
     /* announce our launch to a potential eyetv plugin */
     [[NSDistributedNotificationCenter defaultCenter] postNotificationName: @"VLCOSXGUIInit"
@@ -876,6 +877,11 @@ static bool f_appExit = false;
 
     [self resumeItunesPlayback:nil];
 
+    /* Restore keyboard backlight when exiting */
+    if (var_InheritBool(p_intf, "macosx-dim-keyboard")) {
+	[o_keyboard_backlight switchLightsInstantly:YES];
+    }
+
     if (notification == nil)
         [[NSNotificationCenter defaultCenter] postNotificationName: NSApplicationWillTerminateNotification object: nil];
 
@@ -953,6 +959,7 @@ static bool f_appExit = false;
     [o_coredialogs release];
     [o_eyetv release];
     [o_remote release];
+    [o_keyboard_backlight release];
 
     /* unsubscribe from libvlc's debug messages */
     vlc_LogSet(p_intf->p_libvlc, NULL, NULL);
@@ -1539,6 +1546,8 @@ static bool f_appExit = false;
         }
     }
 
+    BOOL b_backlight_on = YES;
+
     if (state == PLAYING_S) {
         if (i_control_itunes > 0) {
             // pause iTunes
@@ -1569,6 +1578,9 @@ static bool f_appExit = false;
             }
         }
 
+        /* Dim keyboard backlight if a video is playing in fullscreen */
+        b_backlight_on = !(var_InheritBool(p_intf, "fullscreen") && [self activeVideoPlayback]);
+
         /* Declare user activity.
          This wakes the display if it is off, and postpones display sleep according to the users system preferences
          Available from 10.7.3 */
@@ -1618,6 +1630,9 @@ static bool f_appExit = false;
         [[self mainMenu] setPlay];
         [o_mainwindow setPlay];
 
+        /* Restore keyboard backlight when nothing is playing */
+        b_backlight_on = YES;
+
         /* allow the system to sleep again */
         if (systemSleepAssertionID > 0) {
             msg_Dbg(VLCIntf, "releasing sleep blocker (%i)" , systemSleepAssertionID);
@@ -1642,6 +1657,10 @@ static bool f_appExit = false;
         }
     }
 
+    if (var_InheritBool(p_intf, "macosx-dim-keyboard")) {
+       [o_keyboard_backlight switchLightsAsync:b_backlight_on];
+    }
+
     [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainWindow) withObject: nil waitUntilDone: NO];
     [self performSelectorOnMainThread:@selector(sendDistributedNotificationWithUpdatedPlaybackStatus) withObject: nil waitUntilDone: NO];
 }
diff --git a/modules/gui/macosx/macosx.m b/modules/gui/macosx/macosx.m
index 1c73e96..e1d84ef 100644
--- a/modules/gui/macosx/macosx.m
+++ b/modules/gui/macosx/macosx.m
@@ -107,6 +107,9 @@ void WindowClose  (vout_window_t *);
 
 #define LOCK_ASPECT_RATIO_TEXT N_("Lock Aspect Ratio")
 
+#define DIM_KEYBOARD_PLAYBACK_TEXT N_("Dim keyboad backlight during fullscreen playback")
+#define DIM_KEYBOARD_PLAYBACK_LONGTEXT N_("Turn off the MacBook keyboard backlight while a video is playing in fullscreen. Automatic brightness adjustment should be disabled in System Preferences.")
+
 #define JUMPBUTTONS_TEXT N_("Show Previous & Next Buttons")
 #define JUMPBUTTONS_LONGTEXT N_("Shows the previous and next buttons in the main window.")
 
@@ -168,6 +171,7 @@ vlc_module_begin()
         add_bool("macosx-video-autoresize", true, KEEPSIZE_TEXT, KEEPSIZE_LONGTEXT, false)
         add_bool("macosx-pause-minimized", false, PAUSE_MINIMIZED_TEXT, PAUSE_MINIMIZED_LONGTEXT, false)
         add_bool("macosx-lock-aspect-ratio", true, LOCK_ASPECT_RATIO_TEXT, LOCK_ASPECT_RATIO_TEXT, true)
+        add_bool("macosx-dim-keyboard", false, DIM_KEYBOARD_PLAYBACK_TEXT, DIM_KEYBOARD_PLAYBACK_LONGTEXT, false)
         add_integer("macosx-control-itunes", 1, ITUNES_TEXT, ITUNES_LONGTEXT, false)
         change_integer_list(itunes_list, itunes_list_text)
         add_integer("macosx-continue-playback", 0, CONTINUE_PLAYBACK_TEXT, CONTINUE_PLAYBACK_LONGTEXT, false)
-- 
2.4.0




More information about the vlc-devel mailing list