You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
5.3 KiB
195 lines
5.3 KiB
/*****************************************************************************
|
|
* VLCKeyboardBlacklightControl.m: MacBook keyboard backlight control for VLC
|
|
*****************************************************************************
|
|
* Copyright (C) 2015, 2019 VLC authors and VideoLAN
|
|
*
|
|
* Authors: Maxime Mouchet <max@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 "VLCKeyboardBacklightControl.h"
|
|
#import <IOKit/IOKitLib.h>
|
|
#import "main/VLCMain.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 *)
|
|
};
|
|
|
|
@interface VLCKeyboardBacklightControl ()
|
|
{
|
|
io_connect_t _dataPort;
|
|
float _lastBrightnessLevel;
|
|
}
|
|
@end
|
|
|
|
@implementation VLCKeyboardBacklightControl
|
|
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
_dataPort = [self getDataPort];
|
|
_lastBrightnessLevel = [self getBrightness];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
if (_dataPort)
|
|
IOServiceClose(_dataPort);
|
|
}
|
|
|
|
- (io_connect_t)getDataPort {
|
|
if (_dataPort)
|
|
return _dataPort;
|
|
|
|
io_service_t serviceObject = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
|
|
|
|
if (!serviceObject) {
|
|
msg_Warn(getIntf(), "Failed to get an AppleLMUController service, keyboard dimming will not work");
|
|
return 0;
|
|
}
|
|
|
|
kern_return_t kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &_dataPort);
|
|
IOObjectRelease(serviceObject);
|
|
|
|
if (kr != KERN_SUCCESS) {
|
|
msg_Warn(getIntf(), "Failed to open an AppleLMUController service, keyboard dimming will not work");
|
|
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];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|