Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a hardware backlight interface and gui controls #14970

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

lrusak
Copy link
Contributor

@lrusak lrusak commented Nov 29, 2018

This adds a new interface to allow adjusting a hardware backlight (like those found in laptops or touchscreens). This change required a rework of the sysfs utility to comply with the kernel documentation (as interpreted by me). This backlight interface is also quite invasive as it touches many parts of Kodi internals so it could use a thorough review as maybe I did more than what is needed.

This change add no new dependencies or ifdefs. The interface is opt in and requires registration. The backlight utility can be used for amlogic and rpi windowing too if someone wants to implement that.

I also have basically zero knowledge of kodi dialogs and skinning, this is the first time I have touched these areas and am open for input about these changes. I also created the backlight icon myself so if someone wants to do it better feel free 🎨

This image shows both the touch screen interface and the onscreen indicator (hidden between the gallium hud elements).
backlight

I will outline the commits below with their messages:

SysfsUtils: cleanup and improve interface according to the documentation

as written in the kernel docs:

sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
method. Sysfs will call the method exactly once for each read or
write.

When writing sysfs files, userspace processes should first read the
entire file, modify the values it wishes to change, then write the
entire buffer back.

for more info please consult the kernel documentation:

https://www.kernel.org/doc/Documentation/filesystems/sysfs.txt

Add new backlight interface and gui

this adds a new interface to be able to access a hardware
backlight. this also adds the gui elements needed to show
the backlight brightness change and to change it via the
touch screen interface. this change is quite invasive but
it is based off the way the volume control works.

the backlight controls will not be show if no backlight
has been register to CServiceBroker

CLibInputKeyboard: add brightness keys

this adds the keyboard backlight brightness keys to the libinput
keyboard mapping.

CBacklight: add linux backlight helper utility

this utility interacts with the kernel sysfs backlight control
by querying the backlight device and matching it to the drm device.

windowing/gbm: use CBacklight

add the linux backlight utility to gbm windowing.

@lrusak lrusak added Type: Feature non-breaking change which adds functionality Platform: Linux v19 Matrix labels Nov 29, 2018
@garbear
Copy link
Member

garbear commented Dec 1, 2018

I see you're entered the realm of the GUI :) Still time constrained so I can't offer much feedback than that, but good job. Cool feature!

@@ -1645,7 +1645,9 @@ const infomap system_labels[] = {{ "hasnetwork", SYSTEM_ETHERNET_LINK_ACT
{ "stereoscopicmode", SYSTEM_STEREOSCOPIC_MODE },
{ "hascms", SYSTEM_HAS_CMS },
{ "privacypolicy", SYSTEM_PRIVACY_POLICY },
{ "haspvraddon", SYSTEM_HAS_PVR_ADDON }};
{ "haspvraddon", SYSTEM_HAS_PVR_ADDON },
{ "hasbacklight", SYSTEM_HAS_BACKLIGHT },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing doxygen entry at the top of the map like all the others

static int SetInt(const std::string& path, const int val);
static int GetInt(const std::string& path, int& val);
static bool SetString(const std::string& path, const std::string& value);
static const std::string GetString(const std::string& path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why you return const std::string and not std::string ?
Same for the const int below.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1; never return const

}

return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to call closedir after you finished.

static void Register(std::shared_ptr<IBacklight> backlight) { CServiceBroker::RegisterBacklight(backlight); }

virtual bool SetBrightness(int brightness) = 0;
virtual int GetBrightness() = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the implementation actually hasn't even a member for it, I'd still make this
virtual int GetBrightness() const = 0;
Same for other Getters.

@a1rwulf
Copy link
Member

a1rwulf commented Dec 4, 2018

Please make sure the IBacklight interface is already there when you implement CBacklight so it doesn't break bisect.

Copy link
Member

@yol yol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of minors, but at the very least you have to split the commits differently so that they follow logically and you can bisect.

👍 for changing the SysfsUtils interface :-)

{
if (SysfsUtils::GetString("/sys/class/amhdmitx/amhdmitx0/disp_cap", valstr) < 0)
std::string valstr = SysfsUtils::GetString("/sys/class/amhdmitx/amhdmitx0/disp_cap");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable redeclaration (curious that you didn't get a warning at least)

return false;

if (SysfsUtils::GetString("/sys/class/amhdmitx/amhdmitx0/vesa_cap", vesastr) == 0)
std::string vesastr = SysfsUtils::GetString("/sys/class/amhdmitx/amhdmitx0/vesa_cap");
if (vesastr.length() > 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

100% unimportant, but out of curiosity: Why not !vesastr.empty()? (considering the check 4 lines above)

if (write(fd, valstr.c_str(), valstr.size()) < 0)
ret = -1;
close(fd);
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this is a good idea? Does the kernel interface guarantee that writing a value that already "seems" to be there never has any (desired) side-effect?

#ifdef TARGET_WINDOWS_STORE
#include <io.h>
#endif
static const unsigned int PAGESIZE = getpagesize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

namespace {} instead of static

int fd = open(path.c_str(), O_RDWR);
if (fd < 0)
{
CLog::Log(LOGERROR, "{}: error opening {}", __FUNCTION__, path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with SetString: error opening xxxxx the SetString: prefix is not going to be especially helpful. Rather write something descriptive (sysfs utils or the like).

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2005-2018 Team Kodi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong year

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2005-2018 Team Kodi
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong year

@@ -85,6 +85,20 @@ static int NotifyAll(const std::vector<std::string>& params)
return 0;
}

/*! \brief Set volume.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

volume

class IBacklight
{
public:
static void Register(std::shared_ptr<IBacklight> backlight) { CServiceBroker::RegisterBacklight(backlight); }
Copy link
Member

@yol yol Dec 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not completely sure what the purpose of this function is?
EDIT: to clarify, why is having this better than just calling CServiceBroker::RegisterBacklight?

@@ -27,6 +25,11 @@ set(HEADERS Backlight.h
XMemUtils.h
XTimeUtils.h)

if(CORE_SYSTEM_NAME STREQUAL linux)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shouldn't it be linux in this directory?

@jenkins4kodi jenkins4kodi added the Rebase needed PR that does not apply/merge cleanly to current base branch label Mar 19, 2019
@phunkyfish
Copy link
Contributor

@lrusak do you want to progress this, close it or backburner?

@phunkyfish phunkyfish added the PR Cleanup: Ask Author PR appears to still be relevant and mergeable. Comment to author to check on status. label Mar 8, 2020
@lrusak
Copy link
Contributor Author

lrusak commented Mar 21, 2020

I would still like to see this get merged in, I'll revisit it at some point

@phunkyfish phunkyfish added PR Cleanup: Recent Checked as part of PR cleanup. PR has been followed up on recently. and removed PR Cleanup: Ask Author PR appears to still be relevant and mergeable. Comment to author to check on status. labels Mar 23, 2020
this adds a new interface to be able to access a hardware
backlight. this also adds the gui elements needed to show
the backlight brightness change and to change it via the
touch screen interface. this change is quite invasive but
it is based off the way the volume control works.

the backlight controls will not be show if no backlight
has been register to CServiceBroker
this adds the keyboard backlight brightness keys to the libinput
keyboard mapping.
this utility interacts with the kernel sysfs backlight control
by querying the backlight device and matching it to the drm device.
add the linux backlight utility to gbm windowing.
@jenkins4kodi jenkins4kodi removed the Rebase needed PR that does not apply/merge cleanly to current base branch label Sep 23, 2020

virtual bool SetBrightness(int brightness) = 0;
virtual int GetBrightness() const = 0;
virtual int GetMaxBrightness() const = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int is not very descriptive of what a brightness is, so could use some documentation. typing could also improve semantics. could I suggest a float in the range [0, 1]?

@@ -337,6 +337,9 @@

#define ACTION_HDR_TOGGLE 260 //!< Toggle display HDR on/off

#define ACTION_BACKLIGHT_BRIGHTNESS_UP 251
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ID is a duplicate of ACTION_QUEUE_ITEM_NEXT, you probably want 261

@@ -645,6 +653,10 @@ bool CSystemGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int context
}
break;
}
case SYSTEM_HAS_BACKLIGHT:
std::shared_ptr<IBacklight> backlight = CServiceBroker::GetBacklight();
value = !!backlight;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe static_cast<bool>(backlight) to be a little more explicit about what is going on here?

return CGUIDialog::OnMessage(message);
}

return false; // don't process anything other than what we need!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it just saddens me to see lengthy backlight logic added to CApplication. With your work, we now have a beautiful minimal file to add logic to. What if we move all backlight logic from CApplication into this file?

@garbear
Copy link
Member

garbear commented Sep 23, 2020

Glad to see you've revisited this. please, please, please don't increase the size of service broker. these are effectively globals (ok, singletons with global scope, so their lifetime is managed relative to just each other, yay?). let's get creative in how we can not nuke architecture. remember, architecture is not what you build, but what you restrict.

Looking at the technical debt we've currently saddled service broken with, I see two promising options. Peripheral manager and power manager have something to do with backlight. Maybe we can use these.

I'm not that familiar with power manager, but it seems less appropriate for backlight control. backlight changes are not always done from a power perspective. and from a high level, backlight is just responding to user input and controlling hardware. Power manager controls hardware too, but that seems like kind of a stretch.

To use peripheral manager, there seems to be some overhead. this requires treating the display as a peripheral, so we need a class that might not be used for anything else. it doesn't make sense to "scan" for displays, because there can only ever be one (as distinct from monitors). I actually faced this with keyboards and mice and created a virtual "application" bus that has one keyboard and mouse per application. Scanning the "application" bus could also return a monitor/display. And we're in luck. All peripherals can see all actions.

Maybe peripherals, made for hardware, is a good place for hardware backlight control?

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<window type="dialog" id="1110">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id="1110" is already in use, please use 1106 instead

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<window type="dialog" id="1110">
<defaultcontrol>11</defaultcontrol>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop this line, there's no control with id="11" in this dialog

<width>120</width>
<height>120</height>
<label></label>
<onclick>ActivateWindow(1110)</onclick>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to 1106 here as well please

@jenkins4kodi jenkins4kodi added the Rebase needed PR that does not apply/merge cleanly to current base branch label Oct 14, 2020
@jenkins4kodi
Copy link
Contributor

@lrusak this needs a rebase

@setevejhone

This comment has been minimized.

@fuzzard fuzzard removed the v20 Nexus label Oct 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Linux PR Cleanup: Recent Checked as part of PR cleanup. PR has been followed up on recently. Rebase needed PR that does not apply/merge cleanly to current base branch Type: Feature non-breaking change which adds functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants