4

タッチ スクリーン用に開発しており、タッチ イベントを検出して画面を再びオンにする必要があります。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();
    }
}
4

1 に答える 1

1

今のところ有効な解決策を見つけたようです。それは最高ではないので、より良い解決策があれば聞いてみたいと思います. 以前はこれについて考えていなかったのは、関数内に新しい connect ステートメントがあると、関数が終了したときにスコープが制限されると思ったからです。

解決策は、ファイル内でハンドルの変更が発生していないかどうかを確認し、そのハンドルを使用してノーティファイアの新しいポインタを作成することでした。次に、notifier が無効になっている可能性があるため、再度有効にしてから、ポインターの新しい接続ステートメントを作成します。これは私が使用したコードで、イベント ファイルを閉じて再度開いた直後に追加されています。

if(inputDevice->handle()!=inputNotifier->socket()){
    inputNotifier = new QSocketNotifier(inputDevice->handle(), QSocketNotifier::Read);
    inputNotifier->setEnabled(true);
    connect(inputNotifier, SIGNAL(activated(int)), SLOT(activateBacklight()));
}
于 2012-10-24T14:19:37.083 に答える