From 7c3aa759dd51c4396902034b91bb2c8cbb3ac206 Mon Sep 17 00:00:00 2001 From: am0ebe <am0ebe@gmx.de> Date: Mon, 19 Feb 2024 16:36:21 +0100 Subject: [PATCH] 1. add camobserver to listen when cam is plugged/unplugged 2. rearrange files in the project (adjust includes/.pro) --- obj/recorder-cmd.pro | 18 +++-- src/camobserver.cpp | 24 ++++++ src/camobserver.h | 22 +++++ src/cmd/console.cpp | 6 +- src/cmd/console.h | 2 +- src/cmd/main.cpp | 11 ++- src/{cmd => }/core.cpp | 134 ++++++++++++++++--------------- src/{cmd => }/core.h | 6 +- src/{cmd => }/frameobserver.cpp | 3 +- src/{cmd => }/frameobserver.h | 0 src/{cmd => }/frameprocessor.cpp | 3 +- src/{cmd => }/frameprocessor.h | 0 src/recorder.cpp | 37 --------- src/simple_streaming.cpp | 82 ------------------- src/utils.cpp | 3 +- src/utils.h | 1 + 16 files changed, 143 insertions(+), 209 deletions(-) create mode 100644 src/camobserver.cpp create mode 100644 src/camobserver.h rename src/{cmd => }/core.cpp (71%) rename src/{cmd => }/core.h (95%) rename src/{cmd => }/frameobserver.cpp (97%) rename src/{cmd => }/frameobserver.h (100%) rename src/{cmd => }/frameprocessor.cpp (94%) rename src/{cmd => }/frameprocessor.h (100%) delete mode 100644 src/recorder.cpp delete mode 100644 src/simple_streaming.cpp diff --git a/obj/recorder-cmd.pro b/obj/recorder-cmd.pro index a7c42f7..2d95e37 100644 --- a/obj/recorder-cmd.pro +++ b/obj/recorder-cmd.pro @@ -6,16 +6,18 @@ CONFIG += c++20 warn_on console SOURCES += \ ../src/cmd/main.cpp \ ../src/cmd/console.cpp \ - ../src/cmd/core.cpp \ - ../src/cmd/frameObserver.cpp \ - ../src/cmd/frameProcessor.cpp \ + ../src/core.cpp \ + ../src/frameobserver.cpp \ + ../src/frameprocessor.cpp \ + ../src/camobserver.cpp \ ../src/utils.cpp HEADERS += \ ../src/cmd/console.h \ - ../src/cmd/core.h \ - ../src/cmd/frameObserver.h \ - ../src/cmd/frameProcessor.h \ + ../src/core.h \ + ../src/frameobserver.h \ + ../src/frameprocessor.h \ + ../src/camobserver.h \ ../src/utils.h DEFINES *= QT_USE_QSTRINGBUILDER #converts + to % when building strings @@ -24,7 +26,7 @@ DEFINES *= QT_USE_QSTRINGBUILDER #converts + to % when building strings CONFIG += link_pkgconfig PKGCONFIG += opencv4 -# Vimba +# VimbaX INCLUDEPATH += ../vimbax/api/include VIMBA_LIB_DIR = ../lib LIBS += -L$${VIMBA_LIB_DIR} -lVmbC -lVmbCPP -Wl,-rpath,\'\$$ORIGIN\' @@ -41,4 +43,4 @@ TARGET = cmd DESTDIR = ../bin QMAKE_CLEAN += .cache/clangd/index/* .qmake.stash $${DESTDIR}/*jpg -#cant rm dir here, so added in project file +#cant rm dir here, so added in sublime-project file diff --git a/src/camobserver.cpp b/src/camobserver.cpp new file mode 100644 index 0000000..7a86566 --- /dev/null +++ b/src/camobserver.cpp @@ -0,0 +1,24 @@ +#include "camobserver.h" + +#include <VmbCPP/Camera.h> +#include <VmbCPP/VmbCPPCommon.h> //enum + +#include <QDebug> + + +using namespace VmbCPP; + +//2D XXX Code to determine the open state +void CamObserver::CameraListChanged(CameraPtr pCam, UpdateTriggerType reason) +{ + if( UpdateTriggerPluggedIn == reason || UpdateTriggerPluggedOut == reason ) + { + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; + emit cameraListChanged(); + } + else // UpdateTriggerOpenStateChanged + { + emit cameraOpenStateChanged(pCam); + qDebug() << __LINE__ << "-" << __PRETTY_FUNCTION__ << ""; + } +} diff --git a/src/camobserver.h b/src/camobserver.h new file mode 100644 index 0000000..1a740b9 --- /dev/null +++ b/src/camobserver.h @@ -0,0 +1,22 @@ +#pragma once + +#include <QObject> +#include <VmbCPP/ICameraListObserver.h> + +namespace VmbCPP +{ + +// observer that reacts on camera list changes +class CamObserver : public QObject, public ICameraListObserver +{ + Q_OBJECT + +signals: + void cameraListChanged(); + void cameraOpenStateChanged(CameraPtr); + +public: + void CameraListChanged(CameraPtr, UpdateTriggerType); +}; + +} diff --git a/src/cmd/console.cpp b/src/cmd/console.cpp index b497cc6..f86bf4d 100644 --- a/src/cmd/console.cpp +++ b/src/cmd/console.cpp @@ -68,8 +68,8 @@ void Console::printHelp() str << "HELP!" << "-------------------------------" << "h: print this help" - << "1-9: select camera" - << "o: open selected camera" + << "1-9: set camera" + << "o: open current camera" // XXX add new func << "r: start recording" << "t: stop recording" @@ -106,7 +106,7 @@ void Controller::keyPress(const QChar& key) qDebug().noquote() << __FUNCTION__ << ": " << key; if ( key.isDigit() ) { - emit selectCam(key.digitValue()-1); + emit setCam(key.digitValue()-1); } else { diff --git a/src/cmd/console.h b/src/cmd/console.h index 1f06a56..8c30a81 100644 --- a/src/cmd/console.h +++ b/src/cmd/console.h @@ -46,7 +46,7 @@ class Controller : public QObject // to core void listCams(); void openCam(); - void selectCam(int); + void setCam(int); void startRecording(); void stopRecording(); diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp index 69f1f11..485267b 100644 --- a/src/cmd/main.cpp +++ b/src/cmd/main.cpp @@ -1,10 +1,9 @@ -#include "../utils.h" #include "console.h" -#include "core.h" -#include "qnamespace.h" +#include "../core.h" +#include "../utils.h" +// #include "qnamespace.h" #include <QCoreApplication> -#include <QCommandLineParser> #include <QTimer> int main(int argc, char *argv[]) @@ -20,7 +19,7 @@ int main(int argc, char *argv[]) //ui (controller) -> vmb (core) QObject::connect(&controller, &Controller::listCams, &core, &Core::listCams); QObject::connect(&controller, &Controller::openCam, &core, &Core::openCam); - QObject::connect(&controller, &Controller::selectCam, &core, &Core::selectCam); + QObject::connect(&controller, &Controller::setCam, &core, &Core::setCam); QObject::connect(&controller, &Controller::startRecording, &core, &Core::startRecording); QObject::connect(&controller, &Controller::stopRecording, &core, &Core::stopRecording); // XXX add new func @@ -35,7 +34,7 @@ int main(int argc, char *argv[]) QTimer::singleShot(0, &controller, SIGNAL(operate())); // QTimer::singleShot(10, controller.console, SLOT(printVersion()), Qt::DirectConnection); // for testing QTimer::singleShot(30, &core, SLOT(listCams())); // for testing - QTimer::singleShot(200, &core, SLOT(openCam())); // for testing + // QTimer::singleShot(200, &core, SLOT(openCam())); // for testing return a.exec(); } diff --git a/src/cmd/core.cpp b/src/core.cpp similarity index 71% rename from src/cmd/core.cpp rename to src/core.cpp index f30bede..c98a194 100644 --- a/src/cmd/core.cpp +++ b/src/core.cpp @@ -1,12 +1,13 @@ #include "core.h" #include "frameobserver.h" -#include "../utils.h" +#include "camobserver.h" +#include "utils.h" #include <iostream> #include <vector> -#include "VmbC/VmbCommonTypes.h" -#include "VmbCPP/SharedPointerDefines.h" +#include <VmbC/VmbCommonTypes.h> +#include <VmbCPP/SharedPointerDefines.h> #include <VmbCPP/VmbCPP.h> #include <VmbCPP/Camera.h> @@ -28,33 +29,20 @@ Core::Core() : // frames(FramePtrVector(QThread::idealThreadCount())), pixelFormat("") { - if ( f(sys.Startup()) ) - { - qDebug() << "Couldn't initialize API"; - exit(VmbErrorApiNotStarted); - } - - qDebug() << "init API :)"; //emitting signals in ctor doesnt Work, cuz their not connected yet - apiStarted = true; - initCams(); + QTimer::singleShot(0, this, SLOT(init())); //delayed init to allow connections to be established } -void Core::initCams() +void Core::init() { - if ( f(sys.GetCameras( cameras ))) - { - qDebug() << "No cameras"; - } - else - { - qDebug().noquote() << QString("found %1 cameras").arg(cameras.size()); - if (cameras.size()) - { - camIdx = 0; //dflt to 1rst - curCam = cameras.at(camIdx); - } - } + if ( f(sys.Startup(), "init API") ) + exit(VmbErrorApiNotStarted); + + apiStarted = true; + + auto camObserver = new CamObserver(); + connect( camObserver, SIGNAL(cameraListChanged()), this, SLOT(listCams()) ); + f(sys.RegisterCameraListObserver(ICameraListObserverPtr(camObserver)), "register cam observer"); } Core::~Core() @@ -67,11 +55,6 @@ Core::~Core() sys.Shutdown(); } -CameraPtr Core::cam() -{ - return cameras.at(camIdx); -} - //2d // need to update open / closed states. //initially cams are closed, right? XXX how to find out? @@ -82,50 +65,61 @@ void Core::listCams() if( !apiStarted ) return; - // id,name,model,serial,interfaceID,state - QStringList allCamInfo; - auto idx=0UL; - for ( auto camera : cameras ) + if ( f(sys.GetCameras( cameras ), "get cameras") ) + return; + + qDebug().noquote() << QString("found %1 camera(s)").arg(cameras.size()); + if (cameras.size()) { - std::string str; - QString curCamInfo; + if( camIdx == -1UL || camIdx >= cameras.size() ) + { + setCam(0); + } - curCamInfo += QString::number(idx+1) + ". "; + // id,name,model,serial,interfaceID,state + QStringList allCamInfo; + auto idx=0UL; + for ( auto camera : cameras ) + { + std::string str; + QString curCamInfo; - if (idx == camIdx ) - curCamInfo += "[*]" + DELIM; - else - curCamInfo += "[ ]" + DELIM; + curCamInfo += QString::number(idx+1) + ". "; + if (idx == camIdx ) + curCamInfo += "[*]" + DELIM; + else + curCamInfo += "[ ]" + DELIM; - if( f((camera->GetID( str )))) continue; - curCamInfo += QString::fromStdString(str) + DELIM; - if( f((camera->GetName( str )))) continue; - curCamInfo += QString::fromStdString(str) + DELIM; + if( f((camera->GetID( str )))) continue; + curCamInfo += QString::fromStdString(str) + DELIM; - if( f((camera->GetModel( str )))) continue; - curCamInfo += QString::fromStdString(str) + DELIM; + if( f((camera->GetName( str )))) continue; + curCamInfo += QString::fromStdString(str) + DELIM; - if( f((camera->GetSerialNumber( str )))) continue; - curCamInfo += QString::fromStdString(str) + DELIM; + if( f((camera->GetModel( str )))) continue; + curCamInfo += QString::fromStdString(str) + DELIM; - if( f((camera->GetInterfaceID( str )))) continue; - curCamInfo += QString::fromStdString(str) + DELIM; + if( f((camera->GetSerialNumber( str )))) continue; + curCamInfo += QString::fromStdString(str) + DELIM; - // curCamInfo += "closed";//xxx + if( f((camera->GetInterfaceID( str )))) continue; + curCamInfo += QString::fromStdString(str) + DELIM; - allCamInfo << curCamInfo; - idx++; - } + // curCamInfo += "closed";//xxx + + allCamInfo << curCamInfo; + idx++; + } - if( !cameras.size()) - emit error(errNoCams); - else - { emitPrint("found Cameras",cameras.size()); emit print(allCamInfo); } + else + { + emit error(errNoCams); + } } bool Core::f(const VmbErrorType& ret, const QString& msg) @@ -184,19 +178,23 @@ bool Core::openCam() return f(curCam->Open( VmbAccessModeFull ),"open cam #"+QString::number(camIdx+1)); } -void Core::selectCam(const int& camIdx) +CameraPtr Core::cam() +{ + return curCam; +} + +void Core::setCam(const int& newCamIdx) { try { - curCam = cameras.at(camIdx); + camIdx = newCamIdx; + curCam = cameras.at(newCamIdx); + emitPrint("set cam",newCamIdx+1); } catch (const std::out_of_range& oor) { emit error(errCamIdx); - return; } - - emitPrint("camSelected",camIdx); } /* Does: @@ -215,6 +213,9 @@ void Core::selectCam(const int& camIdx) */ void Core::startRecording() { + if( !curCam ) + return; + FeaturePtr pFeature; try @@ -259,6 +260,9 @@ void Core::startRecording() */ void Core::stopRecording() { + if( !curCam ) + return; + FeaturePtr pFeature; try { diff --git a/src/cmd/core.h b/src/core.h similarity index 95% rename from src/cmd/core.h rename to src/core.h index d3da7b6..a9a81e6 100644 --- a/src/cmd/core.h +++ b/src/core.h @@ -25,12 +25,15 @@ class Core : public QObject public slots: void listCams(); bool openCam(); - void selectCam(const int &); + void setCam(const int &); CameraPtr cam(); // make getter setter -> rm curCam and camIdx //or make Camera class wrapper void startRecording(); void stopRecording(); + private slots: + void init(); + signals: void print(const QString &); void print(const QStringList&); @@ -44,7 +47,6 @@ class Core : public QObject void emitPrint(const QString&, const VmbInt64_t& v); void emitPrint(const QString&, const std::string& v=""); - void initCams(); void getCamInfo( const CameraPtr & ); bool apiStarted; diff --git a/src/cmd/frameobserver.cpp b/src/frameobserver.cpp similarity index 97% rename from src/cmd/frameobserver.cpp rename to src/frameobserver.cpp index 3d38938..9cfed68 100644 --- a/src/cmd/frameobserver.cpp +++ b/src/frameobserver.cpp @@ -1,11 +1,10 @@ #include "frameobserver.h" #include "frameprocessor.h" -#include "qnamespace.h" -#include "qthread.h" #include <VmbCPP/SharedPointerDefines.h> #include <VmbCPP/Camera.h> +// #include "qnamespace.h" #include <QDebug> #include <QThread> #include <QObject> diff --git a/src/cmd/frameobserver.h b/src/frameobserver.h similarity index 100% rename from src/cmd/frameobserver.h rename to src/frameobserver.h diff --git a/src/cmd/frameprocessor.cpp b/src/frameprocessor.cpp similarity index 94% rename from src/cmd/frameprocessor.cpp rename to src/frameprocessor.cpp index b127422..c07f2fa 100644 --- a/src/cmd/frameprocessor.cpp +++ b/src/frameprocessor.cpp @@ -42,8 +42,7 @@ void FrameProcessor::processFrame() if (pixelFormat != VmbPixelFormatRgb8) { - qWarning() << "Pixel format is not RGB8, 2D: implement convert func ... "; - return; + qWarning() << "⚠️ Pixel format is not RGB8, 2D: implement convert func ... "; } qDebug() << "Frame received: " << width << "x" << height << "px, format: " << pixelFormat << ", timestamp: " << timestamp; diff --git a/src/cmd/frameprocessor.h b/src/frameprocessor.h similarity index 100% rename from src/cmd/frameprocessor.h rename to src/frameprocessor.h diff --git a/src/recorder.cpp b/src/recorder.cpp deleted file mode 100644 index 969881f..0000000 --- a/src/recorder.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include <VmbCPP/VmbCPP.h> - -#include <iostream> -#include <vector> - -#include <opencv2/core.hpp> -#include <opencv2/imgcodecs.hpp> -#include <opencv2/highgui.hpp> - - - -using std::cout; -using std::endl; - -// using namespace VmbCPP; - -// read_and_display_img("/home/sugu/code/c++/opencv_quark/starry_night.png"); //make HOME user independent -// int read_and_display_img( cv::String img_with_path ) -// { -// std::vector<int> vec; -// cv::Mat image; -// image = imread(img_with_path, cv::IMREAD_COLOR); // Read the file -// if( image.empty() ) // Check for invalid input -// { -// cout << "Could not open or find the image" << std::endl ; -// return -1; -// } - -// namedWindow( "Display window", cv::WINDOW_AUTOSIZE ); // Create a window for display. -// imshow( "Display window", image ); // Show our image inside it. -// cv::waitKey(0); // Wait for a keystroke in the window - -// return 0; -// } - - - diff --git a/src/simple_streaming.cpp b/src/simple_streaming.cpp deleted file mode 100644 index cf7d910..0000000 --- a/src/simple_streaming.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "VmbCPP/VimbaCPP.h" -#include "VmbC/VimbaC.h" -#include "VmbCPP/Frame.h" - -namespace VmbCPP { - -// Constructor for the FrameObserver -class FrameObserver::FrameObserver( CameraPtr pCamera ) : IFrameObserver ( pCamera ){} - -// Frame callback notifies about incoming frames -void FrameObserver::FrameReceived ( const FramePtr pFrame ) -{ - - // Send notification to working thread - // Do not apply image processing within this callback ( performance ) - // When the frame has been processed , requeue it - m_pCamera -> QueueFrame ( pFrame ); -} - - -void Vimba::RunExample (void) -{ - VmbSystem &sys = VmbSystem :: GetInstance (); // Create and get Vimba singleton - CameraPtrVector cameras ; // Holds camera handles - CameraPtr camera ; - VmbInt64_t nPLS; // Payload size value - FeaturePtr pFeature ; // Generic feature pointer - FramePtrVector frames (15); // Frame array - - // Start the API , get and open cameras - sys.Startup (); // = VmbErrorSuccess? - sys.GetCameras( cameras ); // = VmbErrorSuccess? - camera = cameras [0]; //iterate over all cams -> auto it = cameras.begin()... (*iter)->GetName( name )==success - camera ->Open( VmbAccessModeFull ); - - // Get the image size for the required buffer - // Allocate memory for frame buffer - // Register frame observer / callback for each frame - // Announce frame to the API - camera -> GetFeatureByName (" PayloadSize ", pFeature ); - pFeature -> GetValue (nPLS ); - for( FramePtrVector :: iterator iter= frames .begin (); frames .end () != iter; ++ iter) - { - (* iter ).reset(new Frame (nPLS)); - (* iter)-> RegisterObserver ( IFrameObserverPtr (new FrameObserver ( camera ))); - camera -> AnnounceFrame (* iter ); - } - - // Start the capture engine (API) - camera -> StartCapture (); - for( FramePtrVector :: iterator iter= frames .begin (); frames .end ()!= iter; ++ iter) - { - // Put frame into the frame queue - camera->QueueFrame (* iter ); - } - - // Start the acquisition engine ( camera ) - camera -> GetFeatureByName (" AcquisitionStart ", pFeature ); - pFeature -> RunCommand (); - - // Program runtime , e.g., Sleep (2000); - - // Stop the acquisition engine ( camera ) - camera -> GetFeatureByName (" AcquisitionStop ", pFeature ); - pFeature -> RunCommand (); - - // Stop the capture engine (API) - // Flush the frame queue - // Revoke all frames from the API - camera -> EndCapture (); - camera -> FlushQueue (); - camera -> RevokeAllFrames (); - for( FramePtrVector :: iterator iter= frames .begin (); frames .end ()!= iter; ++ iter) - { - // Unregister the frame observer / callback - (* iter)-> UnregisterObserver (); - } - - camera ->Close (); - sys.Shutdown (); // Always pair sys. Startup and sys. Shutdown -} -} // namespace VmbCPP diff --git a/src/utils.cpp b/src/utils.cpp index db9f009..5eb357d 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -64,7 +64,8 @@ const QString errorCodeToMessage( VmbError_t err ) // ------------------------------- own errCodes ------------------------------- case errCamIdx: msg += "Camera index out of range."; break; case errNoCams: msg += "no cameras found."; break; - // xx = 12, //!< Unexpected fault in VmbC or driver + case errRegisterCamObserver: msg += "cant register camobserver."; break; + // ... add more } return msg; } diff --git a/src/utils.h b/src/utils.h index cd65a80..84a68a8 100644 --- a/src/utils.h +++ b/src/utils.h @@ -18,6 +18,7 @@ typedef enum camtronErr { errCamIdx = 10, //!< camera index out of range errNoCams = 11, //!< no cameras found + errRegisterCamObserver = 12, //!< cant register camobserver // errUn = 12, //!< Unexpected fault in VmbC or driver } camtronErr; -- GitLab