2012-10-23 11 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())); 
}