タッチ スクリーン用に開発しており、タッチ イベントを検出して画面を再びオンにする必要があります。Qt とソケットを使用していますが、興味深い問題に遭遇しました。
私の QSocketNotifier がイベントを検出するたびに、それに関する無限の通知が送信されます。したがって、イベント ファイルを閉じてから開き、通知機能 (以下のコードの inputNotifier) を循環させる必要があります。この問題は通常、デバイスが実行されてから数分後に発生し、ファイル (inputDevice) のハンドルが 24 から別のもの (通常は 17) に突然変更されます。
最初の接続ステートメントが最初の Notifier ポインターにリンクされているため、どうすればよいかわかりません。新しいハンドルを使用して新しい Notifier を作成すると、接続が無効になります。私が知る限り、実行中の QSocketNotifier に新しいソケット値を設定するオプションはありません。提案?関連するコードは次のとおりです。
#include "backlightcontroller.h"
#include <QTimer>
#include <QFile>
#include <syslog.h>
#include <QDebug>
#include <QSocketNotifier>
BacklightController::BacklightController(QObject *parent) :
QObject(parent)
{
backlightActive = true;
// setup timer
trigger = new QTimer;
trigger->setSingleShot(false);
connect(trigger, SIGNAL(timeout()), SLOT(deactivateBacklight()));
idleTimer = new QTimer;
idleTimer->setInterval(IDLE_TIME * 1000);
idleTimer->setSingleShot(false);
connect(idleTimer, SIGNAL(timeout()), SIGNAL(idled()));
idleTimer->start();
// setup socket notifier
inputDevice = new QFile(USERINPUT_DEVICE);
if (!inputDevice->open(QIODevice::ReadOnly))
{
syslog (LOG_ERR, "Input file for Backlight controller could not been opened.");
}
else
{
inputNotifier = new QSocketNotifier(inputDevice->handle(), QSocketNotifier::Read);
inputNotifier->setEnabled(true);
connect(inputNotifier, SIGNAL(activated(int)), SLOT(activateBacklight()));
}
qDebug()<<"backlight socket: "<<inputNotifier->socket();
// read out settings-file
QString intensity = Global::system_settings->getValue("BelatronUS_backlight_intensity");
if (intensity.length() == 0) intensity = "100";
QString duration = Global::system_settings->getValue("BelatronUS_backlight_duration");
if (duration.length() == 0) duration = "180";
QString always_on = Global::system_settings->getValue("BelatronUS_backlight_always_on");
if (always_on.length() == 0) always_on = "0";
setIntensity(intensity.toInt());
setDuration(duration.toInt());
if (always_on == "0")
setAlwaysOn(false);
else
setAlwaysOn(true);
}
BacklightController::~BacklightController()
{
trigger->stop();
inputNotifier->setEnabled(false);
inputDevice->close();
delete trigger;
delete inputDevice;
delete inputNotifier;
}
void BacklightController::setCurrentIntensity(int intensity)
{
// adapt backlight intensity
QFile backlightFile("/sys/class/backlight/atmel-pwm-bl/brightness");
if (!backlightFile.open(QIODevice::WriteOnly))
{
syslog (LOG_ERR, "Backlight intensity file could not been opened.");
}
else
{
QString intensityString = QString::number(TO_BRIGHTNESS(intensity));
if (backlightFile.write(
qPrintable(intensityString), intensityString.length()
) < intensityString.length())
{
syslog (LOG_ERR, "Backlight intensity could not been changed.");
}
backlightFile.close();
}
}
void BacklightController::resetNotifier()
{
inputDevice->close();
if (!inputDevice->open(QIODevice::ReadOnly))
{
syslog (LOG_ERR, "BacklightController::%s: Input file could not been opened.", __FUNCTION__);
}
qDebug()<<"reset, handle: "<<inputDevice->handle();
//inputNotifier=QSocketNotifier(inputDevice->handle(), QSocketNotifier::Read);
// restart timer after user input
idleTimer->start();
}
void BacklightController::activateBacklight()
{
// only activate backlight, if it's off (avoid to useless fileaccess)
if (!backlightActive)
{
setCurrentIntensity(_intensity);
backlightActive = true;
emit backlightActivated();
}
// restart backlight timeout, but only if we don't want the backlight to shine all the time
if (!_alwaysOn)
trigger->start();
// reset notifier to be able to catch the next userinput
resetNotifier();
}
void BacklightController::deactivateBacklight()
{
// don't turn it off, if it's forced on
if (!_alwaysOn)
{
if (backlightActive)
{
// only deactivate backlight, if it's on (avoid to useless fileaccess)
setCurrentIntensity(BACKLIGHT_INTENSITY_OFF);
backlightActive = false;
emit backlightDeactivated();
}
}
qDebug()<<"trigger stopping";
trigger->stop();
}
void BacklightController::setIntensity(int intensity)
{
if (intensity > 100)
intensity = 100;
else if (intensity < 0)
intensity = 0;
_intensity = intensity;
// write new intensity to file if it's active at the moment
if (backlightActive)
{
setCurrentIntensity(_intensity);
trigger->start();
}
}
void BacklightController::setDuration(int duration)
{
if (duration < 1)
duration = 1;
_duration = duration;
trigger->setInterval(_duration * MS_IN_SEC);
// reset trigger after changing duration
if (backlightActive)
{
trigger->start();
}
}
void BacklightController::setAlwaysOn(bool always_on)
{
_alwaysOn = always_on;
// tell the timer what to to now
if (_alwaysOn)
{
this->activateBacklight();
trigger->stop();
}
else
{
trigger->start();
}
}