diff --git a/src/cam.cpp b/src/cam.cpp index 7414a8e9112922e95f8926dc991e6ec27c0542e7..67d599e0b60afe162cc56e7b0918295ba801f9b4 100644 --- a/src/cam.cpp +++ b/src/cam.cpp @@ -1,4 +1,5 @@ #include "cam.h" +#include "iprinter.h" #include "utils.h" #include "frameobserver.h" @@ -15,14 +16,12 @@ using State = Cam::State; using namespace VmbCPP; using namespace std::chrono; -//xxx -// Cam(QString name, QString ip) : IPrinter(), -// _cam(CameraPtr(new Camera(name.toStdString(), ip.toStdString()))), - -Cam::Cam(CameraPtr pCamera) : IPrinter(), -_cam(pCamera), +Cam::Cam(QString name, QString ip) : IPrinter(), +_cam(nullptr), +_name(name), +_ip(ip), _id(""), -_state(closed), +_state(disconnected), _frames(FramePtrVector(threadsPerCam())), _payloadSize(0LL), _pixelFormat(""), @@ -30,22 +29,40 @@ _timer(new QTimer(this)) { _timer->setSingleShot(true); connect(_timer, SIGNAL(timeout()), this, SLOT(stopRecording())); - id(); - + // id(); } -// Copy constructor -Cam::Cam(const Cam& other) : -IPrinter(), -_cam(other._cam), -_id(other._id), -_state(other._state), -_frames(other._frames), -_payloadSize(other._payloadSize), -_pixelFormat(other._pixelFormat) -{ - qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "copy constructor"; -} + +//xxx add ip and name +// Cam::Cam(CameraPtr pCamera) : IPrinter(), +// _cam(pCamera), +// _name(""), +// _ip(""), +// _id(""), +// _state(closed), +// _frames(FramePtrVector(threadsPerCam())), +// _payloadSize(0LL), +// _pixelFormat(""), +// _timer(new QTimer(this)) +// { +// _timer->setSingleShot(true); +// connect(_timer, SIGNAL(timeout()), this, SLOT(stopRecording())); +// id(); + +// } + +// // Copy constructor +// Cam::Cam(const Cam& other) : +// IPrinter(), +// _cam(other._cam), +// _id(other._id), +// _state(other._state), +// _frames(other._frames), +// _payloadSize(other._payloadSize), +// _pixelFormat(other._pixelFormat) +// { +// qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "copy constructor"; +// } Cam::~Cam() { @@ -56,6 +73,16 @@ Cam::~Cam() // close() should be called automatically, when the last shared_ptr to the camera is destroyed } +QString Cam::name() const +{ + return _name; +} + +QString Cam::ip() const +{ + return _ip; +} + QString Cam::id() { if( _id.isEmpty() ) @@ -67,6 +94,11 @@ QString Cam::id() return _id; } +void Cam::setState(const State& state) +{ + _state = state; +} + State Cam::state() const { return _state; @@ -74,14 +106,20 @@ State Cam::state() const void Cam::open() { + if(_state != closed) + return error("cant open " + stateToString(_state) + " cam"); + f(_cam->Open( VmbAccessModeFull ),"open cam #"+_id); - //state change will be handled by CamObserver::CameraStateChanged + //state change will be handled by CamObserver::CameraStateChanged > Core::onCameraChanged > Cam::onChanged } void Cam::close() { + if(_state != opened) + return error("cant close " + stateToString(_state) + " cam"); + f(_cam->Close(),"close cam #"+_id); - //state change will be handled by CamObserver::CameraStateChanged + //state change will be handled by CamObserver::CameraStateChanged > Core::onCameraChanged > Cam::onChanged } /* Does: @@ -99,6 +137,9 @@ void Cam::close() */ void Cam::startRecording(seconds dur) { + if(_state != opened) + return error("cant start recording, when cam is " + stateToString(_state)); + try { FeaturePtr pFeature; @@ -154,6 +195,9 @@ void Cam::startRecording(minutes dur) */ void Cam::stopRecording() { + if(_state != recording) + return error("cant stop recording, when cam is " + stateToString(_state)); + _timer->stop(); FeaturePtr pFeature; @@ -176,7 +220,10 @@ void Cam::stopRecording() // id,name,model,serial,interfaceID,state QString Cam::info() { - QString camInfo; + QString camInfo = _name + DELIM + _ip + DELIM; + if( state() == Cam::disconnected ) + return camInfo + "disconnected"; + try { std::string str; @@ -224,18 +271,29 @@ QString Cam::stateToString(const State& state) } } -void Cam::toggleOpenClose() +void Cam::onChanged(UpdateTriggerType type) { - // qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << stateToString(_state); - if( _state == opened ) - _state = closed; - else if ( _state == closed ) - _state = opened; - else - error("toggleOpenClose: cam state is neither closed nor opened"); -} - -void Cam::onCameraDisconnected() -{ - _state = disconnected; + switch (type) + { + case UpdateTriggerType::UpdateTriggerPluggedIn: + IPrinter::info(name()+" connected"); + setState(closed); + //_cam ptr set in core + break; + case UpdateTriggerType::UpdateTriggerPluggedOut: + IPrinter::info(name()+" disconnected"); + setState(disconnected); + _cam.reset(); + break; + case UpdateTriggerType::UpdateTriggerOpenStateChanged: + + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << "state changed" << stateToString(_state); + if( _state == opened ) + _state = closed; + else if ( _state == closed ) + _state = opened; + break; + default: + error("onChanged: unknown trigger type"); + } } diff --git a/src/cam.h b/src/cam.h index 6268817df6c499312be09f276e34afaf796ef14e..64698ecd91e190c61e2e11afb00a3b5230a57b1e 100644 --- a/src/cam.h +++ b/src/cam.h @@ -15,6 +15,7 @@ using VmbCPP::CameraPtr; using VmbCPP::FramePtr; using VmbCPP::FeaturePtr; using VmbCPP::FramePtrVector; +using VmbCPP::UpdateTriggerType; using std::chrono::minutes; using std::chrono::seconds; @@ -37,26 +38,31 @@ public: }; // const QString& name, const int& nThreads - Cam(CameraPtr pCamera); Cam(QString name, QString ip); - Cam(const Cam&); + // Cam(CameraPtr pCamera); + // Cam(const Cam&); ~Cam(); QString id(); + QString name() const; + QString ip() const; + State state() const; + void setState(const State&); + static QString stateToString(const State&); - void toggleOpenClose(); + void onChanged(UpdateTriggerType); void open(); void close(); void startRecording(minutes dur); void startRecording(seconds dur); //can use literals "1s, 1min" QString info(); - inline CameraPtr getCameraPtr() const { return _cam; } + inline CameraPtr getCameraPtr() { return _cam; } + inline void setCameraPtr( CameraPtr pCamera ) { _cam = pCamera; } public slots: void stopRecording(); - void onCameraDisconnected(); private: CameraPtr _cam; diff --git a/src/camobserver.cpp b/src/camobserver.cpp index 125cdc368ce1dfbc92a5da5e781aec0a4fb29363..8ac90563d1f3641b77b98df4816fa42951225067 100644 --- a/src/camobserver.cpp +++ b/src/camobserver.cpp @@ -7,16 +7,8 @@ using namespace VmbCPP; -void CamObserver::CameraListChanged(CameraPtr pCam, UpdateTriggerType reason) +void CamObserver::CameraListChanged(CameraPtr pCam, UpdateTriggerType type) { - if( UpdateTriggerPluggedIn == reason || UpdateTriggerPluggedOut == reason ) - { - // qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; - emit cameraListChanged(); - } - else // UpdateTriggerOpenStateChanged - { - emit cameraStateChanged(pCam); - // qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; - } + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__; + emit cameraChanged(pCam,type); } diff --git a/src/camobserver.h b/src/camobserver.h index b0e4065390576c12ae8d67b629b19955a1da22c2..ee401e29681a0ae7328bbdc783072b14db66e550 100644 --- a/src/camobserver.h +++ b/src/camobserver.h @@ -12,11 +12,13 @@ class CamObserver : public QObject, public ICameraListObserver Q_OBJECT signals: - void cameraListChanged(); - void cameraStateChanged(CameraPtr); + void cameraChanged(CameraPtr, UpdateTriggerType); public: void CameraListChanged(CameraPtr, UpdateTriggerType); + + // virtual ~CamObserver() { qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; } + }; } diff --git a/src/cmd/console.cpp b/src/cmd/console.cpp index e1ccf04202872aa3f44eff8c3f363fc2cd8c5ad6..1a8dfcb340a32a199ac7c6162d1f16d506289b46 100644 --- a/src/cmd/console.cpp +++ b/src/cmd/console.cpp @@ -91,11 +91,12 @@ void Console::printHelp() << "h: print this help" << "1-9: select camera" << "d: change duration of recording" - << "c: close current camera" << "o: open current camera" + << "c: close current camera" << "r: start recording" - << "t: stop recording" + << "s: stop recording" << "l: list available cameras" + << "k: deteKt cameras" << "v: print versions" << "q: quit" // XXX add new func @@ -137,10 +138,6 @@ void Controller::onKeyPressed(const QChar& key) switch (key.unicode()) { // XXX add new func - case 'h': - console->printHelp(); - break; - case 'd': console->print("Enter duration in seconds: "); getDur = true; @@ -158,11 +155,15 @@ void Controller::onKeyPressed(const QChar& key) emit listCams(); break; + case 'k': + emit detectCams(); + break; + case 'r': emit startRecording(); break; - case 't': + case 's': emit stopRecording(); break; @@ -173,6 +174,10 @@ void Controller::onKeyPressed(const QChar& key) case 'q': qApp->quit(); break; + + default: + console->printHelp(); + break; } } diff --git a/src/cmd/console.h b/src/cmd/console.h index 8ee9c7e1b63b6a1a5d9952c9533dad12b4574e7e..bb680ab637f7704307101e9e53b2318a78a19d32 100644 --- a/src/cmd/console.h +++ b/src/cmd/console.h @@ -60,6 +60,7 @@ class Controller : public QObject // to core void listCams(); + void detectCams(); void openCam(); void closeCam(); void cam(int); diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp index 882b7dfb3db6a2d137d555f35bccebcfa4cec498..5c4c5aa64b4e3bdc146794a23b124d9db51fc5b6 100644 --- a/src/cmd/main.cpp +++ b/src/cmd/main.cpp @@ -25,6 +25,7 @@ int main(int argc, char *argv[]) //ui (controller) -> vmb (core) QObject::connect(&controller, &Controller::listCams, &core, &Core::listCams); + QObject::connect(&controller, &Controller::detectCams, &core, &Core::detectCams); QObject::connect(&controller, &Controller::openCam, &core, &Core::openCam); QObject::connect(&controller, &Controller::closeCam, &core, &Core::closeCam); QObject::connect(&controller, &Controller::cam, &core, &Core::cam); diff --git a/src/core.cpp b/src/core.cpp index c7f60ed5c285372f88cef9f10785ae5e41445485..2bee444774ddd2e2a5abc32864fb65a7bbeb39d1 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -6,6 +6,7 @@ #include <chrono> #include <iostream> +#include <list> #include <vector> #include <VmbC/VmbCommonTypes.h> @@ -17,14 +18,14 @@ #include <QThread> #include <QTimer> - using namespace VmbCPP; -using namespace std::chrono_literals; //seconds, minutes, hours +using namespace std::chrono_literals; //ms, s, m, h Core::Core() : IPrinter(), _sys( VmbSystem::GetInstance() ), // create and get Vimba singleton - _cameras( CamPtrVector() ), - _recDuration( 6s ) //default + // _cameras( CamPtrVector() ), + _recDuration( 6s ), //default + _camObserver( new CamObserver ) { QTimer::singleShot(0, this, SLOT(init())); //delayed init to allow connections to be established -> print/error signals! } @@ -36,24 +37,22 @@ void Core::init() print("threads",QThread::idealThreadCount()); - auto camObserver = new CamObserver(); - connect( camObserver, SIGNAL(cameraListChanged()), this, SLOT(listCams()) ); //listcams calls updateCams! - connect( camObserver, SIGNAL(cameraStateChanged(CameraPtr)), this, SLOT(toggleCamState(CameraPtr)) ); // - f(_sys.RegisterCameraListObserver(ICameraListObserverPtr(camObserver)), "register cam observer"); + f(_sys.RegisterCameraListObserver(ICameraListObserverPtr(_camObserver)), "register cam observer"); + connect( _camObserver, SIGNAL(cameraChanged(CameraPtr,UpdateTriggerType)), this, SLOT(onCameraChanged(CameraPtr,UpdateTriggerType)) ); //listcams calls updateCams! //parse config file QList<QPair<QString, QString>> parsedCameras; parseConfig(configFile(), parsedCameras); - print("parsed cams:"); + + //add to cam list for ( auto cam : parsedCameras ) { - print({cam.first,cam.second}); + auto pcam = std::make_shared<Cam>(cam.first,cam.second); + _cameras.push_back(pcam); } - -//XXX - //ping each cam and if its exists create camPtr + detectCams(); // listCams(); } @@ -61,89 +60,41 @@ void Core::init() Core::~Core() { qDebug() << __FUNCTION__ << "():" << __LINE__; - - _sys.Shutdown(); + _sys.Shutdown(); // will delete camObserver } // update & sync camera vectors -void Core::updateCameras() +void Core::detectCams() { - // CameraPtrVector vmbCameras; - // if ( f(_sys.GetCameras( vmbCameras ), "update cameras") ) - // return; - -//XXX - // if( VmbErrorSuccess == _sys.GetCameraByID( "172.18.227.211", VmbAccessModeFull, camera ) ) - // { - // std::cout << "Camera opened" << std::endl; - // } - - // if( (int)vmbCameras.size() != ncam() ) //update number of cameras - // error(QString("Expected %1 cams!").arg(ncam()),errLessCamsThanExpected); //XXX warning - - // // vector< shared_ptr<Camera> > vmbCameras - // // vector< shared_ptr<Cam> > _cameras - - // // Add new cameras - // for (const auto& vcam : vmbCameras) - // { - // bool found = false; - // for (const auto& cam : _cameras) - // { - // if (cam->getCameraPtr() == vcam) - // { - // found = true; - // break; - // } - // } - // if (!found) - // { - // _cameras.push_back(std::make_shared<Cam>(vcam)); //create Cam() from CameraPtr vcam - // print(QString("cam connected: %1").arg(_cameras.back()->id())); - // } - // } - - // // Remove cameras that are no longer present - // auto it = _cameras.begin(); - // while (it != _cameras.end()) - // { - // // qDebug() << "check " << (*it)->id(); - - // bool found = false; - // for (const auto& vcam : vmbCameras) - // { - // if ((*it)->getCameraPtr() == vcam) - // { - // found = true; - // ++it; - // break; - // } - // } - - // if (!found) - // { - // qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << " !!! "; - // print({"cam disconnected",(*it)->id()}); - // it = _cameras.erase(it); - // } - // } -} // now ~Camera() should be called on removed cams. >> triggers camObserver - -void Core::toggleCamState(CameraPtr vcam) + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; + for ( auto cam : _cameras ) + { + if( cam->state() == Cam::disconnected ) + { + CameraPtr pcam; + if( VmbErrorSuccess == _sys.GetCameraByID( cam->ip().toStdString(), VmbAccessModeFull, pcam ) ) + { + cam->setCameraPtr(pcam); //triggers camobserver changed signal > set state closed + } + } + } +} + +void Core::onCameraChanged(CameraPtr vcam, UpdateTriggerType type) { for (const auto& cam : _cameras) if (cam->getCameraPtr() == vcam) - return cam->toggleOpenClose(); + cam->onChanged(type); + + listCams(); } + // update + print camlist void Core::listCams() { - updateCameras(); - print("cams",_cameras.size()); - + // qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; QStringList allCamInfo; - auto idx=0; for ( auto camera : _cameras ) { QString camInfo; @@ -151,7 +102,6 @@ void Core::listCams() camInfo += " * "; else camInfo += " "; - camInfo += "Cam" + QString::number(++idx) + ": "; camInfo += camera->info(); allCamInfo << camInfo; @@ -165,16 +115,19 @@ void Core::listCams() void Core::openCam() { - if( cam() ) - cam()->open(); + if( !cam() ) + return; + + cam()->open(); } void Core::closeCam() { - if( cam() ) - cam()->close(); -} + if( !cam() ) + return; + cam()->close(); +} /* current camera getter + setter @@ -185,11 +138,13 @@ CamPtr Core::cam(const unsigned long &idx) { static unsigned long curIdx = 0; if( idx != -1UL ) + { curIdx = idx; + listCams(); // avoid endless loop + } try { - // print("set cam",idx+1); return _cameras.at(curIdx); } catch (const std::out_of_range& oor) diff --git a/src/core.h b/src/core.h index c7729e3d69f5eeb42478ac813cba363871eaa077..239c100c87f8c6b96ec7f6fe948460f8ea0fe6da 100644 --- a/src/core.h +++ b/src/core.h @@ -1,6 +1,8 @@ #pragma once +#include "VmbCPP/VmbCPPCommon.h" #include "cam.h" +#include "camobserver.h" #include "iprinter.h" #include <QObject> @@ -10,6 +12,8 @@ namespace VmbCPP { class VmbSystem; } using VmbCPP::VmbSystem; +using VmbCPP::CamObserver; +using VmbCPP::UpdateTriggerType; using std::chrono::seconds; class Core : public IPrinter @@ -23,7 +27,8 @@ public: public slots: void listCams(); - void toggleCamState(CameraPtr); + void detectCams(); + void onCameraChanged(CameraPtr,UpdateTriggerType); void openCam(); void closeCam(); // XXX add new func @@ -38,9 +43,10 @@ private slots: void init(); private: - void updateCameras(); VmbSystem& _sys; CamPtrVector _cameras; seconds _recDuration; + CamObserver* _camObserver; + }; diff --git a/src/utils.cpp b/src/utils.cpp index eb98755ee9e316c7dc9d7b4a738214c57720490a..8c939d927153a5bb5425389c9888eed4fbfbefee 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -193,7 +193,7 @@ QString configFile(QString filename) static QString _filename; if( _filename.isEmpty() ) { - _filename = filename.isEmpty() ? QCoreApplication::applicationDirPath() + "/cams.json" : filename; + _filename = filename.isEmpty() ? QCoreApplication::applicationDirPath() + "/test.json" : filename; } return _filename; } diff --git a/vimbax/api/include/VmbCPP/VmbSystem.hpp b/vimbax/api/include/VmbCPP/VmbSystem.hpp index 9d791cd0ef37c72e4a6099d08a429b286b232955..69b50fe80807ba986a0d62a9ce6fd0dc46163754 100644 --- a/vimbax/api/include/VmbCPP/VmbSystem.hpp +++ b/vimbax/api/include/VmbCPP/VmbSystem.hpp @@ -170,8 +170,9 @@ inline typename std::enable_if<CStringLikeTraits<T>::IsCStringLike, VmbErrorType return GetTransportLayerByID(CStringLikeTraits<T>::ToString(id), pTransportLayer); } +//XXX added [[gnu::unused]] to get rid of unused warning template<class IdType> -inline typename std::enable_if<CStringLikeTraits<IdType>::IsCStringLike, VmbErrorType>::type VmbSystem::GetCameraByID(const IdType& id, VmbAccessModeType eAccessMode, CameraPtr& pCamera) +inline typename std::enable_if<CStringLikeTraits<IdType>::IsCStringLike, VmbErrorType>::type VmbSystem::GetCameraByID(const IdType& id, [[gnu::unused]] VmbAccessModeType eAccessMode, CameraPtr& pCamera) { static_assert(std::is_same<char const*, decltype(CStringLikeTraits<IdType>::ToString(id))>::value, "CStringLikeTraits<IdType>::ToString(const IdType&) does not return char const*");