diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,16 +50,17 @@ find_package(XCB REQUIRED COMPONENTS XCB RANDR DPMS) -option(WITH_DDCUTIL "DDCUtil library support" OFF) -if(WITH_DDCUTIL) - find_package(DDCUtil REQUIRED) - set_package_properties(DDCUtil - PROPERTIES DESCRIPTION "DDCUtil library support" - TYPE OPTIONAL - PURPOSE "Set monitor settings over DDC/CI channel" - ) +option(HAVE_DDCUTIL "DDCUtil library support" OFF) +if(HAVE_DDCUTIL) + find_package(DDCUtil REQUIRED) + add_compile_definitions(WITH_DDCUTIL) + set_package_properties(DDCUtil + PROPERTIES DESCRIPTION "DDCUtil library support" + TYPE OPTIONAL + PURPOSE "Set monitor settings over DDC/CI channel" + ) else() - add_feature_info("DDCUtil" "Off" "DDCUtil library support is disabled by default as recomemded by authors, add -DWITH_DDCUTIL=On to enable") + add_feature_info("DDCUtil" HAVE_DDCUTIL "DDCUtil library support is disabled by default as recomended by authors, add -DHAVE_DDCUTIL=On to enable") endif() include_directories ( diff --git a/daemon/backends/upower/ddcutilbrightness.h b/backends/upower/ddcutilbrightness.h rename from daemon/backends/upower/ddcutilbrightness.h rename to backends/upower/ddcutilbrightness.h --- a/daemon/backends/upower/ddcutilbrightness.h +++ b/backends/upower/ddcutilbrightness.h @@ -49,9 +49,8 @@ #endif //ifdef WITH_DDCUTIL //Per display properties //destription mapped to vcp values for easy retrieval - QVector > m_descrToVcp_perDisp; - QVector > > m_vcpTovcpValueWithDescr_perDisp; - + QVector m_usedVcp; + QVector> m_supportedVcp_perDisp; long m_tmpCurrentBrightness; QTimer m_setBrightnessEventFilter; diff --git a/backends/upower/ddcutilbrightness.cpp b/backends/upower/ddcutilbrightness.cpp new file mode 100644 --- /dev/null +++ b/backends/upower/ddcutilbrightness.cpp @@ -0,0 +1,169 @@ +/* This file is part of the KDE project + * Copyright (C) 2017 Dorian Vogel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include +#include "ddcutilbrightness.h" + +DDCutilBrightness::DDCutilBrightness() + : m_usedVcp({0x10}) +{ + m_setBrightnessEventFilter.setInterval(100); + m_setBrightnessEventFilter.setSingleShot(true); + connect(&m_setBrightnessEventFilter, &QTimer::timeout, this, &DDCutilBrightness::setBrightnessAfterFilter); +} + +void DDCutilBrightness::detect() +{ +#ifdef WITH_DDCUTIL + DDCA_Status rc; + + qCDebug(POWERDEVIL) << "Check for monitors using ddca_get_displays()..."; + // Inquire about detected monitors. + DDCA_Display_Info_List * dlist = nullptr; + ddca_get_display_info_list2(true, &dlist); + qCInfo(POWERDEVIL) << "[DDCutilBrightness] " << dlist->ct << "display(s) were detected"; + + for (int iDisp = 0; iDisp < dlist->ct; ++iDisp) { + DDCA_Display_Handle dh = nullptr; // initialize to avoid clang analyzer warning + + qCDebug(POWERDEVIL) << "Create a Display Identifier for display"<info[iDisp].model_name; + + m_displayInfoList.append(dlist->info[iDisp]); + + qCDebug(POWERDEVIL) << "Opening the display reference, creating a display handle..."; + rc = ddca_open_display2(dlist->info[iDisp].dref, true, &dh); + if (rc != 0) { + qCWarning(POWERDEVIL) << "[DDCutilBrightness]: ddct_open_display"<< rc; + continue; + } + + DDCA_Feature_List vcpList; + ddca_get_feature_list_by_dref(DDCA_SUBSET_COLOR, dh, false, &vcpList); + qCDebug(POWERDEVIL) << "ddca_feature_list: "<< ddca_feature_list_string(&vcpList, "0x", ","); + QVector tmpVcpList; + for (int iVcp = 0; iVcp < m_usedVcp.count(); ++iVcp) { + DDCA_Non_Table_Vcp_Value returnValue; + rc = ddca_get_non_table_vcp_value(dh,m_usedVcp.value(iVcp), &returnValue); + + if (rc < 0) { + qCDebug(POWERDEVIL) << "[DDCutilBrightness]: This monitor does not seem to support " << m_usedVcp[iVcp]; + } else { + qCDebug(POWERDEVIL) << "[DDCutilBrightness]: This monitor supports " << m_usedVcp[iVcp]; + tmpVcpList.append(m_usedVcp.value(iVcp)); + } + } + //we only store displays that actually support the features we want. + if (tmpVcpList.contains(0x10)) { + qCDebug(POWERDEVIL) << "Display supports Brightness, adding handle to list"; + m_displayHandleList.append(dh); + m_supportedVcp_perDisp.value(iDisp).append(tmpVcpList); + } + } +#else + qCInfo(POWERDEVIL) << "[DDCutilBrightness] compiled without DDC/CI support"; + return; +#endif +} + +bool DDCutilBrightness::isSupported() const +{ +#ifdef WITH_DDCUTIL + return !m_displayHandleList.isEmpty(); +#else + return false; +#endif +} + +long DDCutilBrightness::brightness() +{ +#ifdef WITH_DDCUTIL + //we check whether the timer is running, this means we received new values but did not send them yet to the monitor + //not checking that results in the brightness slider jump to the previous value when changing. + if (m_setBrightnessEventFilter.isActive()) { + m_lastBrightnessKnown = m_tmpCurrentBrightness; + } else { //FIXME: gets value for display 1 + DDCA_Status rc; + DDCA_Non_Table_Vcp_Value returnValue; + + rc = ddca_get_non_table_vcp_value(m_displayHandleList.at(0), + 0x10, &returnValue); + qCDebug(POWERDEVIL) << "[DDCutilBrightness::brightness]: ddca_get_vcp_value returned" << rc; + + //check rc to prevent crash on wake from idle and the monitor has gone to powersave mode + if (rc == 0) { + m_lastBrightnessKnown = (long)(returnValue.sh <<8|returnValue.sl); + } + } + return m_lastBrightnessKnown; +#else + return 0; +#endif +} + +long DDCutilBrightness::brightnessMax() +{ +#ifdef WITH_DDCUTIL + DDCA_Status rc; + DDCA_Non_Table_Vcp_Value returnValue; + + rc = ddca_get_non_table_vcp_value(m_displayHandleList.at(0) + , 0x10, &returnValue); + qCDebug(POWERDEVIL) << "[DDCutilBrightness::brightnessMax]: ddca_get_vcp_value returned" << rc; + + //check rc to prevent crash on wake from idle and the monitor has gone to powersave mode + if (rc == 0) { + m_lastMaxBrightnessKnown = (long)(returnValue.mh <<8|returnValue.ml); + } + + return m_lastMaxBrightnessKnown; +#else + return 100.0; +#endif +} + +void DDCutilBrightness::setBrightness(long value) +{ + m_tmpCurrentBrightness = value; + qCDebug(POWERDEVIL) << "[DDCutilBrightness]: saving brightness value: " << value; + m_setBrightnessEventFilter.start(); +} + +void DDCutilBrightness::setBrightnessAfterFilter() +{ +#ifdef WITH_DDCUTIL + DDCA_Status rc; + for (int iDisp = 0; iDisp < m_displayHandleList.count(); ++iDisp) { //FIXME: we set the same brightness to all monitors, plugin architecture needed + qCDebug(POWERDEVIL) << "[DDCutilBrightness]: setting brightness "<> 8; + uint8_t newsl = (uint16_t)m_tmpCurrentBrightness & 0x00ff; + rc = ddca_set_non_table_vcp_value(m_displayHandleList.at(iDisp), 0x10, + newsh, newsl); + + if (rc < 0) { + qCWarning(POWERDEVIL) << "[DDCutilBrightness::setBrightness] failed, trying to detect()"; + detect(); + } else { + m_lastBrightnessKnown = m_tmpCurrentBrightness; + } + } +#else + return; +#endif +} diff --git a/daemon/backends/upower/ddcutilbrightness.cpp b/daemon/backends/upower/ddcutilbrightness.cpp deleted file mode 100644 --- a/daemon/backends/upower/ddcutilbrightness.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* This file is part of the KDE project - * Copyright (C) 2017 Dorian Vogel - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License version 2 as published by the Free Software Foundation. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include -#include "ddcutilbrightness.h" - - -DDCutilBrightness::DDCutilBrightness() -{ - m_setBrightnessEventFilter.setInterval(100); - m_setBrightnessEventFilter.setSingleShot(true); - connect(&m_setBrightnessEventFilter, &QTimer::timeout, this, &DDCutilBrightness::setBrightnessAfterFilter); -} - -void DDCutilBrightness::detect() -{ -#ifndef WITH_DDCUTIL - qCInfo(POWERDEVIL) << "[DDCutilBrightness] compiled without DDC/CI support"; - return; -#else - DDCA_Status rc; - - qCDebug(POWERDEVIL) << "Check for monitors using ddca_get_displays()..."; - // Inquire about detected monitors. - DDCA_Display_Info_List * dlist = ddca_get_display_info_list(); - qCDebug(POWERDEVIL) << "ddca_get_display_info_list() returned "<< dlist; - qCInfo(POWERDEVIL) << "[DDCutilBrightness] " << dlist->ct << "display(s) were detected"; - - for (int iDisp=0;iDispct;iDisp++) { - DDCA_Display_Identifier did; - DDCA_Display_Ref dref; - DDCA_Display_Handle dh = nullptr; // initialize to avoid clang analyzer warning - - qCDebug(POWERDEVIL) << "Create a Display Identifier for display"<info[iDisp].model_name; - - m_displayInfoList.append(dlist->info[iDisp]); - - rc = ddca_create_dispno_display_identifier(iDisp+1, &did); // ddcutil uses 1 paded indexing for displays - - char * did_repr = ddca_did_repr(did); - - qCDebug(POWERDEVIL) << "did="<vcp_code_ct << "capabilities parsed"; - - - m_descrToVcp_perDisp.append(QMap()); - m_vcpTovcpValueWithDescr_perDisp.append(QMap >() ); - //fill the feature description to vcp LUT - - DDCA_Version_Feature_Info* featureInfo; - for (int iVcp=0;iVcpvcp_code_ct;iVcp++) { - - int vcpCode=parsedCapabilities->vcp_codes[iVcp].feature_code; - - m_vcpTovcpValueWithDescr_perDisp[iDisp].insert(vcpCode, QMap()); - - m_descrToVcp_perDisp[iDisp].insert( - QString(ddca_get_feature_name(vcpCode)), vcpCode); - - - ddca_get_feature_info_by_display(m_displayHandleList.at(iDisp), vcpCode, &featureInfo); - if (featureInfo == nullptr) { - continue; - } - qCDebug(POWERDEVIL) << featureInfo->feature_code<<":"<desc; - if ((featureInfo->feature_flags & DDCA_SIMPLE_NC) != DDCA_SIMPLE_NC) { - continue; - } - for (int iVcpVal=0;featureInfo->sl_values[iVcpVal].value_code!=0;++iVcpVal) { - - qCDebug(POWERDEVIL) << "\t"<sl_values[iVcpVal].value_code - <<":"<< featureInfo->sl_values[iVcpVal].value_name; - - bool thisVcpValIsSupported=false; - - for (int iSupportedVcpVal=0; iSupportedVcpValvcp_codes[iVcp].value_ct; iSupportedVcpVal++) { - if(parsedCapabilities->vcp_codes[iVcp].values[iSupportedVcpVal] - ==featureInfo->sl_values[iVcpVal].value_code) { - thisVcpValIsSupported=true; - } - } - - if (thisVcpValIsSupported) { - (m_vcpTovcpValueWithDescr_perDisp[iDisp])[vcpCode].insert( - featureInfo->sl_values[iVcpVal].value_code, - featureInfo->sl_values[iVcpVal].value_name); - } - } - } - ddca_free_display_identifier(did); - ddca_free_parsed_capabilities(parsedCapabilities); - } -#endif -} - - -bool DDCutilBrightness::isSupported() const -{ -#ifndef WITH_DDCUTIL - return false; -#else - return !m_displayHandleList.isEmpty(); -#endif -} - - -long DDCutilBrightness::brightness() -{ -#ifdef WITH_DDCUTIL - //we check whether the timer is running, this means we received new values but did not send them yet to the monitor - //not checking that results in the brightness slider jump to the previous vqlue when changing. - if(m_setBrightnessEventFilter.isActive()) { - m_lastBrightnessKnown = m_tmpCurrentBrightness; - } - else { //FIXME: gets value for display 1 - DDCA_Status rc; - DDCA_Single_Vcp_Value *returnValue; - - rc = ddca_get_vcp_value(m_displayHandleList.at(0), - m_descrToVcp_perDisp.at(0).value("Brightness"), - DDCA_NON_TABLE_VCP_VALUE, &returnValue); - qCDebug(POWERDEVIL) << "[DDCutilBrightness::brightness]: ddca_get_vcp_value returned" << rc; - - //check rc to prevent crash on wake from idle and the monitor has gone to powersave mode - if (rc == 0) { - m_lastBrightnessKnown = (long)returnValue->val.c.cur_val; - } - } - return m_lastBrightnessKnown; -#else - return 0; -#endif -} - -long DDCutilBrightness::brightnessMax() -{ -#ifdef WITH_DDCUTIL - DDCA_Status rc; - DDCA_Single_Vcp_Value *returnValue; - - rc = ddca_get_vcp_value(m_displayHandleList.at(0), - m_descrToVcp_perDisp.at(0).value("Brightness"), - DDCA_NON_TABLE_VCP_VALUE, &returnValue); - qCDebug(POWERDEVIL) << "[DDCutilBrightness::brightnessMax]: ddca_get_vcp_value returned" << rc; - - //check rc to prevent crash on wake from idle and the monitor has gone to powersave mode - if (rc == 0) { - m_lastMaxBrightnessKnown = (long)returnValue->val.c.max_val; - } - - return m_lastMaxBrightnessKnown; -#else - return 100.0; -#endif -} - -void DDCutilBrightness::setBrightness(long value) -{ - m_tmpCurrentBrightness = value; - qCDebug(POWERDEVIL) << "[DDCutilBrightness]: saving brightness value: " << value; - m_setBrightnessEventFilter.start(); -} - -void DDCutilBrightness::setBrightnessAfterFilter() -{ -#ifdef WITH_DDCUTIL - DDCA_Status rc; - for (int iDisp=0;iDisp