X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fjogshuttle.cpp;h=0188b166a7367ce42720f327fc587f2508407220;hb=3c6382a662bd065953ee7793ad25880654809189;hp=1cde287f80e4e780c2ed27bb9f49195736a986ad;hpb=778b2a473faa6c8b9fc966fc1b92d33d77056107;p=kdenlive diff --git a/src/jogshuttle.cpp b/src/jogshuttle.cpp index 1cde287f..0188b166 100644 --- a/src/jogshuttle.cpp +++ b/src/jogshuttle.cpp @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #define DELAY 10 @@ -73,7 +75,7 @@ void ShuttleThread::init(QObject *parent, QString device) stop_me = false; m_isWorking = false; shuttlevalue = 0xffff; - shuttlechange = false; + shuttlecounter = 0; jogvalue = 0xffff; } @@ -84,32 +86,80 @@ bool ShuttleThread::isWorking() void ShuttleThread::run() { - kDebug() << "------- STARTING SHUTTLE: " << m_device; - - const int fd = KDE_open((char *) m_device.toUtf8().data(), O_RDONLY); - if (fd < 0) { - fprintf(stderr, "Can't open Jog Shuttle FILE DESCRIPTOR\n"); - return;; - } - EV ev; - - if (ioctl(fd, EVIOCGRAB, 1) < 0) { - fprintf(stderr, "Can't get exclusive access on Jog Shuttle FILE DESCRIPTOR\n"); - close(fd); - return;; - } - - int num_warnings = 0; - while (!stop_me) { - if (read(fd, &ev, sizeof(ev)) < 0) { - if (num_warnings % 10000 == 0) - fprintf(stderr, "Failed to read event from Jog Shuttle FILE DESCRIPTOR (repeated %d times)\n", num_warnings + 1); - num_warnings++; - } - handle_event(ev); - } - close(fd); - + kDebug() << "------- STARTING SHUTTLE: " << m_device; + /* open file descriptor */ + const int fd = KDE_open((char *) m_device.toUtf8().data(), O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Can't open Jog Shuttle FILE DESCRIPTOR\n"); + return; + } + + EV ev; + + if (ioctl(fd, EVIOCGRAB, 1) < 0) { + fprintf(stderr, "Can't get exclusive access on Jog Shuttle FILE DESCRIPTOR\n"); + close(fd); + return; + } + + fd_set readset; + struct timeval timeout; + + int num_warnings = 0; + int result, iof = -1; + + /* enter thread loop */ + while (!stop_me) { + /* reset the read set */ + FD_ZERO(&readset); + FD_SET(fd, &readset); + + /* reinit the timeout structure */ + timeout.tv_sec = 0; + timeout.tv_usec = 400000; /* 400 ms */ + + /* do select in blocked mode and wake up after timeout for eval stop_me */ + result = select(fd+1, &readset, NULL, NULL, &timeout); + + /* see if there was an error or timeout else process event */ + if (result < 0) { + /* usually this is a condition for exit but EINTR error is thrown + * one time when the playback is started the first time. I think + * its ok to ignore this if its not too often */ + kDebug() << strerror(errno) << "\n"; + } else if (result == 0) { + /* do nothing. reserved for future purposes */ + } else { + /* we have input */ + if (FD_ISSET(fd, &readset)) { + /* get fd settings */ + if ((iof = fcntl(fd, F_GETFL, 0)) != -1) { + /* set fd non blocking */ + fcntl(fd, F_SETFL, iof | O_NONBLOCK); + /* read input */ + if (read(fd, &ev, sizeof(ev)) < 0) { + if (num_warnings % 10000 == 0) + /* should not happen cause select called before */ + fprintf(stderr, "Failed to read event from Jog Shuttle FILE DESCRIPTOR (repeated %d times)\n", num_warnings + 1); + num_warnings++; + } + + /* restore settings */ + if (iof != -1) { + fcntl(fd, F_SETFL, iof); + } + /* process event */ + handle_event(ev); + } else { + fprintf(stderr, "Can't set Jog Shuttle FILE DESCRIPTOR to O_NONBLOCK and stop thread\n"); + stop_me = true; + } + } + } + } + + /* close the handle and return thread */ + close(fd); } void ShuttleThread::handle_event(EV ev) @@ -149,15 +199,17 @@ void ShuttleThread::shuttle(int value) //gettimeofday( &last_shuttle, 0 ); //need_synthetic_shuttle = value != 0; - if (value == shuttlevalue) + if (value == shuttlevalue) { + shuttlecounter = 1; return; + } if (value > MAX_SHUTTLE_RANGE || value < -MAX_SHUTTLE_RANGE) { fprintf(stderr, "Jog Shuttle returned value of %d (should be between -%d ad +%d)", value, MAX_SHUTTLE_RANGE, MAX_SHUTTLE_RANGE); return; } shuttlevalue = value; - shuttlechange = true; + shuttlecounter = 1; QApplication::postEvent(m_parent, new QEvent((QEvent::Type) (JOG_STOP + value))); } @@ -184,14 +236,16 @@ void ShuttleThread::jog(unsigned int value) QApplication::postEvent(m_parent, new QEvent((QEvent::Type) JOG_BACK1)); else if ((forward && !wrap) || (rewind && wrap)) QApplication::postEvent(m_parent, new QEvent((QEvent::Type) JOG_FWD1)); - else if (!forward && !rewind && !shuttlechange) + else if (!forward && !rewind && shuttlecounter > 2) { // An event without changing the jog value is sent after each shuttle change. // As the shuttle rest position does not get a shuttle event, only a non-position-changing jog event. // Hence we stop on this when we see 2 non-position-changing jog events in a row. + shuttlecounter = 0; QApplication::postEvent(m_parent, new QEvent((QEvent::Type) JOG_STOP)); + } } jogvalue = value; - shuttlechange = false; + if (shuttlecounter > 0) shuttlecounter++; } @@ -219,11 +273,11 @@ void JogShuttle::initDevice(QString device) void JogShuttle::stopDevice() { if (m_shuttleProcess.isRunning()) { - /* the read fd is in blocking mode => stop_me is broken at the moment */ + /* tell thread to stop */ m_shuttleProcess.stop_me = true; m_shuttleProcess.exit(); - /* give the thread some time to shutdown */ - m_shuttleProcess.wait(100); + /* give the thread some time (ms) to shutdown */ + m_shuttleProcess.wait(600); /* if still running - do it in the hardcore way */ if (m_shuttleProcess.isRunning()) {