diff --git a/slsReceiverSoftware/CMakeLists.txt b/slsReceiverSoftware/CMakeLists.txt index 8ff2b1e6bd..4f342e6189 100755 --- a/slsReceiverSoftware/CMakeLists.txt +++ b/slsReceiverSoftware/CMakeLists.txt @@ -138,13 +138,33 @@ if (SLS_USE_RECEIVER_BINARIES) slsProjectWarnings ) - install(TARGETS slsReceiver slsMultiReceiver + add_executable(slsFrameSynchronizer + src/FrameSynchronizerApp.cpp + ) + + set_target_properties(slsFrameSynchronizer PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin + ) + if((CMAKE_BUILD_TYPE STREQUAL "Release") AND SLS_LTO_AVAILABLE) + set_property(TARGET slsFrameSynchronizer PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + endif() + + target_link_libraries(slsFrameSynchronizer + PUBLIC + slsReceiverStatic + pthread + rt + PRIVATE + slsProjectWarnings + ) + + install(TARGETS slsReceiver slsMultiReceiver slsFrameSynchronizer EXPORT "${TARGETS_EXPORT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sls -) + ) endif(SLS_USE_RECEIVER_BINARIES) diff --git a/slsReceiverSoftware/include/sls/Receiver.h b/slsReceiverSoftware/include/sls/Receiver.h index cbeccd29a8..f3389c80ec 100644 --- a/slsReceiverSoftware/include/sls/Receiver.h +++ b/slsReceiverSoftware/include/sls/Receiver.h @@ -41,51 +41,36 @@ class Receiver : private virtual slsDetectorDefs { /** * Start Acquisition Call back (slsMultiReceiver writes data if file write * enabled) if registerCallBackRawDataReady or - * registerCallBackRawDataModifyReady registered, users get data callback - * arguments are: - * - file path - * - file name prefix - * - file index - * - image size in bytes + * registerCallBackRawDataModifyReady registered + * Call back arguments are: + * - startCallbackHeader metadata */ - void registerCallBackStartAcquisition(int (*func)(const std::string &, - const std::string &, - uint64_t, size_t, void *), + void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader, + void *), void *arg); /** * Call back for acquisition finished * callback argument is: - * - total frames caught + * - startCallbackHeader metadata */ - void registerCallBackAcquisitionFinished(void (*func)(uint64_t, void *), - void *arg); + void registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg); /** * Call back for raw data * args to raw data ready callback are: * - sls_receiver_header frame metadata, + * - dataCallbackHeader metadata * - pointer to data - * - image size in bytes + * - image size in bytes. Can be modified to the new size to be + * written/streamed. (only smaller value allowed). */ void registerCallBackRawDataReady(void (*func)(sls_receiver_header &, - char *, size_t, void *), + const dataCallbackHeader, + char *, size_t &, void *), void *arg); - /** - * Call back for raw data (modified) - * args to raw data ready callback are: - * - sls_receiver_header frame metadata, - * - pointer to data - * - revDatasize is the reference of data size in bytes. - * Can be modified to the new size to be written/streamed. (only smaller - * value allowed). - */ - void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header &, - char *, size_t &, - void *), - void *arg); - private: std::unique_ptr tcpipInterface; }; diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 51a4e2bb20..ce87021516 100644 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -54,32 +54,25 @@ std::string ClientInterface::getReceiverVersion() { return APIRECEIVER; } /***callback functions***/ void ClientInterface::registerCallBackStartAcquisition( - int (*func)(const std::string &, const std::string &, uint64_t, size_t, - void *), - void *arg) { + int (*func)(const startCallbackHeader, void *), void *arg) { startAcquisitionCallBack = func; pStartAcquisition = arg; } -void ClientInterface::registerCallBackAcquisitionFinished(void (*func)(uint64_t, - void *), - void *arg) { +void ClientInterface::registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg) { acquisitionFinishedCallBack = func; pAcquisitionFinished = arg; } void ClientInterface::registerCallBackRawDataReady( - void (*func)(sls_receiver_header &, char *, size_t, void *), void *arg) { + void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &, + void *), + void *arg) { rawDataReadyCallBack = func; pRawDataReady = arg; } -void ClientInterface::registerCallBackRawDataModifyReady( - void (*func)(sls_receiver_header &, char *, size_t &, void *), void *arg) { - rawDataModifyReadyCallBack = func; - pRawDataReady = arg; -} - void ClientInterface::startTCPServer() { tcpThreadId = gettid(); LOG(logINFOBLUE) << "Created [ TCP server Tid: " << tcpThreadId << "]"; @@ -477,9 +470,6 @@ void ClientInterface::setDetectorType(detectorType arg) { if (rawDataReadyCallBack != nullptr) impl()->registerCallBackRawDataReady(rawDataReadyCallBack, pRawDataReady); - if (rawDataModifyReadyCallBack != nullptr) - impl()->registerCallBackRawDataModifyReady(rawDataModifyReadyCallBack, - pRawDataReady); impl()->setThreadIds(parentThreadId, tcpThreadId); } diff --git a/slsReceiverSoftware/src/ClientInterface.h b/slsReceiverSoftware/src/ClientInterface.h index b24dfbbbdf..8bde90c641 100644 --- a/slsReceiverSoftware/src/ClientInterface.h +++ b/slsReceiverSoftware/src/ClientInterface.h @@ -34,26 +34,20 @@ class ClientInterface : private virtual slsDetectorDefs { //***callback functions*** /** params: file path, file name, file index, image size */ - void registerCallBackStartAcquisition(int (*func)(const std::string &, - const std::string &, - uint64_t, size_t, void *), + void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader, + void *), void *arg); /** params: total frames caught */ - void registerCallBackAcquisitionFinished(void (*func)(uint64_t, void *), - void *arg); + void registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg); /** params: sls_receiver_header, pointer to data, image size */ void registerCallBackRawDataReady(void (*func)(sls_receiver_header &, - char *, size_t, void *), + const dataCallbackHeader, + char *, size_t &, void *), void *arg); - /** params: sls_receiver_header, pointer to data, reference to image size */ - void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header &, - char *, size_t &, - void *), - void *arg); - private: void startTCPServer(); int functionTable(); @@ -186,15 +180,14 @@ class ClientInterface : private virtual slsDetectorDefs { //***callback parameters*** - int (*startAcquisitionCallBack)(const std::string &, const std::string &, - uint64_t, size_t, void *) = nullptr; + int (*startAcquisitionCallBack)(const startCallbackHeader, + void *) = nullptr; void *pStartAcquisition{nullptr}; - void (*acquisitionFinishedCallBack)(uint64_t, void *) = nullptr; + void (*acquisitionFinishedCallBack)(const endCallbackHeader, + void *) = nullptr; void *pAcquisitionFinished{nullptr}; - void (*rawDataReadyCallBack)(sls_receiver_header &, char *, size_t, - void *) = nullptr; - void (*rawDataModifyReadyCallBack)(sls_receiver_header &, char *, size_t &, - void *) = nullptr; + void (*rawDataReadyCallBack)(sls_receiver_header &, dataCallbackHeader, + char *, size_t &, void *) = nullptr; void *pRawDataReady{nullptr}; pid_t parentThreadId{0}; diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index e1ad9fcc18..e5702389d6 100644 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -41,6 +41,10 @@ void DataProcessor::SetFifo(Fifo *f) { fifo = f; } void DataProcessor::SetGeneralData(GeneralData *g) { generalData = g; } +void DataProcessor::SetUdpPortNumber(const uint16_t portNumber) { + udpPortNumber = portNumber; +} + void DataProcessor::SetActivate(bool enable) { activated = enable; } void DataProcessor::SetReceiverROI(ROI roi) { @@ -73,6 +77,27 @@ void DataProcessor::SetCtbDbitList(std::vector value) { void DataProcessor::SetCtbDbitOffset(int value) { ctbDbitOffset = value; } +void DataProcessor::SetQuadEnable(bool value) { quadEnable = value; } + +void DataProcessor::SetFlipRows(bool fd) { + flipRows = fd; + // flip only right port of quad + if (quadEnable) { + flipRows = (index == 1 ? true : false); + } +} + +void DataProcessor::SetNumberofTotalFrames(uint64_t value) { + nTotalFrames = value; +} + +void DataProcessor::SetAdditionalJsonHeader( + const std::map &json) { + std::lock_guard lock(additionalJsonMutex); + additionalJsonHeader = json; + isAdditionalJsonUpdated = true; +} + void DataProcessor::ResetParametersforNewAcquisition() { StopRunning(); startedFlag = false; @@ -127,8 +152,6 @@ void DataProcessor::CreateFirstFiles(const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, - const uint16_t udpPortNumber, - const uint64_t numImages, const bool detectorDataStream) { if (dataFile == nullptr) { throw RuntimeError("file object not contstructed"); @@ -156,7 +179,7 @@ void DataProcessor::CreateFirstFiles(const std::string &fileNamePrefix, case HDF5: dataFile->CreateFirstHDF5DataFile( fileNamePrefix, fileIndex, overWriteEnable, silentMode, - udpPortNumber, generalData->framesPerFile, numImages, nx, ny, + udpPortNumber, generalData->framesPerFile, nTotalFrames, nx, ny, generalData->dynamicRange); break; #endif @@ -182,8 +205,8 @@ uint32_t DataProcessor::GetFilesInAcquisition() const { std::string DataProcessor::CreateVirtualFile( const std::string &filePath, const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, - const int modulePos, const uint64_t numImages, const int numModX, - const int numModY, std::mutex *hdf5LibMutex) { + const int modulePos, const int numModX, const int numModY, + std::mutex *hdf5LibMutex) { if (receiverRoiEnabled) { throw std::runtime_error( @@ -361,14 +384,31 @@ void DataProcessor::ProcessAnImage(sls_receiver_header &header, size_t &size, } try { - // normal call back + // callbacks if (rawDataReadyCallBack != nullptr) { - rawDataReadyCallBack(header, data, size, pRawDataReady); - } - // call back with modified size - else if (rawDataModifyReadyCallBack != nullptr) { - rawDataModifyReadyCallBack(header, data, size, pRawDataReady); + uint64_t frameIndex = fnum - firstIndex; + // update local copy only if it was updated (to prevent locking each + // time) + if (isAdditionalJsonUpdated) { + std::lock_guard lock(additionalJsonMutex); + localAdditionalJsonHeader = additionalJsonHeader; + isAdditionalJsonUpdated = false; + } + + dataCallbackHeader callbackHeader = { + udpPortNumber, + {static_cast(generalData->nPixelsX), + static_cast(generalData->nPixelsY)}, + fnum, + frameIndex, + (100 * ((double)(frameIndex + 1) / (double)(nTotalFrames))), + (nump == generalData->packetsPerFrame ? true : false), + flipRows, + localAdditionalJsonHeader}; + + rawDataReadyCallBack(header, callbackHeader, data, size, + pRawDataReady); } } catch (const std::exception &e) { throw RuntimeError("Get Data Callback Error: " + std::string(e.what())); @@ -427,17 +467,13 @@ bool DataProcessor::CheckCount() { } void DataProcessor::registerCallBackRawDataReady( - void (*func)(sls_receiver_header &, char *, size_t, void *), void *arg) { + void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &, + void *), + void *arg) { rawDataReadyCallBack = func; pRawDataReady = arg; } -void DataProcessor::registerCallBackRawDataModifyReady( - void (*func)(sls_receiver_header &, char *, size_t &, void *), void *arg) { - rawDataModifyReadyCallBack = func; - pRawDataReady = arg; -} - void DataProcessor::PadMissingPackets(sls_receiver_header header, char *data) { LOG(logDEBUG) << index << ": Padding Missing Packets"; diff --git a/slsReceiverSoftware/src/DataProcessor.h b/slsReceiverSoftware/src/DataProcessor.h index af8af6d17c..29ea9e84c9 100644 --- a/slsReceiverSoftware/src/DataProcessor.h +++ b/slsReceiverSoftware/src/DataProcessor.h @@ -37,6 +37,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void SetFifo(Fifo *f); void SetGeneralData(GeneralData *generalData); + void SetUdpPortNumber(const uint16_t portNumber); void SetActivate(bool enable); void SetReceiverROI(ROI roi); void SetDataStreamEnable(bool enable); @@ -46,6 +47,11 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void SetFramePadding(bool enable); void SetCtbDbitList(std::vector value); void SetCtbDbitOffset(int value); + void SetQuadEnable(bool value); + void SetFlipRows(bool fd); + void SetNumberofTotalFrames(uint64_t value); + void + SetAdditionalJsonHeader(const std::map &json); void ResetParametersforNewAcquisition(); void CloseFiles(); @@ -56,9 +62,7 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { void CreateFirstFiles(const std::string &fileNamePrefix, const uint64_t fileIndex, const bool overWriteEnable, - const bool silentMode, const uint16_t udpPortNumber, - const uint64_t numImages, - const bool detectorDataStream); + const bool silentMode, const bool detectorDataStream); #ifdef HDF5C uint32_t GetFilesInAcquisition() const; std::string CreateVirtualFile(const std::string &filePath, @@ -66,8 +70,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { const uint64_t fileIndex, const bool overWriteEnable, const bool silentMode, const int modulePos, - const uint64_t numImages, const int numModX, - const int numModY, std::mutex *hdf5LibMutex); + const int numModX, const int numModY, + std::mutex *hdf5LibMutex); void LinkFileInMaster(const std::string &masterFileName, const std::string &virtualFileName, const bool silentMode, std::mutex *hdf5LibMutex); @@ -83,15 +87,10 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { /** params: sls_receiver_header, pointer to data, image size */ void registerCallBackRawDataReady(void (*func)(sls_receiver_header &, - char *, size_t, void *), + dataCallbackHeader, char *, + size_t &, void *), void *arg); - /** params: sls_receiver_header, pointer to data, reference to image size */ - void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header &, - char *, size_t &, - void *), - void *arg); - private: void RecordFirstIndex(uint64_t fnum); @@ -150,6 +149,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { GeneralData *generalData{nullptr}; Fifo *fifo; + + uint16_t udpPortNumber{0}; bool dataStreamEnable; bool activated{false}; ROI receiverRoi{}; @@ -167,6 +168,18 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { int ctbDbitOffset; std::atomic startedFlag{false}; std::atomic firstIndex{0}; + bool quadEnable{false}; + bool flipRows{false}; + uint64_t nTotalFrames{0}; + + std::map additionalJsonHeader; + /** Used by streamer thread to update local copy (reduce number of locks + * during streaming) */ + std::atomic isAdditionalJsonUpdated{false}; + /** mutex to update json and to read and update local copy */ + mutable std::mutex additionalJsonMutex; + /** local copy of additional json header (it can be update on the fly) */ + std::map localAdditionalJsonHeader; // for statistics uint64_t numFramesCaught{0}; @@ -189,19 +202,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject { * dataPointer is the pointer to the data * dataSize in bytes is the size of the data in bytes. */ - void (*rawDataReadyCallBack)(sls_receiver_header &, char *, size_t, - void *) = nullptr; - - /** - * Call back for raw data (modified) - * args to raw data ready callback are - * sls_receiver_header frame metadata - * dataPointer is the pointer to the data - * revDatasize is the reference of data size in bytes. Can be modified to - * the new size to be written/streamed. (only smaller value). - */ - void (*rawDataModifyReadyCallBack)(sls_receiver_header &, char *, size_t &, - void *) = nullptr; + void (*rawDataReadyCallBack)(sls_receiver_header &, dataCallbackHeader, + char *, size_t &, void *) = nullptr; void *pRawDataReady{nullptr}; }; diff --git a/slsReceiverSoftware/src/FrameSynchronizerApp.cpp b/slsReceiverSoftware/src/FrameSynchronizerApp.cpp new file mode 100644 index 0000000000..8a56c1d492 --- /dev/null +++ b/slsReceiverSoftware/src/FrameSynchronizerApp.cpp @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: LGPL-3.0-or-other +// Copyright (C) 2021 Contributors to the SLS Detector Package +/* Creates the slsFrameSynchronizer for running multiple receivers in different + * threads form a single binary that will spit out zmq streams without + * reconstructing image */ +#include "sls/Receiver.h" +#include "sls/ToString.h" +#include "sls/container_utils.h" +#include "sls/logger.h" +#include "sls/sls_detector_defs.h" + +#include //SIGINT +#include +#include +#include +#include //wait +#include +#include + +// gettid added in glibc 2.30 +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 +#include +#define gettid() syscall(SYS_gettid) +#endif + +/** Define Colors to print data call back in different colors for different + * recievers */ +#define PRINT_IN_COLOR(c, f, ...) \ + printf("\033[%dm" f RESET, 30 + c + 1, ##__VA_ARGS__) + +std::vector threads; +std::vector semaphores; + +/** + * Control+C Interrupt Handler + * to let all the processes know to exit properly + */ +void sigInterruptHandler(int p) { + for (size_t i = 0; i != semaphores.size(); ++i) { + sem_post(semaphores[i]); + } +} + +/** + * prints usage of this example program + */ +std::string getHelpMessage() { + return std::string( + "\n\nUsage:\n" + "./slsFrameSynchronizer(detReceiver) [start_tcp_port (non-zero and 16 " + "bit)] [num_receivers] [optional: 1 for call back (print frame header " + "for debugging), 0 for none (default)]\n\n"); +} + +/** + * Start Acquisition Call back (slsFrameSynchronizer writes data if file write + * enabled) if registerCallBackRawDataReady or + * registerCallBackRawDataModifyReady registered, users get data + */ +int StartAcq(const slsDetectorDefs::startCallbackHeader callbackHeader, + void *objectPointer) { + LOG(sls::logINFOBLUE) << "#### Start Acquisition:" + << "\n\t[" + << "\n\tUDP Port : " + << sls::ToString(callbackHeader.udpPort) + << "\n\tDynamic Range : " + << callbackHeader.dynamicRange + << "\n\tDetector Shape : " + << sls::ToString(callbackHeader.detectorShape) + << "\n\tImage Size : " << callbackHeader.imageSize + << "\n\tFile Path : " << callbackHeader.filePath + << "\n\tFile Name : " << callbackHeader.fileName + << "\n\tFile Index : " << callbackHeader.fileIndex + << "\n\tQuad Enable : " << callbackHeader.quad + << "\n\t]"; + return 0; +} + +/** Acquisition Finished Call back */ +void AcquisitionFinished( + const slsDetectorDefs::endCallbackHeader callbackHeader, + void *objectPointer) { + LOG(sls::logINFOBLUE) << "#### AcquisitionFinished:" + << "\n\t[" + << "\n\tUDP Port : " + << sls::ToString(callbackHeader.udpPort) + << "\n\tComplete Frames : " + << sls::ToString(callbackHeader.completeFrames) + << "\n\tLast Frame Index : " + << sls::ToString(callbackHeader.lastFrameIndex) + << "\n\t]"; +} + +/** + * Get Receiver Data Call back + * Prints in different colors(for each receiver process) the different headers + * for each image call back. + */ +void GetData(slsDetectorDefs::sls_receiver_header &header, + slsDetectorDefs::dataCallbackHeader callbackHeader, + char *dataPointer, size_t &imageSize, void *objectPointer) { + + slsDetectorDefs::sls_detector_header detectorHeader = header.detHeader; + + PRINT_IN_COLOR( + (callbackHeader.udpPort % 10), + "#### GetData: " + "\n\tCallback Header: " + "\n\t[" + "\n\tUDP Port: %u" + "\n\tShape: [%u, %u]" + "\n\tAcq Index : %lu" + "\n\tFrame Index :%lu" + "\n\tProgress : %.2f%%" + "\n\tCompelte Image :%s" + "\n\tFlip Rows :%s" + "\n\tAdditional Json Header : %s" + "\n\t]" + "\n\ttReceiver Header: " + "\n\t[" + "\n\tFrame Number : %lu" + "\n\tExposure Length :%u" + "\n\tPackets Caught :%u" + "\n\tDetector Specific 1: %lu" + "\n\tTimestamp : %lu" + "\n\tModule Id :%u" + "\n\tRow : %u" + "\n\tColumn :%u" + "\n\tDetector Specific 2 : %u" + "\n\tDetector Specific 3 : %u" + "\n\tDetector Specific 4 : %u" + "\n\tDetector Type : %s" + "\n\tVersion: %u" + "\n\t]" + "\n\tFirst Byte Data: 0x%x" + "\n\tImage Size: %zu\n\n", + callbackHeader.udpPort, callbackHeader.shape.x, callbackHeader.shape.y, + callbackHeader.acqIndex, callbackHeader.frameIndex, + callbackHeader.progress, + sls::ToString(callbackHeader.completeImage).c_str(), + sls::ToString(callbackHeader.flipRows).c_str(), + sls::ToString(callbackHeader.addJsonHeader).c_str(), + detectorHeader.frameNumber, detectorHeader.expLength, + detectorHeader.packetNumber, detectorHeader.detSpec1, + detectorHeader.timestamp, detectorHeader.modId, detectorHeader.row, + detectorHeader.column, detectorHeader.detSpec2, detectorHeader.detSpec3, + detectorHeader.detSpec4, sls::ToString(detectorHeader.detType).c_str(), + detectorHeader.version, + // header->packetsMask.to_string().c_str(), + ((uint8_t)(*((uint8_t *)(dataPointer)))), imageSize); + + // if data is modified, eg ROI and size is reduced + imageSize = 26000; +} + +/** + * Example of main program using the Receiver class + * + * - Defines in file for: + * - Default Number of receivers is 1 + * - Default Start TCP port is 1954 + */ +int main(int argc, char *argv[]) { + + /** - set default values */ + int numReceivers = 1; + uint16_t startTCPPort = 1954; + int withCallback = 0; + + /** - get number of receivers and start tcp port from command line + * arguments */ + try { + if (argc == 3 || argc == 4) { + startTCPPort = sls::StringTo(argv[1]); + if (startTCPPort == 0) { + throw; + } + numReceivers = std::stoi(argv[2]); + if (argc == 4) { + withCallback = std::stoi(argv[3]); + } + } else + throw; + } catch (...) { + throw std::runtime_error(getHelpMessage()); + } + + cprintf(RESET, "Number of Receivers: %d\n", numReceivers); + cprintf(RESET, "Start TCP Port: %hu\n", startTCPPort); + cprintf(RESET, "Callback Enable: %d\n", withCallback); + + /** - Catch signal SIGINT to close files and call destructors properly */ + struct sigaction sa; + sa.sa_flags = 0; // no flags + sa.sa_handler = sigInterruptHandler; // handler function + sigemptyset(&sa.sa_mask); // dont block additional signals during invocation + // of handler + if (sigaction(SIGINT, &sa, nullptr) == -1) { + cprintf(RED, "Could not set handler function for SIGINT\n"); + } + + /** - Ignore SIG_PIPE, prevents global signal handler, handle locally, + instead of a server crashing due to client crash when writing, it just + gives error */ + struct sigaction asa; + asa.sa_flags = 0; // no flags + asa.sa_handler = SIG_IGN; // handler function + sigemptyset(&asa.sa_mask); // dont block additional signals during + // invocation of handler + if (sigaction(SIGPIPE, &asa, nullptr) == -1) { + cprintf(RED, "Could not set handler function for SIGPIPE\n"); + } + + /** - loop over number of receivers */ + for (int i = 0; i != numReceivers; ++i) { + + sem_t *semaphore = new sem_t; + sem_init(semaphore, 1, 0); + semaphores.push_back(semaphore); + threads.emplace_back([semaphore, i, startTCPPort, withCallback, + numReceivers]() { + sls::Receiver receiver(startTCPPort + i); + if (withCallback) { + receiver.registerCallBackStartAcquisition(StartAcq, nullptr); + receiver.registerCallBackAcquisitionFinished( + AcquisitionFinished, nullptr); + receiver.registerCallBackRawDataReady(GetData, nullptr); + } + + /** - as long as no Ctrl+C */ + sem_wait(semaphore); + sem_destroy(semaphore); + }); + } + + for (auto &thread : threads) { + thread.join(); + } + + std::cout << "Goodbye!\n"; + return 0; +} diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index 76573e5270..e3446f294b 100644 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -196,6 +196,7 @@ void Implementation::SetupListener(int i) { void Implementation::SetupDataProcessor(int i) { dataProcessor[i]->SetFifo(fifo[i].get()); dataProcessor[i]->SetGeneralData(generalData); + dataProcessor[i]->SetUdpPortNumber(udpPortNum[i]); dataProcessor[i]->SetActivate(activated); dataProcessor[i]->SetReceiverROI(portRois[i]); dataProcessor[i]->SetDataStreamEnable(dataStreamEnable); @@ -205,6 +206,10 @@ void Implementation::SetupDataProcessor(int i) { dataProcessor[i]->SetFramePadding(framePadding); dataProcessor[i]->SetCtbDbitList(ctbDbitList); dataProcessor[i]->SetCtbDbitOffset(ctbDbitOffset); + dataProcessor[i]->SetQuadEnable(quadEnable); + dataProcessor[i]->SetFlipRows(flipRows); + dataProcessor[i]->SetNumberofTotalFrames(numberOfTotalFrames); + dataProcessor[i]->SetAdditionalJsonHeader(additionalJsonHeader); } void Implementation::SetupDataStreamer(int i) { @@ -216,7 +221,6 @@ void Implementation::SetupDataStreamer(int i) { dataStreamer[i]->SetQuadEnable(quadEnable); dataStreamer[i]->SetFlipRows(flipRows); dataStreamer[i]->SetNumberofPorts(numPorts); - dataStreamer[i]->SetQuadEnable(quadEnable); dataStreamer[i]->SetNumberofTotalFrames(numberOfTotalFrames); dataStreamer[i]->SetReceiverROI( portRois[i].completeRoi() ? GetMaxROIPerPort() : portRois[i]); @@ -685,18 +689,26 @@ void Implementation::startReceiver() { // callbacks if (startAcquisitionCallBack) { try { - std::size_t imageSize = - static_cast(generalData->imageSize); - startAcquisitionCallBack(filePath, fileName, fileIndex, imageSize, - pStartAcquisition); + std::vector udpPort; + for (size_t i = 0; i != listener.size(); ++i) { + udpPort.push_back(udpPortNum[i]); + } + startCallbackHeader callbackHeader = { + udpPort, + generalData->dynamicRange, + numPorts, + static_cast(generalData->imageSize), + filePath, + fileName, + fileIndex, + quadEnable, + additionalJsonHeader}; + startAcquisitionCallBack(callbackHeader, pStartAcquisition); } catch (const std::exception &e) { std::ostringstream oss; oss << "Start Acquisition Callback Error: " << e.what(); throw RuntimeError(oss.str()); } - if (rawDataReadyCallBack != nullptr) { - LOG(logINFO) << "Data Write has been defined externally"; - } } // processor->writer @@ -799,9 +811,19 @@ void Implementation::stopReceiver() { // callback if (acquisitionFinishedCallBack) { try { - acquisitionFinishedCallBack( - (tot / generalData->numUDPInterfaces), - pAcquisitionFinished); + std::vector udpPort; + std::vector completeFramesCaught; + std::vector lastFrameIndexCaught; + for (size_t i = 0; i != listener.size(); ++i) { + udpPort.push_back(udpPortNum[i]); + completeFramesCaught.push_back( + listener[i]->GetNumCompleteFramesCaught()); + lastFrameIndexCaught.push_back( + listener[i]->GetLastFrameIndexCaught()); + } + endCallbackHeader callHeader = {udpPort, completeFramesCaught, + lastFrameIndexCaught}; + acquisitionFinishedCallBack(callHeader, pAcquisitionFinished); } catch (const std::exception &e) { // change status status = IDLE; @@ -905,9 +927,9 @@ void Implementation::SetupWriter() { os << filePath << "/" << fileName << "_d" << (modulePos * generalData->numUDPInterfaces + i); std::string fileNamePrefix = os.str(); - dataProcessor[i]->CreateFirstFiles( - fileNamePrefix, fileIndex, overwriteEnable, silentMode, - udpPortNum[i], numberOfTotalFrames, detectorDataStream[i]); + dataProcessor[i]->CreateFirstFiles(fileNamePrefix, fileIndex, + overwriteEnable, silentMode, + detectorDataStream[i]); } } catch (const RuntimeError &e) { shutDownUDPSockets(); @@ -1003,8 +1025,7 @@ void Implementation::StartMasterWriter() { (numPorts.x * numPorts.y) > 1) { virtualFileName = dataProcessor[0]->CreateVirtualFile( filePath, fileName, fileIndex, overwriteEnable, silentMode, - modulePos, numberOfTotalFrames, numPorts.x, numPorts.y, - &hdf5LibMutex); + modulePos, numPorts.x, numPorts.y, &hdf5LibMutex); } // link file in master if (masterFileWriteEnable) { @@ -1112,11 +1133,6 @@ void Implementation::setNumberofUDPInterfaces(const int n) { it->registerCallBackRawDataReady(rawDataReadyCallBack, pRawDataReady); } - if (rawDataModifyReadyCallBack) { - for (const auto &it : dataProcessor) - it->registerCallBackRawDataModifyReady( - rawDataModifyReadyCallBack, pRawDataReady); - } // test socket buffer size with current set up setUDPSocketBufferSize(0); @@ -1148,6 +1164,7 @@ uint16_t Implementation::getUDPPortNumber() const { return udpPortNum[0]; } void Implementation::setUDPPortNumber(const uint16_t i) { udpPortNum[0] = i; listener[0]->SetUdpPortNumber(i); + dataProcessor[0]->SetUdpPortNumber(i); LOG(logINFO) << "UDP Port Number[0]: " << udpPortNum[0]; } @@ -1157,6 +1174,7 @@ void Implementation::setUDPPortNumber2(const uint16_t i) { udpPortNum[1] = i; if (listener.size() > 1) { listener[1]->SetUdpPortNumber(i); + dataProcessor[1]->SetUdpPortNumber(i); } LOG(logINFO) << "UDP Port Number[1]: " << udpPortNum[1]; } @@ -1278,6 +1296,9 @@ void Implementation::setAdditionalJsonHeader( const std::map &c) { additionalJsonHeader = c; + for (const auto &it : dataProcessor) { + it->SetAdditionalJsonHeader(c); + } for (const auto &it : dataStreamer) { it->SetAdditionalJsonHeader(c); } @@ -1320,6 +1341,9 @@ void Implementation::setAdditionalJsonParameter(const std::string &key, LOG(logINFO) << "Adding additional json parameter (" << key << ") to " << value; } + for (const auto &it : dataProcessor) { + it->SetAdditionalJsonHeader(additionalJsonHeader); + } for (const auto &it : dataStreamer) { it->SetAdditionalJsonHeader(additionalJsonHeader); } @@ -1359,6 +1383,8 @@ void Implementation::updateTotalNumberOfFrames() { } numberOfTotalFrames = numFrames * repeats * (int64_t)(numberOfAdditionalStorageCells + 1); + for (const auto &it : dataProcessor) + it->SetNumberofTotalFrames(numberOfTotalFrames); for (const auto &it : dataStreamer) it->SetNumberofTotalFrames(numberOfTotalFrames); if (numberOfTotalFrames == 0) { @@ -1617,6 +1643,8 @@ bool Implementation::getFlipRows() const { return flipRows; } void Implementation::setFlipRows(bool enable) { flipRows = enable; + for (const auto &it : dataProcessor) + it->SetFlipRows(flipRows); for (const auto &it : dataStreamer) it->SetFlipRows(flipRows); LOG(logINFO) << "Flip Rows: " << flipRows; @@ -1628,6 +1656,10 @@ void Implementation::setQuad(const bool b) { if (quadEnable != b) { quadEnable = b; setDetectorSize(numModules); + for (const auto &it : dataProcessor) { + it->SetQuadEnable(quadEnable); + it->SetFlipRows(flipRows); + } for (const auto &it : dataStreamer) { it->SetQuadEnable(quadEnable); it->SetFlipRows(flipRows); @@ -1769,35 +1801,25 @@ void Implementation::setTransceiverEnableMask(uint32_t mask) { * * * ************************************************/ void Implementation::registerCallBackStartAcquisition( - int (*func)(const std::string &, const std::string &, uint64_t, size_t, - void *), - void *arg) { + int (*func)(const startCallbackHeader, void *), void *arg) { startAcquisitionCallBack = func; pStartAcquisition = arg; } -void Implementation::registerCallBackAcquisitionFinished(void (*func)(uint64_t, - void *), - void *arg) { +void Implementation::registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg) { acquisitionFinishedCallBack = func; pAcquisitionFinished = arg; } void Implementation::registerCallBackRawDataReady( - void (*func)(sls_receiver_header &, char *, size_t, void *), void *arg) { + void (*func)(sls_receiver_header &, dataCallbackHeader, char *, size_t &, + void *), + void *arg) { rawDataReadyCallBack = func; pRawDataReady = arg; for (const auto &it : dataProcessor) it->registerCallBackRawDataReady(rawDataReadyCallBack, pRawDataReady); } -void Implementation::registerCallBackRawDataModifyReady( - void (*func)(sls_receiver_header &, char *, size_t &, void *), void *arg) { - rawDataModifyReadyCallBack = func; - pRawDataReady = arg; - for (const auto &it : dataProcessor) - it->registerCallBackRawDataModifyReady(rawDataModifyReadyCallBack, - pRawDataReady); -} - } // namespace sls diff --git a/slsReceiverSoftware/src/Implementation.h b/slsReceiverSoftware/src/Implementation.h index 45f1546bf2..671f6deb2a 100644 --- a/slsReceiverSoftware/src/Implementation.h +++ b/slsReceiverSoftware/src/Implementation.h @@ -265,22 +265,17 @@ class Implementation : private virtual slsDetectorDefs { * * * ************************************************/ /** params: file path, file name, file index, image size */ - void registerCallBackStartAcquisition(int (*func)(const std::string &, - const std::string &, - uint64_t, size_t, void *), + void registerCallBackStartAcquisition(int (*func)(const startCallbackHeader, + void *), void *arg); /** params: total frames caught */ - void registerCallBackAcquisitionFinished(void (*func)(uint64_t, void *), - void *arg); + void registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg); /** params: sls_receiver_header, pointer to data, image size */ void registerCallBackRawDataReady(void (*func)(sls_receiver_header &, - char *, size_t, void *), + dataCallbackHeader, char *, + size_t &, void *), void *arg); - /** params: sls_receiver_header, pointer to data, reference to image size */ - void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header &, - char *, size_t &, - void *), - void *arg); private: void SetLocalNetworkParameters(); @@ -379,15 +374,13 @@ class Implementation : private virtual slsDetectorDefs { int ctbDbitOffset{0}; // callbacks - int (*startAcquisitionCallBack)(const std::string &, const std::string &, - uint64_t, size_t, void *){nullptr}; + int (*startAcquisitionCallBack)(const startCallbackHeader, void *){nullptr}; void *pStartAcquisition{nullptr}; - void (*acquisitionFinishedCallBack)(uint64_t, void *){nullptr}; + void (*acquisitionFinishedCallBack)(const endCallbackHeader, + void *){nullptr}; void *pAcquisitionFinished{nullptr}; - void (*rawDataReadyCallBack)(sls_receiver_header &, char *, size_t, - void *){nullptr}; - void (*rawDataModifyReadyCallBack)(sls_receiver_header &, char *, size_t &, - void *){nullptr}; + void (*rawDataReadyCallBack)(sls_receiver_header &, dataCallbackHeader, + char *, size_t &, void *){nullptr}; void *pRawDataReady{nullptr}; // class objects diff --git a/slsReceiverSoftware/src/MultiReceiverApp.cpp b/slsReceiverSoftware/src/MultiReceiverApp.cpp index b9ac35eab3..1d0203d549 100644 --- a/slsReceiverSoftware/src/MultiReceiverApp.cpp +++ b/slsReceiverSoftware/src/MultiReceiverApp.cpp @@ -50,19 +50,40 @@ std::string getHelpMessage() { * enabled) if registerCallBackRawDataReady or * registerCallBackRawDataModifyReady registered, users get data */ -int StartAcq(const std::string &filePath, const std::string &fileName, - uint64_t fileIndex, size_t imageSize, void *objectPointer) { - LOG(sls::logINFOBLUE) << "#### StartAcq: filePath:" << filePath - << " fileName:" << fileName - << " fileIndex:" << fileIndex - << " imageSize:" << imageSize << " ####"; +int StartAcq(const slsDetectorDefs::startCallbackHeader callbackHeader, + void *objectPointer) { + LOG(sls::logINFOBLUE) << "#### Start Acquisition:" + << "\n\t[" + << "\n\tUDP Port : " + << sls::ToString(callbackHeader.udpPort) + << "\n\tDynamic Range : " + << callbackHeader.dynamicRange + << "\n\tDetector Shape : " + << sls::ToString(callbackHeader.detectorShape) + << "\n\tImage Size : " << callbackHeader.imageSize + << "\n\tFile Path : " << callbackHeader.filePath + << "\n\tFile Name : " << callbackHeader.fileName + << "\n\tFile Index : " << callbackHeader.fileIndex + << "\n\tQuad Enable : " << callbackHeader.quad + << "\n\tAdditional Json Header : " + << sls::ToString(callbackHeader.addJsonHeader) + << "\n\t]"; return 0; } /** Acquisition Finished Call back */ -void AcquisitionFinished(uint64_t framesCaught, void *objectPointer) { - LOG(sls::logINFOBLUE) << "#### AcquisitionFinished: framesCaught:" - << framesCaught << " ####"; +void AcquisitionFinished( + const slsDetectorDefs::endCallbackHeader callbackHeader, + void *objectPointer) { + LOG(sls::logINFOBLUE) << "#### AcquisitionFinished:" + << "\n\t[" + << "\n\tUDP Port : " + << sls::ToString(callbackHeader.udpPort) + << "\n\tComplete Frames : " + << sls::ToString(callbackHeader.completeFrames) + << "\n\tLast Frame Index : " + << sls::ToString(callbackHeader.lastFrameIndex) + << "\n\t]"; } /** @@ -70,62 +91,61 @@ void AcquisitionFinished(uint64_t framesCaught, void *objectPointer) { * Prints in different colors(for each receiver process) the different headers * for each image call back. */ -void GetData(slsDetectorDefs::sls_receiver_header &header, char *dataPointer, - size_t imageSize, void *objectPointer) { - slsDetectorDefs::sls_detector_header detectorHeader = header.detHeader; - - PRINT_IN_COLOR( - detectorHeader.modId ? detectorHeader.modId : detectorHeader.row, - "#### %d %d GetData: ####\n" - "frameNumber: %lu\t\texpLength: %u\t\tpacketNumber: %u\t\tdetSpec1: %lu" - "\t\ttimestamp: %lu\t\tmodId: %u\t\t" - "row: %u\t\tcolumn: %u\t\tdetSpec2: %u\t\tdetSpec3: %u" - "\t\tdetSpec4: %u\t\tdetType: %u\t\tversion: %u" - //"\t\tpacketsMask:%s" - "\t\tfirstbytedata: 0x%x\t\tdatsize: %zu\n\n", - detectorHeader.column, detectorHeader.row, - (long unsigned int)detectorHeader.frameNumber, detectorHeader.expLength, - detectorHeader.packetNumber, (long unsigned int)detectorHeader.detSpec1, - (long unsigned int)detectorHeader.timestamp, detectorHeader.modId, - detectorHeader.row, detectorHeader.column, detectorHeader.detSpec2, - detectorHeader.detSpec3, detectorHeader.detSpec4, - detectorHeader.detType, detectorHeader.version, - // header->packetsMask.to_string().c_str(), - ((uint8_t)(*((uint8_t *)(dataPointer)))), imageSize); -} +void GetData(slsDetectorDefs::sls_receiver_header &header, + slsDetectorDefs::dataCallbackHeader callbackHeader, + char *dataPointer, size_t &imageSize, void *objectPointer) { -/** - * Get Receiver Data Call back (modified) - * Prints in different colors(for each receiver process) the different headers - * for each image call back. - * @param modifiedImageSize new data size in bytes after the callback. - * This will be the size written/streamed. (only smaller value is allowed). - */ -void GetData(slsDetectorDefs::sls_receiver_header &header, char *dataPointer, - size_t &modifiedImageSize, void *objectPointer) { slsDetectorDefs::sls_detector_header detectorHeader = header.detHeader; PRINT_IN_COLOR( - detectorHeader.modId ? detectorHeader.modId : detectorHeader.row, - "#### %d %d GetData: ####\n" - "frameNumber: %lu\t\texpLength: %u\t\tpacketNumber: %u\t\tdetSpec1: %lu" - "\t\ttimestamp: %lu\t\tmodId: %u\t\t" - "row: %u\t\tcolumn: %u\t\tdetSpec2: %u\t\tdetSpec3: %u" - "\t\tdetSpec4: %u\t\tdetType: %u\t\tversion: %u" - //"\t\tpacketsMask:%s" - "\t\tfirstbytedata: 0x%x\t\tdatsize: %zu\n\n", - detectorHeader.column, detectorHeader.row, - (long unsigned int)detectorHeader.frameNumber, detectorHeader.expLength, - detectorHeader.packetNumber, (long unsigned int)detectorHeader.detSpec1, - (long unsigned int)detectorHeader.timestamp, detectorHeader.modId, - detectorHeader.row, detectorHeader.column, detectorHeader.detSpec2, - detectorHeader.detSpec3, detectorHeader.detSpec4, - detectorHeader.detType, detectorHeader.version, + (callbackHeader.udpPort % 10), + "#### GetData: " + "\n\tCallback Header: " + "\n\t[" + "\n\tUDP Port: %u" + "\n\tShape: [%u, %u]" + "\n\tAcq Index : %lu" + "\n\tFrame Index :%lu" + "\n\tProgress : %.2f%%" + "\n\tCompelte Image :%s" + "\n\tFlip Rows :%s" + "\n\tAdditional Json Header : %s" + "\n\t]" + "\n\ttReceiver Header: " + "\n\t[" + "\n\tFrame Number : %lu" + "\n\tExposure Length :%u" + "\n\tPackets Caught :%u" + "\n\tDetector Specific 1: %lu" + "\n\tTimestamp : %lu" + "\n\tModule Id :%u" + "\n\tRow : %u" + "\n\tColumn :%u" + "\n\tDetector Specific 2 : %u" + "\n\tDetector Specific 3 : %u" + "\n\tDetector Specific 4 : %u" + "\n\tDetector Type : %s" + "\n\tVersion: %u" + "\n\t]" + "\n\tFirst Byte Data: 0x%x" + "\n\tImage Size: %zu\n\n", + callbackHeader.udpPort, callbackHeader.shape.x, callbackHeader.shape.y, + callbackHeader.acqIndex, callbackHeader.frameIndex, + callbackHeader.progress, + sls::ToString(callbackHeader.completeImage).c_str(), + sls::ToString(callbackHeader.flipRows).c_str(), + sls::ToString(callbackHeader.addJsonHeader).c_str(), + detectorHeader.frameNumber, detectorHeader.expLength, + detectorHeader.packetNumber, detectorHeader.detSpec1, + detectorHeader.timestamp, detectorHeader.modId, detectorHeader.row, + detectorHeader.column, detectorHeader.detSpec2, detectorHeader.detSpec3, + detectorHeader.detSpec4, sls::ToString(detectorHeader.detType).c_str(), + detectorHeader.version, // header->packetsMask.to_string().c_str(), - *reinterpret_cast(dataPointer), modifiedImageSize); + ((uint8_t)(*((uint8_t *)(dataPointer)))), imageSize); // if data is modified, eg ROI and size is reduced - modifiedImageSize = 26000; + imageSize = 26000; } /** @@ -214,26 +234,22 @@ int main(int argc, char *argv[]) { throw; } /** - register callbacks. remember to set file write enable to 0 - (using the client) if we should not write files and you will write data - using the callbacks */ + * (using the client) if we should not write files and you will + * write data using the callbacks */ if (withCallback) { /** - Call back for start acquisition */ - cprintf(BLUE, "Registering StartAcq()\n"); + cprintf(BLUE, "Registering StartAcq()\n"); receiver->registerCallBackStartAcquisition(StartAcq, nullptr); /** - Call back for acquisition finished */ - cprintf(BLUE, "Registering AcquisitionFinished()\n"); + cprintf(BLUE, "Registering AcquisitionFinished()\n"); receiver->registerCallBackAcquisitionFinished( AcquisitionFinished, nullptr); /* - Call back for raw data */ - cprintf(BLUE, "Registering GetData() \n"); - if (withCallback == 1) - receiver->registerCallBackRawDataReady(GetData, nullptr); - else if (withCallback == 2) - receiver->registerCallBackRawDataModifyReady(GetData, - nullptr); + cprintf(BLUE, "Registering GetData() \n"); + receiver->registerCallBackRawDataReady(GetData, nullptr); } /** - as long as no Ctrl+C */ diff --git a/slsReceiverSoftware/src/Receiver.cpp b/slsReceiverSoftware/src/Receiver.cpp index bff6757e07..d7c6763667 100644 --- a/slsReceiverSoftware/src/Receiver.cpp +++ b/slsReceiverSoftware/src/Receiver.cpp @@ -133,28 +133,21 @@ std::string Receiver::getReceiverVersion() { return tcpipInterface->getReceiverVersion(); } -void Receiver::registerCallBackStartAcquisition(int (*func)(const std::string &, - const std::string &, - uint64_t, size_t, - void *), - void *arg) { +void Receiver::registerCallBackStartAcquisition( + int (*func)(const startCallbackHeader, void *), void *arg) { tcpipInterface->registerCallBackStartAcquisition(func, arg); } -void Receiver::registerCallBackAcquisitionFinished(void (*func)(uint64_t, - void *), - void *arg) { +void Receiver::registerCallBackAcquisitionFinished( + void (*func)(const endCallbackHeader, void *), void *arg) { tcpipInterface->registerCallBackAcquisitionFinished(func, arg); } void Receiver::registerCallBackRawDataReady( - void (*func)(sls_receiver_header &, char *, size_t, void *), void *arg) { + void (*func)(sls_receiver_header &, const dataCallbackHeader, char *, + size_t &, void *), + void *arg) { tcpipInterface->registerCallBackRawDataReady(func, arg); } -void Receiver::registerCallBackRawDataModifyReady( - void (*func)(sls_receiver_header &, char *, size_t &, void *), void *arg) { - tcpipInterface->registerCallBackRawDataModifyReady(func, arg); -} - } // namespace sls \ No newline at end of file diff --git a/slsSupportLib/include/sls/sls_detector_defs.h b/slsSupportLib/include/sls/sls_detector_defs.h index 96b1f8a436..755a1da91c 100644 --- a/slsSupportLib/include/sls/sls_detector_defs.h +++ b/slsSupportLib/include/sls/sls_detector_defs.h @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #else // C includes #include @@ -113,6 +115,20 @@ class slsDetectorDefs { STOPPED }; + /** + dimension indexes + */ + enum dimension { X, Y }; + +#ifdef __cplusplus + struct xy { + int x{0}; + int y{0}; + xy() = default; + xy(int x, int y) : x(x), y(y){}; + } __attribute__((packed)); +#endif + /** @short structure for a Detector Packet or Image Header Details at https://slsdetectorgroup.github.io/devdoc/udpheader.html @@ -160,6 +176,36 @@ class slsDetectorDefs { sls_detector_header detHeader; /**< is the detector header */ sls_bitset packetsMask; /**< is the packets caught bit mask */ }; + + struct startCallbackHeader { + std::vector udpPort; + uint32_t dynamicRange; + xy detectorShape; + size_t imageSize; + std::string filePath; + std::string fileName; + uint64_t fileIndex; + bool quad; + std::map addJsonHeader; + }; + + struct endCallbackHeader { + std::vector udpPort; + std::vector completeFrames; + std::vector lastFrameIndex; + }; + + struct dataCallbackHeader { + uint32_t udpPort; + xy shape; + uint64_t acqIndex; + uint64_t frameIndex; + double progress; + bool completeImage; + bool flipRows; + std::map addJsonHeader; + }; + #endif enum frameDiscardPolicy { NO_DISCARD, @@ -224,20 +270,6 @@ typedef struct { READOUT_ZMQ_ACTION }; - /** - dimension indexes - */ - enum dimension { X, Y }; - -#ifdef __cplusplus - struct xy { - int x{0}; - int y{0}; - xy() = default; - xy(int x, int y) : x(x), y(y){}; - } __attribute__((packed)); -#endif - /** use of the external signals */