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

David Fuhrmann david.fuhrmann at gmail.com
Sat May 30 13:44:03 CEST 2015


Hello Maxime,

> Am 28.05.2015 um 20:24 schrieb Maxime Mouchet <max at maxmouchet.com>:
> 
> This patch adds the option to smoothly 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.
> ---
> Hi,
> 
> This is the edited patch following the suggestions from the previous versions.
> Logic is now implemented only in VoutWindowController and behaves as follow:
> * Dim keyboard backlight when entering fullscreen.
> * Restore backlight when exiting fullscreen or when quitting VLC.
> 
> I hope it looks better :-)
> 
> 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 |  10 ++
> modules/gui/macosx/macosx.m                  |   4 +
> 6 files changed, 245 insertions(+)
> 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..38c80d3 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,11 @@
>     for (NSValue *key in keys)
>         [self removeVoutforDisplay:key];
> 
> +    if (var_InheritBool(VLCIntf, "macosx-dim-keyboard")) {
> +        [o_keyboard_backlight switchLightsInstantly:YES];
> +    }
> +
> +    [o_keyboard_backlight release];
>     [o_vout_dict release];
>     [super dealloc];
> }
> @@ -339,6 +345,10 @@
>     if(p_wnd)
>         o_current_window = [o_vout_dict objectForKey:[NSValue valueWithPointer:p_wnd]];
> 
> +    if (var_InheritBool(p_intf, "macosx-dim-keyboard")) {
> +        [o_keyboard_backlight switchLightsAsync:!b_fullscreen];
> +    }
> +
>     if (b_nativeFullscreenMode) {
>         if(!o_current_window)
>             o_current_window = [VLCMainWindow sharedInstance];
> diff --git a/modules/gui/macosx/macosx.m b/modules/gui/macosx/macosx.m
> index 1c73e96..37092c8 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 keyboard 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

Thanks for the revised patch, I merged it for now.

But we found one issue we would like to ask you to fix if possible: Its not good to simply fire threads to change the blacklights. If you try switching fullscreen quickly (just quickly press cmd+f a couple of times), you see the lights repeatedly flashing a couple of seconds even after the animation has been finished.

We should cancel previous threads before firing a new one. Speaking of that, maybe it makes even sense to get rid of the threads altogether and switch to a timer doing the animation? I assume the system call is fast enough to be executed on the main thread, and you can easily cancel the timer if a new request comes in.

Best regards,
David




More information about the vlc-devel mailing list