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

David Fuhrmann david.fuhrmann at gmail.com
Tue May 19 21:09:17 CEST 2015


Hi,


> Am 18.05.2015 um 22:36 schrieb Maxime Mouchet <max at maxmouchet.com>:
> 
> 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.

Well, getting rid of the singleton only makes sense if we can integrate your class in one place only - my idea was to do it in VLCVoutController as you should have all events here.

> I kept the code to manage play an pause transitions in VLCIntf (in the same
> place as the code for iTunes and Spotify).

Why?

> 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).

This should be possible to do in VoutWindowController as well: When video playback is started, setupVoutForWindow:… is called.

> * Restore backlight when exiting fullscreen (in VLCVoutWindowController).
> * Restore backlight on pause/stop,

You want to restore the blacklight on pause as well? Why?

> or when exiting (in intf).

Isn’t it possible to do that in VoutWindowController as well? But its good that you think about termination as well - we should have no extra thread running why the main loop already quit.

> 
> 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];
> +    }

Why checking for input and PLAYING_S here? Should not be necessary I think.

> +
>     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

Best regards,
David


More information about the vlc-devel mailing list