2012-10-23 15 views
2

我正在開發觸摸屏並需要檢測觸摸事件才能重新開啓屏幕。我正在使用Qt和套接字,並遇到了一個有趣的問題。文件更改句柄,由於無效套接字而導致QSocketNotifier禁用

每當我的QSocketNotifier檢測到事件時,它都會發送給我無限的通知。因此,我需要關閉並打開事件文件來循環通知程序(inputNotifier在下面的代碼中)。問題通常在設備運行幾分鐘後出現,文件(inputDevice)突然將其句柄從24更改爲其他內容(通常爲17)。

我不知道該怎麼做,因爲初始連接語句鏈接到最初的通告程序指針。如果我使用新句柄創建新的通告程序,則連接無效。據我所知,沒有選項可以在正在運行的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(); 
    } 
} 

回答

1

我似乎已經找到了一個現在的工作解決方案。這不是最好的,如果有更好的解決方案,我會有興趣聽到他們。之前我沒有想到這一點的原因是因爲我認爲如果我在函數中有一個新的連接語句,函數結束時它的範圍有限。

解決方案是簡單地檢查文件中句柄更改的發生,然後使用該句柄爲通知程序創建一個新指針。然後重新啓用通知程序,因爲它現在可能已被禁用,然後爲該指針創建一個新的連接語句。這是我使用的代碼,剛剛添加到事件文件的關閉和重新打開下方:

if(inputDevice->handle()!=inputNotifier->socket()){ 
    inputNotifier = new QSocketNotifier(inputDevice->handle(), QSocketNotifier::Read); 
    inputNotifier->setEnabled(true); 
    connect(inputNotifier, SIGNAL(activated(int)), SLOT(activateBacklight())); 
} 
相關問題