/*! \file pigrabberbase.h * \ingroup Thread * \~\brief * \~english Abstract class for create grabbers * \~russian Базовый класс для создания грабберов */ /* PIP - Platform Independent Primitives Abstract class for create grabbers Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIGRABBERBASE_H #define PIGRABBERBASE_H #include "pithread.h" #include "pidiagnostics.h" template class PIGrabberBase: public PIThread { PIOBJECT_SUBCLASS(PIGrabberBase, PIThread) public: PIGrabberBase() { is_opened = false; is_recording = false; } virtual ~PIGrabberBase() { stopGrabber(false); } virtual bool isOpened() const {return is_opened;} virtual bool isRecording() const {return is_recording;} virtual void startRecord(const PIString & filename) { if (!isOpened()) return; if (isRecording()) return; rec_mutex.lock(); startRecordInternal(filename); is_recording = true; rec_mutex.unlock(); } virtual void stopRecord() { if (!isOpened()) return; if (!isRecording()) return; rec_mutex.lock(); is_recording = false; stopRecordInternal(); rec_mutex.unlock(); } T last() const { T ret; last_mutex.lock(); ret = last_; last_mutex.unlock(); return ret; } bool isEmpty() { bool ret; que_mutex.lock(); ret = que.isEmpty(); que_mutex.unlock(); return ret; } int queSize() { int ret; que_mutex.lock(); ret = que.size(); que_mutex.unlock(); return ret; } T dequeue() { T ret; // piCoutObj << "start"; que_mutex.lock(); if (!que.isEmpty()) { // piCoutObj << "dequeue"; ret = que.dequeue(); } // piCoutObj << "end"; que_mutex.unlock(); return ret; } void stopGrabber(bool wait_forever = true) { if (isRunning()) { stop(); if (wait_forever) waitForFinish(); else { if (!waitForFinish(100)) terminate(); stopRecord(); close(); } } } bool open() { bool ret = openInternal(); if (!is_opened && ret) opened(); is_opened = ret; return ret; } void close() { bool em = is_opened; closeInternal(); last_ = T(); if (em) closed(); is_opened = false; } const PIDiagnostics & diag() const {return diag_;} void clear() { que_mutex.lock(); que.clear(); que_mutex.unlock(); } void restart() { clear(); close(); } EVENT(dataReady) EVENT(opened) EVENT(closed) protected: virtual void init() {} virtual bool openInternal() = 0; virtual void closeInternal() = 0; virtual int get(T & val) = 0; virtual void record(const T & val) {} virtual void startRecordInternal(const PIString & filename) {} virtual void stopRecordInternal() {} bool is_opened, is_recording; mutable PIMutex rec_mutex; private: void begin() { init(); } void run() { if (!isOpened()) { open(); diag_.reset(); if (!is_opened) piMSleep(200); } if (isOpened()) { T c; int ret = get(c); if (ret < 0) { close(); return; } if (ret > 0) { piMinSleep(); return; } diag_.received(1); que_mutex.lock(); que.enqueue(c); que_mutex.unlock(); if (isRecording()) { rec_mutex.lock(); record(c); rec_mutex.unlock(); diag_.sended(1); } last_mutex.lock(); last_ = c; last_mutex.unlock(); dataReady(); } } void end() { stopRecord(); close(); } T last_; PIQueue que; PIDiagnostics diag_; mutable PIMutex que_mutex, last_mutex; }; #endif // PIGRABBERBASE_H