Pergunta

I am developing for a touch screen and need to detect touch events to turn the screen back on. I am using Qt and sockets and have run into an interesting issue.

Whenever my QSocketNotifier detects the event it sends me infinite notices about it. Therefore I need to close and open the event file to cycle the notifier (inputNotifier in the below code). The problem usually arises several minutes after the device has been running and the file (inputDevice) suddenly changes it's handle from 24 to something else (usually 17).

I am not sure what to do, because the initial connect statement is linked to the initial Notifier pointer. If I create a new Notifier using the new handle, the connect is invalid. As far as I can tell there is no option to set a new socket value on a running QSocketNotifier. Suggestions? The relevant code is below:

#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();
    }
}
Foi útil?

Solução

I seem to have found a working solution for now. It's not the greatest so if there are better solutions I would be interested to hear them. The reason I did not think of this before is because I thought if I had a new connect statement in a function it would have limited scope as the function ended.

The solution was to simply check for an occurrence of the handle change in the file and then create a new pointer for the notifier using that handle. Then re-enable the notifier because it has likely been disabled by now and then create a new connect statement for the pointer. This is the code I used, added just below the closing and reopening of the event file:

if(inputDevice->handle()!=inputNotifier->socket()){
    inputNotifier = new QSocketNotifier(inputDevice->handle(), QSocketNotifier::Read);
    inputNotifier->setEnabled(true);
    connect(inputNotifier, SIGNAL(activated(int)), SLOT(activateBacklight()));
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top