Impact Acquire SDK C++
ContinuousCaptureAllDevices.linux.cpp

The ContinuousCaptureAllDevices.linux program is based on the ContinuousCapture.linux.cpp example. It will try to open every device detected in the system and will display a live image with using the current settings stored for the individual device. Each live image will be displayed in a separate window.

Note
This is a Linux version of ContinuousCaptureAllDevices.cpp only needed when working on a Linux system with a non C++11 capable compiler (e.g. gcc smaller than version 4.8. However please note that Impact Acquire these days is built using gcc 5.5.0 thus using an older compiler for building applications will most likely not result in working binaries!). For a detailed description please have a look on the modern version of this example. Even though the used C++ code is slightly different the general idea of the example is the same!
Source code
//
// @description: Example applications for Impact Acquire
// @copyright: Copyright (C) 2005 - 2023 Balluff GmbH
// @authors: APIs and drivers development team at Balluff GmbH
// @initial date: 2005-03-15
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,i
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
#if !defined(linux) && !defined(__linux) && !defined(__linux__) && !defined(__APPLE__)
# error Sorry! Code for Unix flavoured operating systems only!
#endif // #if !defined(linux) && !defined(__linux) && !defined(__linux__) && !defined(__APPLE__)
#include <stdio.h>
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <errno.h>
#include <apps/Common/exampleHelper.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>
using namespace std;
using namespace mvIMPACT::acquire;
#define PRESS_A_KEY \
getchar();
//-----------------------------------------------------------------------------
class ThreadParameter
//-----------------------------------------------------------------------------
{
Device* m_pDev;
volatile bool m_boTerminateThread;
public:
ThreadParameter( Device* pDev ) : m_pDev( pDev ), m_boTerminateThread( false ) {}
Device* device( void ) const
{
return m_pDev;
}
bool terminated( void ) const
{
return m_boTerminateThread;
}
void terminateThread( void )
{
m_boTerminateThread = true;
}
};
//-----------------------------------------------------------------------------
static unsigned int thread_func( void* pData )
//-----------------------------------------------------------------------------
{
ThreadParameter* pThreadParameter = reinterpret_cast<ThreadParameter*>( pData );
unsigned int cnt = 0;
try
{
pThreadParameter->device()->open();
}
catch( const ImpactAcquireException& e )
{
// this e.g. might happen if the same device is already opened in another process...
cout << "An error occurred while opening the device " << pThreadParameter->device()->serial.read()
<< "(error code: " << e.getErrorCode() << "(" << e.getErrorCodeAsString() << ")). Terminating thread." << endl
<< "Press [ENTER] to end the application..."
<< endl;
PRESS_A_KEY
return 0;
}
// establish access to the statistic properties
Statistics statistics( pThreadParameter->device() );
// create an interface to the device found
FunctionInterface fi( pThreadParameter->device() );
// pre-fill the capture queue. There can be more than 1 queue for some devices, but for this sample
// we will work with the default capture queue. If a device supports more than one capture or result
// queue, this will be stated in the manual. If nothing is mentioned about it, the device supports one
// queue only. Request as many images as possible. If there are no more free requests 'DEV_NO_FREE_REQUEST_AVAILABLE'
// will be returned by the driver.
int result = DMR_NO_ERROR;
SystemSettings ss( pThreadParameter->device() );
const int REQUEST_COUNT = ss.requestCount.read();
for( int i = 0; i < REQUEST_COUNT; i++ )
{
result = fi.imageRequestSingle();
if( result != DMR_NO_ERROR )
{
cout << "Error while filling the request queue: " << ImpactAcquireException::getErrorCodeAsString( result ) << endl;
}
}
// run thread loop
const Request* pRequest = 0;
const unsigned int timeout_ms = 8000; // USB 1.1 on an embedded system needs a large timeout for the first image
int requestNr = INVALID_ID;
// This next comment is valid once we have a display:
// we always have to keep at least 2 images as the display module might want to repaint the image, thus we
// can't free it unless we have a assigned the display to a new buffer.
int lastRequestNr = INVALID_ID;
while( !pThreadParameter->terminated() )
{
// wait for results from the default capture queue
requestNr = fi.imageRequestWaitFor( timeout_ms );
if( fi.isRequestNrValid( requestNr ) )
{
pRequest = fi.getRequest( requestNr );
if( pRequest->isOK() )
{
++cnt;
// here we can display some statistical information every 100th image
if( cnt % 100 == 0 )
{
cout << "Info from " << pThreadParameter->device()->serial.read()
<< ": " << statistics.framesPerSecond.name() << ": " << statistics.framesPerSecond.readS()
<< ", " << statistics.errorCount.name() << ": " << statistics.errorCount.readS()
<< ", " << statistics.captureTime_s.name() << ": " << statistics.captureTime_s.readS() << endl;
}
}
else
{
cout << "Error: " << pRequest->requestResult.readS() << endl;
}
if( fi.isRequestNrValid( lastRequestNr ) )
{
// this image has been displayed thus the buffer is no longer needed...
fi.imageRequestUnlock( lastRequestNr );
}
lastRequestNr = requestNr;
// send a new image request into the capture queue
fi.imageRequestSingle();
}
else
{
// If the error code is -2119(DEV_WAIT_FOR_REQUEST_FAILED), the documentation will provide
// additional information under TDMR_ERROR in the interface reference (
cout << "imageRequestWaitFor failed (" << requestNr << ", " << ImpactAcquireException::getErrorCodeAsString( requestNr ) << ", device " << pThreadParameter->device()->serial.read() << ")"
<< ", timeout value too small?" << endl;
}
}
// free the last potentially locked request
if( fi.isRequestNrValid( requestNr ) )
{
fi.imageRequestUnlock( requestNr );
}
// clear all queues
fi.imageRequestReset( 0, 0 );
return 0;
}
//-----------------------------------------------------------------------------
static void* liveThread( void* pData )
//-----------------------------------------------------------------------------
{
thread_func( pData );
return NULL;
}
//-----------------------------------------------------------------------------
int main( void )
//-----------------------------------------------------------------------------
{
DeviceManager devMgr;
const unsigned int devCnt = devMgr.deviceCount();
if( devCnt == 0 )
{
cout << "No " << PRODUCT_NAME << " compliant device found! Unable to continue!" << endl;
return 1;
}
pthread_t* pHandles = new pthread_t[devCnt];
pthread_attr_t* pAttrs = new pthread_attr_t[devCnt];
// store all device infos in a vector
// and start the execution of a 'live' thread for each device.
vector<ThreadParameter*> threadParams;
for( unsigned int i = 0; i < devCnt; i++ )
{
threadParams.push_back( new ThreadParameter( devMgr[i] ) );
cout << devMgr[i]->family.read() << "(" << devMgr[i]->serial.read() << ")" << endl;
}
// start live threads
for( unsigned int j = 0; j < devCnt; j++ )
{
pthread_attr_init( &pAttrs[j] );
// you can set the stack size like this: pthread_attr_setstacksize (&pAttrs[j], 1024*1024);
pthread_create( &pHandles[j], &pAttrs[j], liveThread, ( void* )threadParams[j] );
}
// now all threads will start running...
cout << "Press return to end the acquisition( the initialisation of the devices might take some time )" << endl;
PRESS_A_KEY
// stop all threads again
cout << "Terminating live threads..." << endl;
size_t vSize = threadParams.size();
for( unsigned int k = 0; k < vSize; k++ )
{
cout << "Terminating thread " << k << "." << endl;
threadParams[k]->terminateThread();
}
// wait until each live thread has terminated.
for( unsigned int j = 0; j < devCnt; j++ )
{
cout << "Waiting for thread " << j << " to terminate." << endl;
pthread_join( pHandles[j], NULL );
}
cout << "All capture threads terminated." << endl;
// free resources
for( unsigned int l = 0; l < vSize; l++ )
{
delete threadParams[l];
cout << "thread parameter " << l << " removed." << endl;
}
delete [] pHandles;
cout << "All thread handles removed." << endl;
delete [] pAttrs;
cout << "All thread atributes removed." << endl;
return 0;
}
Grants access to devices that can be operated by this software interface.
Definition mvIMPACT_acquire.h:7159
unsigned int deviceCount(void) const
Returns the number of devices currently present in the system.
Definition mvIMPACT_acquire.h:7388
This class and its functions represent an actual device detected by this interface in the current sys...
Definition mvIMPACT_acquire.h:6118
The function interface to devices supported by this interface.
Definition mvIMPACT_acquire.h:10746
A base class for exceptions generated by Impact Acquire.
Definition mvIMPACT_acquire.h:256
std::string getErrorCodeAsString(void) const
Returns a string representation of the error associated with the exception.
Definition mvIMPACT_acquire.h:288
int getErrorCode(void) const
Returns a unique numerical representation for this error.
Definition mvIMPACT_acquire.h:275
std::string readS(int index=0, const std::string &format="") const
Reads data from this property as a string.
Definition mvIMPACT_acquire.h:3340
Contains information about a captured buffer.
Definition mvIMPACT_acquire.h:8628
bool isOK(void) const
Convenience function to check if a request has been processed successfully.
Definition mvIMPACT_acquire.h:9462
PropertyIRequestResult requestResult
An enumerated integer property (read-only) defining the result of this request.
Definition mvIMPACT_acquire.h:9768
Contains basic statistical information.
Definition mvIMPACT_acquire.h:14497
A base class for accessing settings that control the overall behaviour of a device driver.
Definition mvIMPACT_acquire.h:14706
const int INVALID_ID
A constant to check for an invalid ID returned from the property handling module.
Definition mvPropHandlingDatatypes.h:62
@ DMR_NO_ERROR
The function call was executed successfully.
Definition mvDriverBaseEnums.h:2603
This namespace contains classes and functions belonging to the image acquisition module of this SDK.
Definition mvCommonDataTypes.h:34