#include "backend.hpp"
#include "QDebug"
#include <cvb/data_type.hpp>
#include <cvb/gevserver/node.hpp>
#include <cvb/gevserver/node_map.hpp>
#include <cvb/gevserver/server.hpp>
#include <cvb/gevserver/stream.hpp>
#include <cvb/size_2d.hpp>
#include <cvb/device_factory.hpp>
#include <cvb/image.hpp>
#include <cvb/ui/image_view_item.hpp>
BackEnd::BackEnd(QQuickView *view, QObject *parent) : QObject(parent), view_{view}
{
qRegisterMetaType<QWindow::Visibility>();
hasRingBuffer_ = !!device_->Stream()->RingBuffer();
if (hasRingBuffer_)
device_->Stream()->RingBuffer()->SetLockMode(Cvb::Driver::RingBufferLockMode::On);
streamHandler_->Create(device_->Stream());
context_ = view->rootContext();
context_->setContextProperty("mainImage", &imageController_);
device_->Stream()->GetSnapshot();
imageController_.Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
}
BackEnd::~BackEnd()
{
if (acqThread_)
StopAcq();
server_->Stop();
if (device_->Stream()->IsRunning())
device_->Stream()->Stop();
}
void BackEnd::StartServer(const int &addressIndex, const int &driverTypeIndex)
{
qDebug() << "Starting server on address index " << addressIndex << " and driver type index " << driverTypeIndex;
if (startInProgress_)
return;
startInProgress_ = true;
try
{
if (!acqStarted_)
{
StopGrab();
device_->DeviceImage()->ColorModel(),
device_->DeviceImage()->Plane(0).DataType(),
AddGenICamFeatures();
server_->SetUserVersion(CVB_LIT("_C++GevServer"));
if (hasRingBuffer_)
server_->Stream()->SetResendBuffersCount(2);
else
server_->Stream()->SetResendBuffersCount(0);
auto address = iFaces_.at(addressIndex).IPAddress();
server_->Start(address);
if (!acqThread_)
StartAcq();
acqStarted_ = true;
qDebug() << "Started server";
}
else
{
if (acqThread_)
StopAcq();
server_->Stop();
acqStarted_ = false;
qDebug() << "Stopped server";
}
}
catch (...)
{
}
startInProgress_ = false;
}
void BackEnd::operator()() noexcept
{
std::unique_lock<std::mutex> guard(mtx_);
device_->Stream()->Start();
while (!stopAcq_)
{
if (grabSwitchSwitched_)
{
if (hasRingBuffer_)
{
}
else
device_->Stream()->Wait();
}
!snapSend_)
{
try
{
if (img.Status == Cvb::WaitStatus::Ok)
{
if (hasRingBuffer_)
{
bufferIndex_ = img.Image->BufferIndex();
imgMap_[bufferIndex_] = img.Image;
server_->Stream()->Send(img.Image, [
this](
const Cvb::ImagePtr &) {
imgMap_[bufferIndex_]->Unlock();
qDebug() << "unlocked buffer index " << std::to_string(bufferIndex_).c_str();
});
}
else
server_->Stream()->Send(*img.Image.get());
}
}
catch (...)
{
}
}
}
device_->Stream()->Stop();
}
void BackEnd::SwitchGrab(const bool &switched)
{
grabSwitchSwitched_ = switched;
if (grabSwitchSwitched_)
{
if (!acqThread_)
StartAcq();
}
else
{
if (acqThread_)
StopAcq();
}
qDebug() << "Grab switch switched to" << switched;
}
QVariantList BackEnd::ConnectionList()
{
iFaces_.clear();
QVariantList list;
list.clear();
for (auto const &iFace : iFaces_)
{
std::stringstream ss;
ss << iFace.IPAddress() << " (" << iFace.IPv4Mask() << ")";
list.append(std::string(ss.str()).c_str());
}
return list;
}
void BackEnd::LoadDevice(const QString &path)
{
qDebug() << "Loading new device on path " << path;
StopGrab();
try
{
device_.reset();
device_ = tmpDevice;
device_->Stream()->GetSnapshot();
hasRingBuffer_ = !!device_->Stream()->RingBuffer();
if (hasRingBuffer_)
device_->Stream()->RingBuffer()->SetLockMode(Cvb::Driver::RingBufferLockMode::On);
imageController_.Refresh(device_->DeviceImage(), Cvb::UI::AutoRefresh::On);
}
catch (...)
{
qDebug() << "Failed to load new device";
}
}
void BackEnd::SaveImg(const QString &path)
{
qDebug() << "Saving new file on path " << path;
device_->DeviceImage()->Save(CVB_LIT(path.toLatin1().toStdString().c_str()));
}
void BackEnd::BtnSnap()
{
qDebug() << "Snap image";
StopGrab();
device_->Stream()->GetSnapshot();
}
void BackEnd::SwitchEnableSnapSend(const bool &switched)
{
snapSend_ = switched;
if (snapSend_)
StopAcq();
else
StartAcq();
qDebug() << "Enable snap switch switched to" << switched;
}
void BackEnd::BtnSnapSend()
{
if (server_->State() == Cvb::GevServer::State::AcquisitionEnabled)
{
qDebug() << "Snap send";
try
{
auto img = device_->Stream()->GetSnapshot();
if (img.Status == Cvb::WaitStatus::Ok)
if (hasRingBuffer_)
{
server_->Stream()->Send(img.Image, nullptr);
}
else
{
auto img2 = device_->Stream()->GetSnapshot();
if (img2.Status == Cvb::WaitStatus::Ok)
server_->Stream()->Send(*img2.Image);
}
}
catch (...)
{
}
}
else
qDebug() << "Acquisition not enabled on server";
}
void BackEnd::StopGrab()
{
if (device_->Stream()->IsRunning() && grabSwitchSwitched_)
{
QObject *box = view_->findChild<QObject *>("switchGrab", Qt::FindChildrenRecursively);
if (box)
box->setProperty("checked", false);
}
if (device_->Stream()->IsRunning() && acqStarted_)
{
StopAcq();
}
}
{
switch (windowStateRegNode_->Value())
{
case 0:
view_->showMinimized();
break;
case 1:
view_->showNormal();
break;
case 2:
view_->showMaximized();
default:
throw std::runtime_error("Invalid window state value");
break;
}
}
void BackEnd::AddGenICamFeatures()
{
server_->NodeMap()->AddNode(catNode);
catNode->SetDisplayName(CVB_LIT("Custom Features"));
catNode->SetToolTip(CVB_LIT("Contains all application defined features."));
auto rootNode = server_->NodeMap()->Node(CVB_LIT("Root"));
rootNode->Add(catNode, Cvb::GevServer::NodeList::Child);
server_->NodeMap()->AddNode(windowStateRegNode_);
windowStateRegNode_->SetVisibility(Cvb::GenApi::Visibility::Invisible);
windowStateRegNode_->SetCacheMode(Cvb::GenApi::CacheMode::NoCache);
windowStateRegNode_->SetPollingTime<float, std::ratio<1, 1000>>(
std::chrono::duration<float, std::ratio<1, 1000>>(333));
windowStateRegNode_->SetValue(1);
windowStateRegNode_->RegisterEventWrittenUpdated(
server_->NodeMap()->AddNode(enumerationNode);
enumerationNode->SetDisplayName(CVB_LIT("Window State"));
enumerationNode->SetToolTip(CVB_LIT("Current window state of server application."));
minimized->SetNumericValue(0);
enumerationNode->Add(minimized, Cvb::GevServer::NodeList::Child);
normalNode->SetNumericValue(1);
enumerationNode->Add(normalNode, Cvb::GevServer::NodeList::Child);
maxNode->SetNumericValue(2);
enumerationNode->Add(maxNode, Cvb::GevServer::NodeList::Child);
catNode->Add(enumerationNode, Cvb::GevServer::NodeList::Child);
}
static std::shared_ptr< T > Open(const String &provider, AcquisitionStack acquisitionStack=AcquisitionStack::PreferVin)
static CategoryNodePtr Create(const String &name, const GevServer::Namespace &nameSpace)
static EnumEntryNodePtr Create(const String &name, const GevServer::Namespace &nameSpace)
static EnumerationNodePtr Create(const String &name, const GevServer::Namespace &nameSpace)
static Int32RegNodePtr Create(const String &name, const GevServer::Namespace &nameSpace, const std::int64_t &address)
static ServerPtr CreateWithConstSize(Size2D< int > size, PfncFormat pixelFormat, GevServer::DriverType driverType=GevServer::DriverType::Auto)
Image(Size2D< int > size, int numPlanes=1, DataType dataType=DataType::Int8BppUnsigned())
std::shared_ptr< IntegerBaseNode > IntegerBaseNodePtr
std::shared_ptr< Server > ServerPtr
std::shared_ptr< Image > ImagePtr
static std::vector< LogicalNetworkInterface > GetAllAvailable()