From 4dfa4a739d9a8d3692ac7ac6b3554dbc80552d15 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 23 Aug 2012 18:33:46 -0400 Subject: [PATCH 01/53] ENH: start implementing session manager --- CMakeLists.txt | 2 +- Examples/CMakeLists.txt | 1 + Examples/SessionManager/CMakeLists.txt | 16 ++ Examples/SessionManager/SessionManagerServer.cxx | 136 +++++++++++++++ Examples/SessionManager/SessionManagerServer.cxx~ | 131 +++++++++++++++ Source/CMakeLists.txt | 3 + Source/igtlMessageHandler.h | 89 ++++++++++ Source/igtlMessageHandler.txx | 76 +++++++++ Source/igtlMessageHandlerMacro.h | 46 ++++++ Source/igtlSessionManager.cxx | 193 ++++++++++++++++++++++ Source/igtlSessionManager.h | 80 +++++++++ 11 files changed, 772 insertions(+), 1 deletion(-) create mode 100644 Examples/SessionManager/CMakeLists.txt create mode 100644 Examples/SessionManager/SessionManagerServer.cxx create mode 100644 Examples/SessionManager/SessionManagerServer.cxx~ create mode 100644 Source/igtlMessageHandler.h create mode 100644 Source/igtlMessageHandler.txx create mode 100644 Source/igtlMessageHandlerMacro.h create mode 100644 Source/igtlSessionManager.cxx create mode 100644 Source/igtlSessionManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c4a23006..9d641b63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "9") -SET(OpenIGTLink_VERSION_PATCH "6") +SET(OpenIGTLink_VERSION_PATCH "7") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index cd86635a..6d7af02a 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -11,6 +11,7 @@ SET(EXAMPLE_DIRS Status Receiver Thread + SessionManager ) if (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") diff --git a/Examples/SessionManager/CMakeLists.txt b/Examples/SessionManager/CMakeLists.txt new file mode 100644 index 00000000..85c60ed9 --- /dev/null +++ b/Examples/SessionManager/CMakeLists.txt @@ -0,0 +1,16 @@ +PROJECT(SessionManager) + +cmake_minimum_required(VERSION 2.4) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +find_package(OpenIGTLink REQUIRED) + +include(${OpenIGTLink_USE_FILE}) + +ADD_EXECUTABLE(SessionManagerServer SessionManagerServer.cxx) +TARGET_LINK_LIBRARIES(SessionManagerServer OpenIGTLink) + +#ADD_EXECUTABLE(SessionManagerClient SessionManagerClient.cxx) +#TARGET_LINK_LIBRARIES(SessionManagerClient OpenIGTLink) diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx new file mode 100644 index 00000000..ce66062b --- /dev/null +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -0,0 +1,136 @@ +/*========================================================================= + + Program: OpenIGTLink -- Example for Data Receiving Server Program + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlMessageHeader.h" + +#include "igtlMessageHandler.h" +#include "igtlMessageHandlerMacro.h" + +#include "igtlSessionManager.h" +#include "igtlTransformMessage.h" +#include "igtlImageMessage.h" +#include "igtlServerSocket.h" +#include "igtlStatusMessage.h" +#include "igtlPositionMessage.h" + +namespace igtl { +igtlMessageHandlerClassMacro(TransformMessage, TestTransformMessageHandler); +igtlMessageHandlerClassMacro(PositionMessage, TestPositionMessageHandler); +igtlMessageHandlerClassMacro(ImageMessage, TestImageMessageHandler); + +template +void TestTransformMessageHandler::Process(TransformMessage * transMsg) +{ + // Retrive the transform data + igtl::Matrix4x4 matrix; + transMsg->GetMatrix(matrix); + igtl::PrintMatrix(matrix); + return 1; +} + +template +void TestPositionMessageHandler::Process(PositionMessage * positionMsg) +{ + // Retrive the transform data + float position[3]; + float quaternion[4]; + + positionMsg->GetPosition(position); + positionMsg->GetQuaternion(quaternion); + + std::cerr << "position = (" << position[0] << ", " << position[1] << ", " << position[2] << ")" << std::endl; + std::cerr << "quaternion = (" << quaternion[0] << ", " << quaternion[1] << ", " + << quaternion[2] << ", " << quaternion[3] << ")" << std::endl << std::endl; + return 1; +} + +template +void TestImageMessageHandler::Process(ImageMessage * imgMsg) +{ + // Retrive the image data + int size[3]; // image dimension + float spacing[3]; // spacing (mm/pixel) + int svsize[3]; // sub-volume size + int svoffset[3]; // sub-volume offset + int scalarType; // scalar type + + scalarType = imgMsg->GetScalarType(); + imgMsg->GetDimensions(size); + imgMsg->GetSpacing(spacing); + imgMsg->GetSubVolume(svsize, svoffset); + + std::cerr << "Device Name : " << imgMsg->GetDeviceName() << std::endl; + std::cerr << "Scalar Type : " << scalarType << std::endl; + std::cerr << "Dimensions : (" + << size[0] << ", " << size[1] << ", " << size[2] << ")" << std::endl; + std::cerr << "Spacing : (" + << spacing[0] << ", " << spacing[1] << ", " << spacing[2] << ")" << std::endl; + std::cerr << "Sub-Volume dimensions : (" + << svsize[0] << ", " << svsize[1] << ", " << svsize[2] << ")" << std::endl; + std::cerr << "Sub-Volume offset : (" + << svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl; + return 1; +} +} + + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 3) // check number of arguments + { + // If not correct, print usage + std::cerr << " : IP or host name" << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + char* hostname = argv[1]; + int port = atoi(argv[2]); + + // Connection + igtl::SessionManager::Pointer sm; + sm = igtl::SessionManager::New(); + sm->SetModeClient(); + sm->SetAddress(hostname); + sm->SetPort(port); + + // Set message handers + igtl::TestImageMessageHander::Pointer imh; + imh = igtl::ImageMessageHander::New(); + igtl::TransformMessageHander::Pointer tmh; + tmh = igtl::ImageMessageHander::New(); + + sm->AddMessageHandler(tmh); + sm->AddMessageHandler(imh); + + // Start session + sm->Start(); + + // Do something + + // Stop session + sm->End(); +} + + + diff --git a/Examples/SessionManager/SessionManagerServer.cxx~ b/Examples/SessionManager/SessionManagerServer.cxx~ new file mode 100644 index 00000000..6c72c475 --- /dev/null +++ b/Examples/SessionManager/SessionManagerServer.cxx~ @@ -0,0 +1,131 @@ +/*========================================================================= + + Program: Open IGT Link -- Example for Data Receiving Server Program + Module: $RCSfile: $ + Language: C++ + Date: $Date: $ + Version: $Revision: $ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlMessageHeader.h" +#include "igtlTransformMessage.h" +#include "igtlImageMessage.h" +#include "igtlServerSocket.h" +#include "igtlStatusMessage.h" +#include "igtlPositionMessage.h" + +igtlMessageHandlerClassMacro(igtl::TransformMessage, TestTransformMessageHandler); +igtlMessageHandlerClassMacro(igtl::PositionMessage, TestPositionMessageHandler); +igtlMessageHandlerClassMacro(igtl::ImageMessage, TestImageMessageHandler); + + +void TestTransformMessageHandler::ProcessMessage(igtl::TransformMessage * transMsg) +{ + // Retrive the transform data + igtl::Matrix4x4 matrix; + transMsg->GetMatrix(matrix); + igtl::PrintMatrix(matrix); +} + + +void TestPositionMessageHandler::ProcessMessage(igtl::PositionMessage * positionMsg) +{ + // Retrive the transform data + float position[3]; + float quaternion[4]; + + positionMsg->GetPosition(position); + positionMsg->GetQuaternion(quaternion); + + std::cerr << "position = (" << position[0] << ", " << position[1] << ", " << position[2] << ")" << std::endl; + std::cerr << "quaternion = (" << quaternion[0] << ", " << quaternion[1] << ", " + << quaternion[2] << ", " << quaternion[3] << ")" << std::endl << std::endl; +} + + +void TestImageMessageHandler::ProcessMessage(igtl::ImageMessage * imgMsg) +{ + // Retrive the image data + int size[3]; // image dimension + float spacing[3]; // spacing (mm/pixel) + int svsize[3]; // sub-volume size + int svoffset[3]; // sub-volume offset + int scalarType; // scalar type + + scalarType = imgMsg->GetScalarType(); + imgMsg->GetDimensions(size); + imgMsg->GetSpacing(spacing); + imgMsg->GetSubVolume(svsize, svoffset); + + std::cerr << "Device Name : " << imgMsg->GetDeviceName() << std::endl; + std::cerr << "Scalar Type : " << scalarType << std::endl; + std::cerr << "Dimensions : (" + << size[0] << ", " << size[1] << ", " << size[2] << ")" << std::endl; + std::cerr << "Spacing : (" + << spacing[0] << ", " << spacing[1] << ", " << spacing[2] << ")" << std::endl; + std::cerr << "Sub-Volume dimensions : (" + << svsize[0] << ", " << svsize[1] << ", " << svsize[2] << ")" << std::endl; + std::cerr << "Sub-Volume offset : (" + << svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl; + return 1; + } +} + + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 3) // check number of arguments + { + // If not correct, print usage + std::cerr << " : IP or host name" << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + char* hostname = argv[1]; + int port = atoi(argv[2]); + + // Connection + igtl::SessionManager::Pointer sm; + sm = igtl::SessionManager::New(); + sm->SetModeClient(); + sm->SetAddress(hostname); + sm->SetPort(port); + + // Set message handers + igtl::TestImageMessageHander::Pointer imh; + imh = igtl::ImageMessageHander::New(); + igtl::TransformMessageHander::Pointer tmh; + tmh = igtl::ImageMessageHander::New(); + + sm->AddMessageHandler(tmh); + sm->AddMessageHandler(imh); + + // Start session + sm->Start(); + + // Do something + + // Stop session + sm->End(); +} + + + diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index e8545aea..26c3e48a 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -51,6 +51,7 @@ SET(OpenIGTLink_SOURCES igtlObjectFactoryBase.cxx igtlPositionMessage.cxx igtlServerSocket.cxx + igtlSessionManager.cxx igtlSimpleFastMutexLock.cxx igtlSocket.cxx igtlStatusMessage.cxx @@ -66,6 +67,7 @@ SET(OpenIGTLink_INCLUDE_FILES igtlutil/igtl_types.h igtlutil/igtl_util.h igtlutil/igtl_capability.h + igtlMessageHandler.h igtlClientSocket.h igtlConditionVariable.h igtlCreateObjectFunction.h @@ -85,6 +87,7 @@ SET(OpenIGTLink_INCLUDE_FILES igtlObjectFactoryBase.h igtlPositionMessage.h igtlServerSocket.h + igtlSessionManager.h igtlSimpleFastMutexLock.h igtlSmartPointer.h igtlSocket.h diff --git a/Source/igtlMessageHandler.h b/Source/igtlMessageHandler.h new file mode 100644 index 00000000..187d949e --- /dev/null +++ b/Source/igtlMessageHandler.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: OpenIGTLink Library + Module: git@github.com:openigtlink/OpenIGTLink.git + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __igtlMessageHandler_h +#define __igtlMessageHandler_h + +#include "igtlObject.h" +#include "igtlMacro.h" +#include "igtlSocket.h" +#include "igtlMessageBase.h" + +namespace igtl +{ + +class IGTLCommon_EXPORT MessageHandlerInterface: public Object +{ + public: + + typedef MessageHandlerInterface Self; + typedef Object Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::MessageHandlerInterface, igtl::Object) + igtlNewMacro(igtl::MessageHandlerInterface); + + public: + virtual const char* GetMessageType() { return ""; } + virtual int ReceiveMessage(Socket*, MessageBase*) {}; + + protected: + MessageHandlerInterface(); + ~MessageHandlerInterface(); + + protected: +}; + + +template +class IGTLCommon_EXPORT MessageHandler: public MessageHandlerInterface +{ + public: + + typedef MessageHandler Self; + typedef MessageHandlerInterface Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(MessageHandler, Object) + igtlNewMacro(MessageHandler); + + public: + virtual const char* GetMessageType(); + virtual int ReceiveMessage(Socket*, MessageBase*); + virtual int Process(MessageType* message) {}; + virtual void CheckCRC(int i); + + protected: + MessageHandler(); + ~MessageHandler(); + + protected: + int m_CheckCRC; + MessageType m_Message; + +}; + + +} // namespace igtl + +#include "igtlMessageHandler.txx" + +#endif // _igtlMessageHandler_h + + + + + diff --git a/Source/igtlMessageHandler.txx b/Source/igtlMessageHandler.txx new file mode 100644 index 00000000..9b8e3bd2 --- /dev/null +++ b/Source/igtlMessageHandler.txx @@ -0,0 +1,76 @@ +/*========================================================================= + + Program: OpenIGTLink Library + Module: git@github.com:openigtlink/OpenIGTLink.git + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __igtlMessageHandler_txx +#define __igtlMessageHandler_txx + +#include "igtlMessageHandler.h" + +namespace igtl +{ + +template +MessageHandler::MessageHandler() +{ + this->m_Message = MessageType::New(); + this->m_CheckCRC = 1; +} + +template +MessageHandler::~MessageHandler() +{ +} + +template +const char* MessageHandler::GetMessageType() +{ + return this->m_Message->GetBodyType(); +} + +template +int MessageHandler::ReceiveMessage(Socket* socket, MessageBase* header) +{ + this->m_Message->SetMessageHeader(header); + this->m_Message->AllocatePack(); + socket->Receive(this->m_Message->GetPackBodyPointer(), this->m_Message->GetPackBodySize()); + int r = this->m_Message->Unpack(this->m_CheckCRC); + if (r) + { + Process(this->m_Message); + return 1; + } + else + { + return 0; + } +} + +template +void MessageHandler::CheckCRC(int i) +{ + if (i == 0) + { + this->m_CheckCRC = 0; + } + else + { + this->m_CheckCRC = 1; + } +} + +} + + + +#endif //__igtlMessageHandler_txx diff --git a/Source/igtlMessageHandlerMacro.h b/Source/igtlMessageHandlerMacro.h new file mode 100644 index 00000000..83470275 --- /dev/null +++ b/Source/igtlMessageHandlerMacro.h @@ -0,0 +1,46 @@ +/*========================================================================= + + Program: OpenIGTLink Library + Module: git@github.com:openigtlink/OpenIGTLink.git + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __igtlMessageHandlerMacro_h +#define __igtlMessageHandlerMacro_h + +#include "igtlMessageHandler.h" + +// Description: +// The igtlMessageHandlerClassMacro() macro is to help developers to +// define message handler class. It generates a chlid class of igtl::MessageHandler. +// The developer only needs to implement ProcessMessage() after calling this macro. +// The following code shows how to define a handler that processes IMAGE message: +// +// igtlMessageHandlerClassMacro(igtl::ImageMessage, TestImageMessageHandler); +// void TestImageMessageHandler::Process(igtl::ImageMessage * message) +// { +// // do something +// } + +#define igtlMessageHandlerClassMacro(messagetype, classname) \ + template \ + class classname : public MessageHandler \ + { \ + typedef classname Self; \ + typedef MessageHandler Superclass; \ + typedef SmartPointer Pointer; \ + typedef SmartPointer ConstPointer; \ + igtlTypeMacro(classname, MessageHandler); \ + igtlNewMacro(classname); \ + public: \ + virtual void Process(messagetype); \ + }; \ + +#endif // __igtlMessageHandlerMacro_h diff --git a/Source/igtlSessionManager.cxx b/Source/igtlSessionManager.cxx new file mode 100644 index 00000000..3f5f6748 --- /dev/null +++ b/Source/igtlSessionManager.cxx @@ -0,0 +1,193 @@ +/*========================================================================= + + Program: OpenIGTLink Library + Module: git@github.com:openigtlink/OpenIGTLink.git + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include + +#include "igtlSessionManager.h" +#include "igtlMessageHandler.h" +#include "igtlClientSocket.h" +#include "igtlServerSocket.h" + +namespace igtl +{ + + +SessionManager::SessionManager() +{ + this->m_MessageHandlerList.clear(); + this->m_Mode = MODE_SERVER; + + this->m_Header = igtl::MessageHeader::New(); + this->m_TimeStamp = igtl::TimeStamp::New(); +} + + +SessionManager::~SessionManager() +{ +} + + +int SessionManager::Connect() +{ + if (this->m_Mode == MODE_CLIENT) + { + this->m_Socket = NULL; + + ClientSocket::Pointer clientSocket; + clientSocket = ClientSocket::New(); + //this->DebugOff(); + if (this->m_Hostname.length() == 0) + { + return 0; + } + //this->m_Socket->SetConnectTimeout(1000); + int r = clientSocket->ConnectToServer(this->m_Hostname.c_str(), this->m_Port); + if (r == 0) // if connected to server + { + clientSocket->SetReceiveTimeout(0); + this->m_Socket = clientSocket; + return 1; + } + //igtl::Sleep(1000); + } + else + { + ServerSocket::Pointer serverSocket; + if (serverSocket->CreateServer(this->m_Port)) + { + return 0; + } + + //std::cerr << this->GetClassName() << ": WaitForConnection(): Port number # = " << this->m_Port << std::endl; + this->m_Socket = NULL; + if (serverSocket.IsNotNull()) + { + //this->ServerSocket->CreateServer(this->m_Port); + this->m_Socket = serverSocket->WaitForConnection(1000); + } + + if (this->m_Socket.IsNotNull() && this->m_Socket->GetConnected()) // if client connected + { + this->m_Socket->DebugOff(); + return 1; + } + return 0; + } +} + +int SessionManager::Disconnect() +{ + if (this->m_Socket.IsNotNull()) + { + this->m_Socket->CloseSocket(); + } + + return 0; +} + + +int SessionManager::ProcessMessage() +{ + // Initialize receive buffer + this->m_Header->InitPack(); + + // Receive generic header from the socket + int r = this->m_Socket->Receive(this->m_Header->GetPackPointer(), this->m_Header->GetPackSize()); + if (r == 0) + { + return 0; + } + if (r != this->m_Header->GetPackSize()) + { + return -1; + } + + // Deserialize the header + this->m_Header->Unpack(); + + // Get time stamp + igtlUint32 sec; + igtlUint32 nanosec; + + this->m_Header->GetTimeStamp(this->m_TimeStamp); + this->m_TimeStamp->GetTimeStamp(&sec, &nanosec); + + std::cerr << "Time stamp: " + << sec << "." << std::setw(9) << std::setfill('0') + << nanosec << std::endl; + + // Look for a message handler that matches to the message type. + int found = 0; + std::vector< MessageHandlerInterface* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + { + if (strcmp(this->m_Header->GetDeviceType(), (*iter)->GetMessageType()) == 0) + { + (*iter)->ReceiveMessage(this->m_Socket, this->m_Header); + iter = this->m_MessageHandlerList.end(); + found = 1; + } + } + + // If there is no message handler, skip the message + if (!found) + { + std::cerr << "Receiving : " << this->m_Header->GetDeviceType() << std::endl; + this->m_Socket->Skip(this->m_Header->GetBodySizeToRead(), 0); + } +} + + +int SessionManager::AddMessageHandler(MessageHandlerInterface* handler) +{ + // Check if there is any handler for the same message type + std::vector< MessageHandlerInterface* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + { + if (strcmp((*iter)->GetMessageType(), handler->GetMessageType()) == 0) + { + return 0; + } + } + + // If not, add the handler to the list. + this->m_MessageHandlerList.push_back(handler); + + return 1; +} + + +int SessionManager::RemoveMessageHandler(MessageHandlerInterface* handler) +{ + // Check if there is any handler for the same message type + std::vector< MessageHandlerInterface* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + { + if (*iter == handler) + { + this->m_MessageHandlerList.erase(iter); + return 1; + } + } + return 0; +} + + +} + + diff --git a/Source/igtlSessionManager.h b/Source/igtlSessionManager.h new file mode 100644 index 00000000..43cb7320 --- /dev/null +++ b/Source/igtlSessionManager.h @@ -0,0 +1,80 @@ +/*========================================================================= + + Program: OpenIGTLink Library + Module: git@github.com:openigtlink/OpenIGTLink.git + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __igtlSessionManager_h +#define __igtlSessionManager_h + +#include "igtlObject.h" +#include "igtlMacro.h" +#include "igtlMessageHandler.h" + + +#include + +namespace igtl +{ + +class IGTLCommon_EXPORT SessionManager: public Object +{ + public: + + typedef SessionManager Self; + typedef Object Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(SessionManager, Object) + igtlNewMacro(SessionManager); + + public: + enum { + MODE_SERVER, + MODE_CLIENT + }; + + void SetHostname(const char * str) {this->m_Hostname = str; this->m_ConfigurationUpdated = true; } + const char * GetHostname() { return this->m_Hostname.c_str(); } + void SetPort(int p) { this->m_Port = p; this->m_ConfigurationUpdated = true; } + int GetPort() { return this->m_Port; } + + // Description: + // Set the role of session manager. Either MODE_SERVER or MODE_CLIENT + void SetMode(int m) {this->m_Mode = m; this->m_ConfigurationUpdated = true; } + int GetMode(int m) {return this->m_Mode = m; } + int Connect(); + int ProcessMessage(); + int Disconnect(); + int AddMessageHandler(MessageHandlerInterface*); + int RemoveMessageHandler(MessageHandlerInterface*); + + protected: + SessionManager(); + ~SessionManager(); + + protected: + bool m_ConfigurationUpdated; + std::string m_Hostname; + int m_Port; + int m_Mode; + + std::vector< MessageHandlerInterface* > m_MessageHandlerList; + Socket::Pointer m_Socket; + + igtl::MessageHeader::Pointer m_Header; + igtl::TimeStamp::Pointer m_TimeStamp; + +}; + +} +#endif // __igtlSessionManager_h From 1149f0d201871f4eebb1573c1358d0a514394a96 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 23 Aug 2012 23:20:17 -0400 Subject: [PATCH 02/53] ENH: MessageHandler and SessionManager classes are implemented and now working. Template-based MessageHandler class has been removed. --- Examples/SessionManager/SessionManagerServer.cxx | 56 ++++++++--------- Source/igtlMessageHandler.h | 47 +++------------ Source/igtlMessageHandler.txx | 76 ------------------------ Source/igtlMessageHandlerMacro.h | 72 +++++++++++++++++++--- Source/igtlSessionManager.cxx | 39 +++++++----- Source/igtlSessionManager.h | 6 +- 6 files changed, 126 insertions(+), 170 deletions(-) delete mode 100644 Source/igtlMessageHandler.txx diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx index ce66062b..e2136ce4 100644 --- a/Examples/SessionManager/SessionManagerServer.cxx +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -30,13 +30,11 @@ #include "igtlStatusMessage.h" #include "igtlPositionMessage.h" -namespace igtl { -igtlMessageHandlerClassMacro(TransformMessage, TestTransformMessageHandler); -igtlMessageHandlerClassMacro(PositionMessage, TestPositionMessageHandler); -igtlMessageHandlerClassMacro(ImageMessage, TestImageMessageHandler); +igtlMessageHandlerClassMacro(igtl::TransformMessage, TransformHandler); +igtlMessageHandlerClassMacro(igtl::PositionMessage, PositionHandler); +igtlMessageHandlerClassMacro(igtl::ImageMessage, ImageHandler); -template -void TestTransformMessageHandler::Process(TransformMessage * transMsg) +int TransformHandler::Process(igtl::TransformMessage * transMsg) { // Retrive the transform data igtl::Matrix4x4 matrix; @@ -45,8 +43,7 @@ void TestTransformMessageHandler::Process(TransformMessage * transMsg) return 1; } -template -void TestPositionMessageHandler::Process(PositionMessage * positionMsg) +int PositionHandler::Process(igtl::PositionMessage * positionMsg) { // Retrive the transform data float position[3]; @@ -61,8 +58,7 @@ void TestPositionMessageHandler::Process(PositionMessage * positionMsg) return 1; } -template -void TestImageMessageHandler::Process(ImageMessage * imgMsg) +int ImageHandler::Process(igtl::ImageMessage * imgMsg) { // Retrive the image data int size[3]; // image dimension @@ -88,48 +84,52 @@ void TestImageMessageHandler::Process(ImageMessage * imgMsg) << svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl; return 1; } -} int main(int argc, char* argv[]) { + //------------------------------------------------------------ // Parse Arguments - - if (argc != 3) // check number of arguments + if (argc != 2) // check number of arguments { // If not correct, print usage - std::cerr << " : IP or host name" << std::endl; std::cerr << " : Port # (18944 in Slicer default)" << std::endl; exit(0); } - char* hostname = argv[1]; - int port = atoi(argv[2]); + int port = atoi(argv[1]); // Connection igtl::SessionManager::Pointer sm; sm = igtl::SessionManager::New(); - sm->SetModeClient(); - sm->SetAddress(hostname); + sm->SetMode(igtl::SessionManager::MODE_SERVER); sm->SetPort(port); // Set message handers - igtl::TestImageMessageHander::Pointer imh; - imh = igtl::ImageMessageHander::New(); - igtl::TransformMessageHander::Pointer tmh; - tmh = igtl::ImageMessageHander::New(); + TransformHandler::Pointer tmh = TransformHandler::New(); + PositionHandler::Pointer pmh = PositionHandler::New(); + ImageHandler::Pointer imh = ImageHandler::New(); sm->AddMessageHandler(tmh); + sm->AddMessageHandler(pmh); sm->AddMessageHandler(imh); // Start session - sm->Start(); - - // Do something - - // Stop session - sm->End(); + if (sm->Connect()) + { + while (1) + { + int r = sm->ProcessMessage(); + if (r == 0) // Disconnected + { + break; + } + } + // Stop session + sm->Disconnect(); + } + } diff --git a/Source/igtlMessageHandler.h b/Source/igtlMessageHandler.h index 187d949e..2bea436b 100644 --- a/Source/igtlMessageHandler.h +++ b/Source/igtlMessageHandler.h @@ -23,64 +23,31 @@ namespace igtl { -class IGTLCommon_EXPORT MessageHandlerInterface: public Object +class IGTLCommon_EXPORT MessageHandler: public Object { public: - typedef MessageHandlerInterface Self; + typedef MessageHandler Self; typedef Object Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; - igtlTypeMacro(igtl::MessageHandlerInterface, igtl::Object) - igtlNewMacro(igtl::MessageHandlerInterface); + igtlTypeMacro(igtl::MessageHandler, igtl::Object) + igtlNewMacro(igtl::MessageHandler); public: virtual const char* GetMessageType() { return ""; } - virtual int ReceiveMessage(Socket*, MessageBase*) {}; + virtual int ReceiveMessage(Socket*, MessageBase*) { return 0; }; protected: - MessageHandlerInterface(); - ~MessageHandlerInterface(); + MessageHandler() {} + ~MessageHandler() {} protected: }; - -template -class IGTLCommon_EXPORT MessageHandler: public MessageHandlerInterface -{ - public: - - typedef MessageHandler Self; - typedef MessageHandlerInterface Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; - - igtlTypeMacro(MessageHandler, Object) - igtlNewMacro(MessageHandler); - - public: - virtual const char* GetMessageType(); - virtual int ReceiveMessage(Socket*, MessageBase*); - virtual int Process(MessageType* message) {}; - virtual void CheckCRC(int i); - - protected: - MessageHandler(); - ~MessageHandler(); - - protected: - int m_CheckCRC; - MessageType m_Message; - -}; - - } // namespace igtl -#include "igtlMessageHandler.txx" - #endif // _igtlMessageHandler_h diff --git a/Source/igtlMessageHandler.txx b/Source/igtlMessageHandler.txx deleted file mode 100644 index 9b8e3bd2..00000000 --- a/Source/igtlMessageHandler.txx +++ /dev/null @@ -1,76 +0,0 @@ -/*========================================================================= - - Program: OpenIGTLink Library - Module: git@github.com:openigtlink/OpenIGTLink.git - Language: C++ - - Copyright (c) Insight Software Consortium. All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ - -#ifndef __igtlMessageHandler_txx -#define __igtlMessageHandler_txx - -#include "igtlMessageHandler.h" - -namespace igtl -{ - -template -MessageHandler::MessageHandler() -{ - this->m_Message = MessageType::New(); - this->m_CheckCRC = 1; -} - -template -MessageHandler::~MessageHandler() -{ -} - -template -const char* MessageHandler::GetMessageType() -{ - return this->m_Message->GetBodyType(); -} - -template -int MessageHandler::ReceiveMessage(Socket* socket, MessageBase* header) -{ - this->m_Message->SetMessageHeader(header); - this->m_Message->AllocatePack(); - socket->Receive(this->m_Message->GetPackBodyPointer(), this->m_Message->GetPackBodySize()); - int r = this->m_Message->Unpack(this->m_CheckCRC); - if (r) - { - Process(this->m_Message); - return 1; - } - else - { - return 0; - } -} - -template -void MessageHandler::CheckCRC(int i) -{ - if (i == 0) - { - this->m_CheckCRC = 0; - } - else - { - this->m_CheckCRC = 1; - } -} - -} - - - -#endif //__igtlMessageHandler_txx diff --git a/Source/igtlMessageHandlerMacro.h b/Source/igtlMessageHandlerMacro.h index 83470275..4f90a0c8 100644 --- a/Source/igtlMessageHandlerMacro.h +++ b/Source/igtlMessageHandlerMacro.h @@ -29,18 +29,74 @@ // // do something // } +//#define igtlMessageHandlerClassMacro(messagetype, classname) \ +// template \ +// class classname : public MessageHandler \ +// { \ +// typedef classname Self; \ +// typedef MessageHandler Superclass; \ +// typedef SmartPointer Pointer; \ +// typedef SmartPointer ConstPointer; \ +// igtlTypeMacro(classname, MessageHandler); \ +// igtlNewMacro(classname); \ +// public: \ +// virtual void Process(messagetype*); \ +// }; + #define igtlMessageHandlerClassMacro(messagetype, classname) \ - template \ - class classname : public MessageHandler \ + class classname : public ::igtl::MessageHandler \ { \ + public: \ typedef classname Self; \ - typedef MessageHandler Superclass; \ - typedef SmartPointer Pointer; \ - typedef SmartPointer ConstPointer; \ - igtlTypeMacro(classname, MessageHandler); \ + typedef ::igtl::MessageHandler Superclass; \ + typedef igtl::SmartPointer Pointer; \ + typedef igtl::SmartPointer ConstPointer; \ + igtlTypeMacro(classname, ::igtl::MessageHandler); \ igtlNewMacro(classname); \ public: \ - virtual void Process(messagetype); \ - }; \ + virtual const char* GetMessageType() \ + { \ + return this->m_Message->GetDeviceType(); \ + } \ + virtual int Process(messagetype*); \ + int ReceiveMessage(::igtl::Socket* socket, ::igtl::MessageBase* header) \ + { \ + this->m_Message->SetMessageHeader(header); \ + this->m_Message->AllocatePack(); \ + socket->Receive(this->m_Message->GetPackBodyPointer(), \ + this->m_Message->GetPackBodySize()); \ + int r = this->m_Message->Unpack(this->m_CheckCRC); \ + if (r) \ + { \ + Process(this->m_Message); \ + return 1; \ + } \ + else \ + { \ + return 0; \ + } \ + } \ + virtual void CheckCRC(int i) \ + { \ + if (i == 0) \ + { \ + this->m_CheckCRC = 0; \ + } \ + else \ + { \ + this->m_CheckCRC = 1; \ + } \ + } \ + protected: \ + classname() \ + { \ + this->m_Message = messagetype::New(); \ + this->m_CheckCRC = 1; \ + } \ + ~classname() {} \ + protected: \ + int m_CheckCRC; \ + messagetype::Pointer m_Message; \ + }; #endif // __igtlMessageHandlerMacro_h diff --git a/Source/igtlSessionManager.cxx b/Source/igtlSessionManager.cxx index 3f5f6748..ee2ab872 100644 --- a/Source/igtlSessionManager.cxx +++ b/Source/igtlSessionManager.cxx @@ -44,10 +44,11 @@ SessionManager::~SessionManager() int SessionManager::Connect() { + + this->m_Socket = NULL; + if (this->m_Mode == MODE_CLIENT) { - this->m_Socket = NULL; - ClientSocket::Pointer clientSocket; clientSocket = ClientSocket::New(); //this->DebugOff(); @@ -68,17 +69,18 @@ int SessionManager::Connect() else { ServerSocket::Pointer serverSocket; - if (serverSocket->CreateServer(this->m_Port)) + serverSocket = ServerSocket::New(); + int r = serverSocket->CreateServer(this->m_Port); + if (r < 0) { return 0; } //std::cerr << this->GetClassName() << ": WaitForConnection(): Port number # = " << this->m_Port << std::endl; - this->m_Socket = NULL; if (serverSocket.IsNotNull()) { //this->ServerSocket->CreateServer(this->m_Port); - this->m_Socket = serverSocket->WaitForConnection(1000); + this->m_Socket = serverSocket->WaitForConnection(10000); } if (this->m_Socket.IsNotNull() && this->m_Socket->GetConnected()) // if client connected @@ -88,6 +90,9 @@ int SessionManager::Connect() } return 0; } + + return 0; + } int SessionManager::Disconnect() @@ -110,7 +115,7 @@ int SessionManager::ProcessMessage() int r = this->m_Socket->Receive(this->m_Header->GetPackPointer(), this->m_Header->GetPackSize()); if (r == 0) { - return 0; + return 0; // Disconnected } if (r != this->m_Header->GetPackSize()) { @@ -127,20 +132,21 @@ int SessionManager::ProcessMessage() this->m_Header->GetTimeStamp(this->m_TimeStamp); this->m_TimeStamp->GetTimeStamp(&sec, &nanosec); - std::cerr << "Time stamp: " - << sec << "." << std::setw(9) << std::setfill('0') - << nanosec << std::endl; + //std::cerr << "Time stamp: " + // << sec << "." << std::setw(9) << std::setfill('0') + // << nanosec << std::endl; // Look for a message handler that matches to the message type. int found = 0; - std::vector< MessageHandlerInterface* >::iterator iter; + std::vector< MessageHandler* >::iterator iter; for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) { if (strcmp(this->m_Header->GetDeviceType(), (*iter)->GetMessageType()) == 0) { (*iter)->ReceiveMessage(this->m_Socket, this->m_Header); - iter = this->m_MessageHandlerList.end(); + //iter = this->m_MessageHandlerList.end(); found = 1; + break; } } @@ -150,13 +156,16 @@ int SessionManager::ProcessMessage() std::cerr << "Receiving : " << this->m_Header->GetDeviceType() << std::endl; this->m_Socket->Skip(this->m_Header->GetBodySizeToRead(), 0); } + + return 1; + } -int SessionManager::AddMessageHandler(MessageHandlerInterface* handler) +int SessionManager::AddMessageHandler(MessageHandler* handler) { // Check if there is any handler for the same message type - std::vector< MessageHandlerInterface* >::iterator iter; + std::vector< MessageHandler* >::iterator iter; for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) { if (strcmp((*iter)->GetMessageType(), handler->GetMessageType()) == 0) @@ -172,10 +181,10 @@ int SessionManager::AddMessageHandler(MessageHandlerInterface* handler) } -int SessionManager::RemoveMessageHandler(MessageHandlerInterface* handler) +int SessionManager::RemoveMessageHandler(MessageHandler* handler) { // Check if there is any handler for the same message type - std::vector< MessageHandlerInterface* >::iterator iter; + std::vector< MessageHandler* >::iterator iter; for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) { if (*iter == handler) diff --git a/Source/igtlSessionManager.h b/Source/igtlSessionManager.h index 43cb7320..372805b2 100644 --- a/Source/igtlSessionManager.h +++ b/Source/igtlSessionManager.h @@ -55,8 +55,8 @@ class IGTLCommon_EXPORT SessionManager: public Object int Connect(); int ProcessMessage(); int Disconnect(); - int AddMessageHandler(MessageHandlerInterface*); - int RemoveMessageHandler(MessageHandlerInterface*); + int AddMessageHandler(MessageHandler*); + int RemoveMessageHandler(MessageHandler*); protected: SessionManager(); @@ -68,7 +68,7 @@ class IGTLCommon_EXPORT SessionManager: public Object int m_Port; int m_Mode; - std::vector< MessageHandlerInterface* > m_MessageHandlerList; + std::vector< MessageHandler* > m_MessageHandlerList; Socket::Pointer m_Socket; igtl::MessageHeader::Pointer m_Header; From 8017cf612d3830cd34d854ccaf3a914b05670340 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 24 Aug 2012 15:57:48 -0400 Subject: [PATCH 03/53] STYLE: adding comment in the source code for SessionManagerServer example program. --- Examples/SessionManager/SessionManagerServer.cxx | 31 +++-- Examples/SessionManager/SessionManagerServer.cxx~ | 131 ---------------------- 2 files changed, 24 insertions(+), 138 deletions(-) delete mode 100644 Examples/SessionManager/SessionManagerServer.cxx~ diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx index e2136ce4..2a076ba4 100644 --- a/Examples/SessionManager/SessionManagerServer.cxx +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -19,21 +19,31 @@ #include "igtlOSUtil.h" #include "igtlMessageHeader.h" - #include "igtlMessageHandler.h" #include "igtlMessageHandlerMacro.h" - #include "igtlSessionManager.h" #include "igtlTransformMessage.h" -#include "igtlImageMessage.h" -#include "igtlServerSocket.h" -#include "igtlStatusMessage.h" #include "igtlPositionMessage.h" +#include "igtlImageMessage.h" + +//------------------------------------------------------------ +// Define message handler classes for TransformMessage, +// PositionMessage and ImageMessage +// igtlMessageHandlerClassMacro() defines a child class of +// igtl::MessageHandler to handle OpenIGTLink messages for +// the message type specified as the first argument. The +// second argument will be used for the name of this +// message handler class. igtlMessageHandlerClassMacro(igtl::TransformMessage, TransformHandler); igtlMessageHandlerClassMacro(igtl::PositionMessage, PositionHandler); igtlMessageHandlerClassMacro(igtl::ImageMessage, ImageHandler); +//------------------------------------------------------------ +// You need to describe how the received message is processed +// in Process() function of the message handler class. + +// -- Transform message int TransformHandler::Process(igtl::TransformMessage * transMsg) { // Retrive the transform data @@ -43,6 +53,7 @@ int TransformHandler::Process(igtl::TransformMessage * transMsg) return 1; } +// -- Position message int PositionHandler::Process(igtl::PositionMessage * positionMsg) { // Retrive the transform data @@ -58,6 +69,7 @@ int PositionHandler::Process(igtl::PositionMessage * positionMsg) return 1; } +// -- Image message int ImageHandler::Process(igtl::ImageMessage * imgMsg) { // Retrive the image data @@ -100,21 +112,26 @@ int main(int argc, char* argv[]) int port = atoi(argv[1]); - // Connection + //------------------------------------------------------------ + // Create a session manager igtl::SessionManager::Pointer sm; sm = igtl::SessionManager::New(); sm->SetMode(igtl::SessionManager::MODE_SERVER); sm->SetPort(port); - // Set message handers + //------------------------------------------------------------ + // Create message handlers TransformHandler::Pointer tmh = TransformHandler::New(); PositionHandler::Pointer pmh = PositionHandler::New(); ImageHandler::Pointer imh = ImageHandler::New(); + //------------------------------------------------------------ + // Register the message handlers to the session manager sm->AddMessageHandler(tmh); sm->AddMessageHandler(pmh); sm->AddMessageHandler(imh); + //------------------------------------------------------------ // Start session if (sm->Connect()) { diff --git a/Examples/SessionManager/SessionManagerServer.cxx~ b/Examples/SessionManager/SessionManagerServer.cxx~ deleted file mode 100644 index 6c72c475..00000000 --- a/Examples/SessionManager/SessionManagerServer.cxx~ +++ /dev/null @@ -1,131 +0,0 @@ -/*========================================================================= - - Program: Open IGT Link -- Example for Data Receiving Server Program - Module: $RCSfile: $ - Language: C++ - Date: $Date: $ - Version: $Revision: $ - - Copyright (c) Insight Software Consortium. All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ - -#include -#include -#include -#include -#include - -#include "igtlOSUtil.h" -#include "igtlMessageHeader.h" -#include "igtlTransformMessage.h" -#include "igtlImageMessage.h" -#include "igtlServerSocket.h" -#include "igtlStatusMessage.h" -#include "igtlPositionMessage.h" - -igtlMessageHandlerClassMacro(igtl::TransformMessage, TestTransformMessageHandler); -igtlMessageHandlerClassMacro(igtl::PositionMessage, TestPositionMessageHandler); -igtlMessageHandlerClassMacro(igtl::ImageMessage, TestImageMessageHandler); - - -void TestTransformMessageHandler::ProcessMessage(igtl::TransformMessage * transMsg) -{ - // Retrive the transform data - igtl::Matrix4x4 matrix; - transMsg->GetMatrix(matrix); - igtl::PrintMatrix(matrix); -} - - -void TestPositionMessageHandler::ProcessMessage(igtl::PositionMessage * positionMsg) -{ - // Retrive the transform data - float position[3]; - float quaternion[4]; - - positionMsg->GetPosition(position); - positionMsg->GetQuaternion(quaternion); - - std::cerr << "position = (" << position[0] << ", " << position[1] << ", " << position[2] << ")" << std::endl; - std::cerr << "quaternion = (" << quaternion[0] << ", " << quaternion[1] << ", " - << quaternion[2] << ", " << quaternion[3] << ")" << std::endl << std::endl; -} - - -void TestImageMessageHandler::ProcessMessage(igtl::ImageMessage * imgMsg) -{ - // Retrive the image data - int size[3]; // image dimension - float spacing[3]; // spacing (mm/pixel) - int svsize[3]; // sub-volume size - int svoffset[3]; // sub-volume offset - int scalarType; // scalar type - - scalarType = imgMsg->GetScalarType(); - imgMsg->GetDimensions(size); - imgMsg->GetSpacing(spacing); - imgMsg->GetSubVolume(svsize, svoffset); - - std::cerr << "Device Name : " << imgMsg->GetDeviceName() << std::endl; - std::cerr << "Scalar Type : " << scalarType << std::endl; - std::cerr << "Dimensions : (" - << size[0] << ", " << size[1] << ", " << size[2] << ")" << std::endl; - std::cerr << "Spacing : (" - << spacing[0] << ", " << spacing[1] << ", " << spacing[2] << ")" << std::endl; - std::cerr << "Sub-Volume dimensions : (" - << svsize[0] << ", " << svsize[1] << ", " << svsize[2] << ")" << std::endl; - std::cerr << "Sub-Volume offset : (" - << svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl; - return 1; - } -} - - -int main(int argc, char* argv[]) -{ - //------------------------------------------------------------ - // Parse Arguments - - if (argc != 3) // check number of arguments - { - // If not correct, print usage - std::cerr << " : IP or host name" << std::endl; - std::cerr << " : Port # (18944 in Slicer default)" << std::endl; - exit(0); - } - - char* hostname = argv[1]; - int port = atoi(argv[2]); - - // Connection - igtl::SessionManager::Pointer sm; - sm = igtl::SessionManager::New(); - sm->SetModeClient(); - sm->SetAddress(hostname); - sm->SetPort(port); - - // Set message handers - igtl::TestImageMessageHander::Pointer imh; - imh = igtl::ImageMessageHander::New(); - igtl::TransformMessageHander::Pointer tmh; - tmh = igtl::ImageMessageHander::New(); - - sm->AddMessageHandler(tmh); - sm->AddMessageHandler(imh); - - // Start session - sm->Start(); - - // Do something - - // Stop session - sm->End(); -} - - - From bc3be186973164500ff64ce981fedd5199c1fc7f Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 6 Sep 2012 00:02:47 -0400 Subject: [PATCH 04/53] ENH: implement session manager with pseudo non-blocking messaging (receive only) --- Examples/SessionManager/SessionManagerServer.cxx | 1 + Source/igtlMessageHandler.h | 9 +- Source/igtlMessageHandlerMacro.h | 44 ++-- Source/igtlSessionManager.cxx | 251 ++++++++++++++++------- Source/igtlSessionManager.h | 22 +- Source/igtlSocket.cxx | 127 +++++++++++- Source/igtlSocket.h | 10 + 7 files changed, 368 insertions(+), 96 deletions(-) diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx index 2a076ba4..7504aec8 100644 --- a/Examples/SessionManager/SessionManagerServer.cxx +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -142,6 +142,7 @@ int main(int argc, char* argv[]) { break; } + igtl::Sleep(400); // Wait for 400 ms } // Stop session sm->Disconnect(); diff --git a/Source/igtlMessageHandler.h b/Source/igtlMessageHandler.h index 2bea436b..0f1c3943 100644 --- a/Source/igtlMessageHandler.h +++ b/Source/igtlMessageHandler.h @@ -37,13 +37,20 @@ class IGTLCommon_EXPORT MessageHandler: public Object public: virtual const char* GetMessageType() { return ""; } - virtual int ReceiveMessage(Socket*, MessageBase*) { return 0; }; + virtual int ReceiveMessage(Socket*, MessageBase*, int) { return 0; }; + + void SetMessageBuffer(MessageBase* buffer) { this->m_Buffer = buffer; } + MessageBase * GetMessageBuffer() { return this->m_Buffer; } protected: MessageHandler() {} ~MessageHandler() {} + + protected: + MessageBase * m_Buffer; + }; } // namespace igtl diff --git a/Source/igtlMessageHandlerMacro.h b/Source/igtlMessageHandlerMacro.h index 4f90a0c8..eeaa40df 100644 --- a/Source/igtlMessageHandlerMacro.h +++ b/Source/igtlMessageHandlerMacro.h @@ -59,23 +59,33 @@ return this->m_Message->GetDeviceType(); \ } \ virtual int Process(messagetype*); \ - int ReceiveMessage(::igtl::Socket* socket, ::igtl::MessageBase* header) \ - { \ - this->m_Message->SetMessageHeader(header); \ - this->m_Message->AllocatePack(); \ - socket->Receive(this->m_Message->GetPackBodyPointer(), \ - this->m_Message->GetPackBodySize()); \ - int r = this->m_Message->Unpack(this->m_CheckCRC); \ - if (r) \ - { \ - Process(this->m_Message); \ - return 1; \ - } \ - else \ - { \ - return 0; \ - } \ - } \ + int ReceiveMessage(::igtl::Socket* socket, ::igtl::MessageBase* header, int pos) \ + { \ + if (pos == 0) /* New body */ \ + { \ + this->m_Message->SetMessageHeader(header); \ + this->m_Message->AllocatePack(); \ + } \ + int s = socket->Receive((void*)((char*)this->m_Message->GetPackBodyPointer()+pos), \ + this->m_Message->GetPackBodySize()-pos); \ + if (s < 0) /* Time out */ \ + { \ + return pos; \ + } \ + if (s+pos >= this->m_Message->GetPackBodySize()) \ + { \ + int r = this->m_Message->Unpack(this->m_CheckCRC); \ + if (r) \ + { \ + Process(this->m_Message); \ + } \ + else \ + { \ + return -1; \ + } \ + } \ + return s + pos; /* return current position in the body */ \ + } \ virtual void CheckCRC(int i) \ { \ if (i == 0) \ diff --git a/Source/igtlSessionManager.cxx b/Source/igtlSessionManager.cxx index ee2ab872..1065153c 100644 --- a/Source/igtlSessionManager.cxx +++ b/Source/igtlSessionManager.cxx @@ -23,6 +23,8 @@ #include "igtlClientSocket.h" #include "igtlServerSocket.h" +#include "igtl_header.h" + namespace igtl { @@ -34,6 +36,9 @@ SessionManager::SessionManager() this->m_Header = igtl::MessageHeader::New(); this->m_TimeStamp = igtl::TimeStamp::New(); + + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; } @@ -42,6 +47,41 @@ SessionManager::~SessionManager() } +int SessionManager::AddMessageHandler(MessageHandler* handler) +{ + // Check if there is any handler for the same message type + std::vector< MessageHandler* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + { + if (strcmp((*iter)->GetMessageType(), handler->GetMessageType()) == 0) + { + return 0; + } + } + + // If not, add the handler to the list. + this->m_MessageHandlerList.push_back(handler); + + return 1; +} + + +int SessionManager::RemoveMessageHandler(MessageHandler* handler) +{ + // Check if there is any handler for the same message type + std::vector< MessageHandler* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + { + if (*iter == handler) + { + this->m_MessageHandlerList.erase(iter); + return 1; + } + } + return 0; +} + + int SessionManager::Connect() { @@ -60,11 +100,9 @@ int SessionManager::Connect() int r = clientSocket->ConnectToServer(this->m_Hostname.c_str(), this->m_Port); if (r == 0) // if connected to server { - clientSocket->SetReceiveTimeout(0); + //clientSocket->SetReceiveTimeout(0); this->m_Socket = clientSocket; - return 1; } - //igtl::Sleep(1000); } else { @@ -76,7 +114,6 @@ int SessionManager::Connect() return 0; } - //std::cerr << this->GetClassName() << ": WaitForConnection(): Port number # = " << this->m_Port << std::endl; if (serverSocket.IsNotNull()) { //this->ServerSocket->CreateServer(this->m_Port); @@ -86,15 +123,20 @@ int SessionManager::Connect() if (this->m_Socket.IsNotNull() && this->m_Socket->GetConnected()) // if client connected { this->m_Socket->DebugOff(); - return 1; } - return 0; + else + { + return 0; + } } - return 0; - + this->m_Socket->SetReceiveBlocking(0); // Psuedo non-blocking + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; + return 1; } + int SessionManager::Disconnect() { if (this->m_Socket.IsNotNull()) @@ -105,95 +147,160 @@ int SessionManager::Disconnect() return 0; } - int SessionManager::ProcessMessage() { - // Initialize receive buffer - this->m_Header->InitPack(); - - // Receive generic header from the socket - int r = this->m_Socket->Receive(this->m_Header->GetPackPointer(), this->m_Header->GetPackSize()); - if (r == 0) + // The workflow of this function is as follows: + // + // HEADER: + // IF the message is (a) a new message: + // start reading the header; + // ELSE IF the message is a message in progress: + // if the process is reading the header: + // continue to read the header; + // ELSE: + // GOTO BODY; + // + // IF the header has not been received: + // GOTO BODY; + // ELSE + // RETURN; + // + // BODY: + // IF the process has not started reading the body: + // check the body type; + // find an appropriate handler; + // start reading the body + // ELSE: + // continue to read the body + // + + //-------------------------------------------------- + // Header + if (this->m_CurrentReadIndex == 0) { - return 0; // Disconnected + // Initialize receive buffer + this->m_Header->InitPack(); + + // Receive generic header from the socket + int r = this->m_Socket->Receive(this->m_Header->GetPackPointer(), this->m_Header->GetPackSize(), 0); + if (r == 0) + { + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; + return 0; // Disconnected + } + if (r != this->m_Header->GetPackSize()) + { + // Only a part of header has arrived. + if (r < 0) // timeout + { + this->m_CurrentReadIndex = 0; + } + else + { + this->m_CurrentReadIndex = r; + } + return -1; + } + // The header has been received. + this->m_CurrentReadIndex = IGTL_HEADER_SIZE; } - if (r != this->m_Header->GetPackSize()) + else if (this->m_CurrentReadIndex < IGTL_HEADER_SIZE) { - return -1; + // Message transfer was interrupted in the header + int r = this->m_Socket->Receive((void*)((char*)this->m_Header->GetPackPointer()+this->m_CurrentReadIndex), + this->m_Header->GetPackSize()-this->m_CurrentReadIndex, 0); + if (r == 0) + { + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; + return 0; // Disconnected + } + if (r != this->m_Header->GetPackSize()-this->m_CurrentReadIndex) + { + // Only a part of header has arrived. + if (r > 0) // exclude a case of timeout + { + this->m_CurrentReadIndex += r; + } + return -1; + } + // The header has been received. + this->m_CurrentReadIndex = IGTL_HEADER_SIZE; } - // Deserialize the header - this->m_Header->Unpack(); - - // Get time stamp - igtlUint32 sec; - igtlUint32 nanosec; - - this->m_Header->GetTimeStamp(this->m_TimeStamp); - this->m_TimeStamp->GetTimeStamp(&sec, &nanosec); - - //std::cerr << "Time stamp: " - // << sec << "." << std::setw(9) << std::setfill('0') - // << nanosec << std::endl; - // Look for a message handler that matches to the message type. - int found = 0; - std::vector< MessageHandler* >::iterator iter; - for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + //-------------------------------------------------- + // Body + if (this->m_HeaderDeserialized == 0) { - if (strcmp(this->m_Header->GetDeviceType(), (*iter)->GetMessageType()) == 0) + // Deserialize the header + this->m_Header->Unpack(); + + // Get time stamp + igtlUint32 sec; + igtlUint32 nanosec; + + this->m_Header->GetTimeStamp(this->m_TimeStamp); + this->m_TimeStamp->GetTimeStamp(&sec, &nanosec); + //std::cerr << "Time stamp: " + // << sec << "." << std::setw(9) << std::setfill('0') + // << nanosec << std::endl; + + // Look for a message handler that matches to the message type. + int found = 0; + std::vector< MessageHandler* >::iterator iter; + for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) { - (*iter)->ReceiveMessage(this->m_Socket, this->m_Header); - //iter = this->m_MessageHandlerList.end(); - found = 1; - break; + if (strcmp(this->m_Header->GetDeviceType(), (*iter)->GetMessageType()) == 0) + { + this->m_CurrentMessageHandler = *iter; + found = 1; + break; + } } + + // If there is no message handler, skip the message + if (!found) + { + std::cerr << "Receiving: " << this->m_Header->GetDeviceType() << std::endl; + this->m_Socket->Skip(this->m_Header->GetBodySizeToRead(), 0); + // Reset the index counter to be ready for the next message + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; + return 1; + } + + this->m_HeaderDeserialized = 1; } - // If there is no message handler, skip the message - if (!found) + int r = this->m_CurrentMessageHandler->ReceiveMessage(this->m_Socket, this->m_Header, + this->m_CurrentReadIndex-IGTL_HEADER_SIZE); + if (r == this->m_Header->GetBodySizeToRead()) + { + this->m_CurrentReadIndex = 0; + this->m_HeaderDeserialized = 0; + } + else { - std::cerr << "Receiving : " << this->m_Header->GetDeviceType() << std::endl; - this->m_Socket->Skip(this->m_Header->GetBodySizeToRead(), 0); + this->m_CurrentReadIndex += IGTL_HEADER_SIZE + r; } return 1; - } -int SessionManager::AddMessageHandler(MessageHandler* handler) +int SessionManager::PushMessage(MessageBase* message) { - // Check if there is any handler for the same message type - std::vector< MessageHandler* >::iterator iter; - for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + + if (message && this->m_Socket.IsNotNull() && this->m_Socket->GetConnected()) // if client connected { - if (strcmp((*iter)->GetMessageType(), handler->GetMessageType()) == 0) - { - return 0; - } + return this->m_Socket->Send(message->GetPackPointer(), message->GetPackSize()); } - - // If not, add the handler to the list. - this->m_MessageHandlerList.push_back(handler); - - return 1; -} - - -int SessionManager::RemoveMessageHandler(MessageHandler* handler) -{ - // Check if there is any handler for the same message type - std::vector< MessageHandler* >::iterator iter; - for (iter = this->m_MessageHandlerList.begin(); iter != this->m_MessageHandlerList.end(); iter ++) + else { - if (*iter == handler) - { - this->m_MessageHandlerList.erase(iter); - return 1; - } + return 0; } - return 0; } diff --git a/Source/igtlSessionManager.h b/Source/igtlSessionManager.h index 372805b2..a544ea16 100644 --- a/Source/igtlSessionManager.h +++ b/Source/igtlSessionManager.h @@ -52,12 +52,19 @@ class IGTLCommon_EXPORT SessionManager: public Object // Set the role of session manager. Either MODE_SERVER or MODE_CLIENT void SetMode(int m) {this->m_Mode = m; this->m_ConfigurationUpdated = true; } int GetMode(int m) {return this->m_Mode = m; } - int Connect(); - int ProcessMessage(); - int Disconnect(); + + // Description: + // Register / Unregister a message handler int AddMessageHandler(MessageHandler*); int RemoveMessageHandler(MessageHandler*); + // Description: + // Functions to manage the session + int Connect(); + int Disconnect(); + int ProcessMessage(); + int PushMessage(MessageBase*); + protected: SessionManager(); ~SessionManager(); @@ -68,6 +75,15 @@ class IGTLCommon_EXPORT SessionManager: public Object int m_Port; int m_Mode; + // Description: + // m_CurrentReadIndex is used to save the current position of the message. + // The index becomes >0 when message transfer is interrupted and only a part + // of message has arrived. + int m_CurrentReadIndex; + int m_HeaderDeserialized; + + MessageHandler* m_CurrentMessageHandler; + std::vector< MessageHandler* > m_MessageHandlerList; Socket::Pointer m_Socket; diff --git a/Source/igtlSocket.cxx b/Source/igtlSocket.cxx index 05aaa303..3a9284c1 100644 --- a/Source/igtlSocket.cxx +++ b/Source/igtlSocket.cxx @@ -359,10 +359,12 @@ int Socket::Receive(void* data, int length, int readFully/*=1*/) #if defined(_WIN32) && !defined(__CYGWIN__) int trys = 0; #endif + int n = recv(this->m_SocketDescriptor, buffer+total, length-total, 0); - if(n < 1) - { + #if defined(_WIN32) && !defined(__CYGWIN__) + if(n == 0) + { // On long messages, Windows recv sometimes fails with WSAENOBUFS, but // will work if you try again. int error = WSAGetLastError(); @@ -371,10 +373,27 @@ int Socket::Receive(void* data, int length, int readFully/*=1*/) Sleep(1); continue; } -#endif // FIXME : Use exceptions ? igtlErrorMacro("Socket Error: Receive failed."); return 0; } + else if (n < 0) + { + // TODO: Need to check if this means timeout. + return -1; + } +#else + if(n == 0) // Disconnected + { + // FIXME : Use exceptions ? igtlErrorMacro("Socket Error: Receive failed."); + return 0; + } + else if (n < 0) // Error (including time out) + { + // TODO: If it is time-out, errno == EAGAIN + return -1; + } +#endif + total += n; } while(readFully && total < length); return total; @@ -466,6 +485,108 @@ int Socket::SetSendTimeout(int timeout) //----------------------------------------------------------------------------- +int Socket::SetReceiveBlocking(int sw) +{ + if (!this->GetConnected()) + { + return 0; + } + + // If sw == 1, timeout is set to 0 (wait until it receives message) +#if defined(_WIN32) && !defined(__CYGWIN__) + if (sw==0) + { + this->m_ReceiveTimeout = 1; + } + else + { + this->m_ReceiveTimeout = 0; + } + int len; +#else + if (sw==0) + { + this->m_ReceiveTimeout.tv_sec = 0; /* second */ + this->m_ReceiveTimeout.tv_usec = 1; /* nanosecond */ + } + else + { + this->m_ReceiveTimeout.tv_sec = 0; /* second */ + this->m_ReceiveTimeout.tv_usec = 0; /* nanosecond */ + } + socklen_t len; +#endif + if (sw==0) + { + getsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_RCVTIMEO, + (char*)&(this->m_OrigReceiveTimeout), &len); + setsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_RCVTIMEO, + (char*)&(this->m_ReceiveTimeout), sizeof(this->m_ReceiveTimeout)); + this->m_ReceiveTimeoutFlag = 1; + } + else if (this->m_ReceiveTimeoutFlag) + { + setsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_RCVTIMEO, + (char*)&(this->m_OrigReceiveTimeout), sizeof(this->m_OrigReceiveTimeout)); + this->m_ReceiveTimeoutFlag = 0; + } + + return sw; +} + + +//----------------------------------------------------------------------------- +int Socket::SetSendBlocking(int sw) +{ + if (!this->GetConnected()) + { + return 0; + } + + // If sw == 1, timeout is set to 0 (wait until it receives message) +#if defined(_WIN32) && !defined(__CYGWIN__) + if (sw==0) + { + this->m_ReceiveTimeout = 1; + } + else + { + this->m_ReceiveTimeout = 0; + } + int len; +#else + if (sw==0) + { + this->m_ReceiveTimeout.tv_sec = 0; /* second */ + this->m_ReceiveTimeout.tv_usec = 1; /* nanosecond */ + } + else + { + this->m_ReceiveTimeout.tv_sec = 0; /* second */ + this->m_ReceiveTimeout.tv_usec = 0; /* nanosecond */ + } + socklen_t len; +#endif + if (sw==0) + { + getsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_SNDTIMEO, + (char*)&(this->m_OrigSendTimeout), &len); + setsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_SNDTIMEO, + (char*)&(this->m_SendTimeout), sizeof(this->m_SendTimeout)); + this->m_SendTimeoutFlag = 1; + } + else if (this->m_SendTimeoutFlag) + { + setsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_SNDTIMEO, + (char*)&(this->m_OrigSendTimeout), sizeof(this->m_OrigSendTimeout)); + this->m_SendTimeoutFlag = 0; + } + + return sw; +} + + +//----------------------------------------------------------------------------- int Socket::GetSocketAddressAndPort(std::string& address, int& port) { struct sockaddr_in sockinfo; diff --git a/Source/igtlSocket.h b/Source/igtlSocket.h index d99b906e..27248778 100644 --- a/Source/igtlSocket.h +++ b/Source/igtlSocket.h @@ -116,6 +116,16 @@ class IGTLCommon_EXPORT Socket : public Object int SetSendTimeout(int timeout); // Description: + // Set (psuedo) non-blocking mode for recv(). When sw=1, the time out is set to + // minimum value (1 microsecond in UNIX, 1 millisecond in Windows) for receiving. + int SetReceiveBlocking(int sw); + + // Description: + // Set (psuedo) non-blocking mode for recv(). When sw=1, the time out is set to + // minimum value (1 microsecond in UNIX, 1 millisecond in Windows) for sending. + int SetSendBlocking(int sw); + + // Description: // Get socket address int GetSocketAddressAndPort(std::string& address, int & port); From 98783c820b121ce26d87c9f42cfd7567a3183d0a Mon Sep 17 00:00:00 2001 From: Laurent Chauvin Date: Mon, 15 Oct 2012 10:56:42 -0300 Subject: [PATCH 05/53] Modified GetMode method --- Source/igtlSessionManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/igtlSessionManager.h b/Source/igtlSessionManager.h index a544ea16..71042c09 100644 --- a/Source/igtlSessionManager.h +++ b/Source/igtlSessionManager.h @@ -51,7 +51,7 @@ class IGTLCommon_EXPORT SessionManager: public Object // Description: // Set the role of session manager. Either MODE_SERVER or MODE_CLIENT void SetMode(int m) {this->m_Mode = m; this->m_ConfigurationUpdated = true; } - int GetMode(int m) {return this->m_Mode = m; } + int GetMode() {return this->m_Mode; } // Description: // Register / Unregister a message handler From 6a37243b1ef1e918913bf3e8ff32241c37c94f20 Mon Sep 17 00:00:00 2001 From: Laurent Chauvin Date: Wed, 7 Nov 2012 18:59:47 -0500 Subject: [PATCH 06/53] Add igtlMessageHandlerMacro.h to the list of files --- Source/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 26c3e48a..c8c93623 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -68,6 +68,7 @@ SET(OpenIGTLink_INCLUDE_FILES igtlutil/igtl_util.h igtlutil/igtl_capability.h igtlMessageHandler.h + igtlMessageHandlerMacro.h igtlClientSocket.h igtlConditionVariable.h igtlCreateObjectFunction.h From 61557a7f66fc662f6b14a0ac85c0dc3a4b1cfeb3 Mon Sep 17 00:00:00 2001 From: Gergely Zombori Date: Mon, 12 Nov 2012 13:31:24 +0000 Subject: [PATCH 07/53] Bug #1912 - Merged the changes and enhancements from upstream into 'master' --- CMakeLists.txt | 2 +- Source/igtlPositionMessage.cxx | 83 ++++++++++++++++++++++++++++++++++++----- Source/igtlPositionMessage.h | 1 + Source/igtlutil/igtl_position.c | 40 ++++++++++++++++++++ Source/igtlutil/igtl_position.h | 3 +- 5 files changed, 117 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4af6bf1d..c4a23006 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "9") -SET(OpenIGTLink_VERSION_PATCH "5") +SET(OpenIGTLink_VERSION_PATCH "6") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Source/igtlPositionMessage.cxx b/Source/igtlPositionMessage.cxx index 9a6820a1..e03b43be 100644 --- a/Source/igtlPositionMessage.cxx +++ b/Source/igtlPositionMessage.cxx @@ -19,7 +19,8 @@ #include "igtl_header.h" #include "igtl_position.h" -#include +#include +#include namespace igtl { @@ -179,6 +180,7 @@ int PositionMessage::GetBodyPackSize() break; default: ret = IGTL_POSITION_MESSAGE_DEFAULT_SIZE; + break; } return ret; @@ -197,11 +199,21 @@ int PositionMessage::PackBody() p->position[1] = this->m_Position[1]; p->position[2] = this->m_Position[2]; - p->quaternion[0] = this->m_Quaternion[0]; - p->quaternion[1] = this->m_Quaternion[1]; - p->quaternion[2] = this->m_Quaternion[2]; - p->quaternion[3] = this->m_Quaternion[3]; + if (this->m_PackType == WITH_QUATERNION3) + { + p->quaternion[0] = this->m_Quaternion[0]; + p->quaternion[1] = this->m_Quaternion[1]; + p->quaternion[2] = this->m_Quaternion[2]; + } + else if (this->m_PackType == ALL) + { + p->quaternion[0] = this->m_Quaternion[0]; + p->quaternion[1] = this->m_Quaternion[1]; + p->quaternion[2] = this->m_Quaternion[2]; + p->quaternion[3] = this->m_Quaternion[3]; + } + igtl_position_convert_byte_order(p); return 1; @@ -212,16 +224,67 @@ int PositionMessage::UnpackBody() igtl_position* p = (igtl_position*)this->m_Body; - igtl_position_convert_byte_order(p); + int bodySize = this->m_PackSize - IGTL_HEADER_SIZE; + switch (bodySize) + { + case IGTL_POSITION_MESSAGE_POSITON_ONLY_SIZE: + this->m_PackType = POSITION_ONLY; + igtl_position_convert_byte_order_position_only(p); + break; + case IGTL_POSITION_MESSAGE_WITH_QUATERNION3_SIZE: + this->m_PackType = WITH_QUATERNION3; + igtl_position_convert_byte_order_quaternion3(p); + break; + default: //IGTL_POSITION_MESSAGE_DEFAULT_SIZE + this->m_PackType = ALL; + igtl_position_convert_byte_order(p); + break; + } this->m_Position[0] = p->position[0]; this->m_Position[1] = p->position[1]; this->m_Position[2] = p->position[2]; - this->m_Quaternion[0] = p->quaternion[0]; - this->m_Quaternion[1] = p->quaternion[1]; - this->m_Quaternion[2] = p->quaternion[2]; - this->m_Quaternion[3] = p->quaternion[3]; + if (this->m_PackType == POSITION_ONLY) + { + this->m_Quaternion[0] = 0.0; + this->m_Quaternion[1] = 0.0; + this->m_Quaternion[2] = 0.0; + this->m_Quaternion[3] = 1.0; + } + + if (this->m_PackType == WITH_QUATERNION3) + { + float ox = p->quaternion[0]; + float oy = p->quaternion[1]; + float oz = p->quaternion[2]; + float sq = 1.0 - (ox*ox + oy*oy + oz*oz); + if (sq < 0.0) + { + // TODO: what should we do with invalid quaternion? + // Tentatively we set (0, 0, 0, 1); + this->m_Quaternion[0] = 0.0; + this->m_Quaternion[1] = 0.0; + this->m_Quaternion[2] = 0.0; + this->m_Quaternion[3] = 1.0; + } + else + { + float w = sqrt(sq); + this->m_Quaternion[0] = ox; + this->m_Quaternion[1] = oy; + this->m_Quaternion[2] = oz; + this->m_Quaternion[3] = w; + } + } + else if (this->m_PackType == ALL) + { + this->m_Quaternion[0] = p->quaternion[0]; + this->m_Quaternion[1] = p->quaternion[1]; + this->m_Quaternion[2] = p->quaternion[2]; + this->m_Quaternion[3] = p->quaternion[3]; + } + return 1; } diff --git a/Source/igtlPositionMessage.h b/Source/igtlPositionMessage.h index 42532163..6b4741e3 100644 --- a/Source/igtlPositionMessage.h +++ b/Source/igtlPositionMessage.h @@ -50,6 +50,7 @@ class IGTLCommon_EXPORT PositionMessage: public MessageBase void Init(); void SetPackType(int t); /* POSITION_ONLY / WITH_QUATERNION3 / ALL */ + int GetPackType() { return m_PackType; }; /** Specify pack type by body size (in most case obtained from general header) */ int SetPackTypeByBodySize(int s); diff --git a/Source/igtlutil/igtl_position.c b/Source/igtlutil/igtl_position.c index 03bffb7e..dd756c83 100644 --- a/Source/igtlutil/igtl_position.c +++ b/Source/igtlutil/igtl_position.c @@ -45,6 +45,46 @@ void igtl_export igtl_position_convert_byte_order(igtl_position* pos) } } +void igtl_export igtl_position_convert_byte_order_position_only(igtl_position* pos) +{ + + igtl_uint32 tmp[4]; + + if (igtl_is_little_endian()) + { + /* position */ + memcpy((void*)tmp, (void*)(pos->position), sizeof(igtl_float32)*3); + tmp[0] = BYTE_SWAP_INT32(tmp[0]); + tmp[1] = BYTE_SWAP_INT32(tmp[1]); + tmp[2] = BYTE_SWAP_INT32(tmp[2]); + memcpy((void*)(pos->position), (void*)tmp, sizeof(igtl_float32)*3); + } +} + +void igtl_export igtl_position_convert_byte_order_quaternion3(igtl_position* pos) +{ + + igtl_uint32 tmp[4]; + + if (igtl_is_little_endian()) + { + /* position */ + memcpy((void*)tmp, (void*)(pos->position), sizeof(igtl_float32)*3); + tmp[0] = BYTE_SWAP_INT32(tmp[0]); + tmp[1] = BYTE_SWAP_INT32(tmp[1]); + tmp[2] = BYTE_SWAP_INT32(tmp[2]); + memcpy((void*)(pos->position), (void*)tmp, sizeof(igtl_float32)*3); + + /* quaternion */ + memcpy((void*)tmp, (void*)(pos->quaternion), sizeof(igtl_float32)*3); + tmp[0] = BYTE_SWAP_INT32(tmp[0]); + tmp[1] = BYTE_SWAP_INT32(tmp[1]); + tmp[2] = BYTE_SWAP_INT32(tmp[2]); + memcpy((void*)(pos->quaternion), (void*)tmp, sizeof(igtl_float32)*3); + } + +} + igtl_uint64 igtl_export igtl_position_get_crc(igtl_position* pos) { diff --git a/Source/igtlutil/igtl_position.h b/Source/igtlutil/igtl_position.h index 178ed0a0..275e2073 100644 --- a/Source/igtlutil/igtl_position.h +++ b/Source/igtlutil/igtl_position.h @@ -53,7 +53,8 @@ typedef struct { */ void igtl_export igtl_position_convert_byte_order(igtl_position* pos); - +void igtl_export igtl_position_convert_byte_order_position_only(igtl_position* pos); +void igtl_export igtl_position_convert_byte_order_quaternion3(igtl_position* pos); /* * CRC calculation From 4caf9cfa490fdc195b39e580eb9730b89939ab56 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 18 Dec 2012 21:21:18 -0500 Subject: [PATCH 08/53] ENH: added the second argument for Process() in the message handler class to share data between the message handler class and other classes/functions outside the class. --- Examples/SessionManager/SessionManagerServer.cxx | 57 ++++++++++++++++++++---- Source/igtlMessageHandlerMacro.h | 16 +++++-- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx index 7504aec8..51309b04 100644 --- a/Examples/SessionManager/SessionManagerServer.cxx +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -27,34 +27,59 @@ #include "igtlImageMessage.h" + +//------------------------------------------------------------ +// Define a structure type to share data between message +// handler classes and main() function. +// It can be any types e.g. C++ class, array, etc. +// In this example, the shared structure is only used for +// passing the message type and the device name from the +// handler to main() function. + +typedef struct { + std::string messagetype; + std::string devicename; +} MyData; + + //------------------------------------------------------------ // Define message handler classes for TransformMessage, -// PositionMessage and ImageMessage +// PositionMessage and ImageMessage. // igtlMessageHandlerClassMacro() defines a child class of // igtl::MessageHandler to handle OpenIGTLink messages for // the message type specified as the first argument. The // second argument will be used for the name of this -// message handler class. -igtlMessageHandlerClassMacro(igtl::TransformMessage, TransformHandler); -igtlMessageHandlerClassMacro(igtl::PositionMessage, PositionHandler); -igtlMessageHandlerClassMacro(igtl::ImageMessage, ImageHandler); +// message handler class, while the third argument specifies +// a type of data that will be shared with the message functions +// of this handler class. + +igtlMessageHandlerClassMacro(igtl::TransformMessage, TransformHandler, MyData); +igtlMessageHandlerClassMacro(igtl::PositionMessage, PositionHandler, MyData); +igtlMessageHandlerClassMacro(igtl::ImageMessage, ImageHandler, MyData); + //------------------------------------------------------------ // You need to describe how the received message is processed // in Process() function of the message handler class. +// When Process() is called, pointers to the received message +// and the shared data are passed as the arguments. // -- Transform message -int TransformHandler::Process(igtl::TransformMessage * transMsg) +int TransformHandler::Process(igtl::TransformMessage * transMsg, MyData* data) { // Retrive the transform data igtl::Matrix4x4 matrix; transMsg->GetMatrix(matrix); igtl::PrintMatrix(matrix); + + data->messagetype = transMsg->GetDeviceType(); + data->devicename = transMsg->GetDeviceName(); + return 1; } // -- Position message -int PositionHandler::Process(igtl::PositionMessage * positionMsg) +int PositionHandler::Process(igtl::PositionMessage * positionMsg, MyData* data) { // Retrive the transform data float position[3]; @@ -66,11 +91,15 @@ int PositionHandler::Process(igtl::PositionMessage * positionMsg) std::cerr << "position = (" << position[0] << ", " << position[1] << ", " << position[2] << ")" << std::endl; std::cerr << "quaternion = (" << quaternion[0] << ", " << quaternion[1] << ", " << quaternion[2] << ", " << quaternion[3] << ")" << std::endl << std::endl; + + data->messagetype = positionMsg->GetDeviceType(); + data->devicename = positionMsg->GetDeviceName(); + return 1; } // -- Image message -int ImageHandler::Process(igtl::ImageMessage * imgMsg) +int ImageHandler::Process(igtl::ImageMessage * imgMsg, MyData *data) { // Retrive the image data int size[3]; // image dimension @@ -94,6 +123,10 @@ int ImageHandler::Process(igtl::ImageMessage * imgMsg) << svsize[0] << ", " << svsize[1] << ", " << svsize[2] << ")" << std::endl; std::cerr << "Sub-Volume offset : (" << svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl; + + data->messagetype = imgMsg->GetDeviceType(); + data->devicename = imgMsg->GetDeviceName(); + return 1; } @@ -125,6 +158,11 @@ int main(int argc, char* argv[]) PositionHandler::Pointer pmh = PositionHandler::New(); ImageHandler::Pointer imh = ImageHandler::New(); + MyData mydata; + tmh->SetData(&mydata); + pmh->SetData(&mydata); + imh->SetData(&mydata); + //------------------------------------------------------------ // Register the message handlers to the session manager sm->AddMessageHandler(tmh); @@ -142,6 +180,9 @@ int main(int argc, char* argv[]) { break; } + std::cerr << "Message Type: " << tmh->GetData()->messagetype << std::endl; + std::cerr << "Device Name: " << tmh->GetData()->devicename << std::endl; + igtl::Sleep(400); // Wait for 400 ms } // Stop session diff --git a/Source/igtlMessageHandlerMacro.h b/Source/igtlMessageHandlerMacro.h index eeaa40df..7d80500b 100644 --- a/Source/igtlMessageHandlerMacro.h +++ b/Source/igtlMessageHandlerMacro.h @@ -43,7 +43,7 @@ // virtual void Process(messagetype*); \ // }; -#define igtlMessageHandlerClassMacro(messagetype, classname) \ +#define igtlMessageHandlerClassMacro(messagetype, classname, datatype) \ class classname : public ::igtl::MessageHandler \ { \ public: \ @@ -58,7 +58,7 @@ { \ return this->m_Message->GetDeviceType(); \ } \ - virtual int Process(messagetype*); \ + virtual int Process(messagetype*, datatype*); \ int ReceiveMessage(::igtl::Socket* socket, ::igtl::MessageBase* header, int pos) \ { \ if (pos == 0) /* New body */ \ @@ -77,7 +77,7 @@ int r = this->m_Message->Unpack(this->m_CheckCRC); \ if (r) \ { \ - Process(this->m_Message); \ + Process(this->m_Message, this->m_Data); \ } \ else \ { \ @@ -97,16 +97,26 @@ this->m_CheckCRC = 1; \ } \ } \ + void SetData(datatype* p) \ + { \ + this->m_Data = p; \ + } \ + datatype* GetData() \ + { \ + return this->m_Data; \ + } \ protected: \ classname() \ { \ this->m_Message = messagetype::New(); \ this->m_CheckCRC = 1; \ + this->m_Data = NULL; \ } \ ~classname() {} \ protected: \ int m_CheckCRC; \ messagetype::Pointer m_Message; \ + datatype* m_Data; \ }; #endif // __igtlMessageHandlerMacro_h From 56eceb34b40e36fb5116b8f7d46cec58ce7da373 Mon Sep 17 00:00:00 2001 From: Laurent Chauvin Date: Fri, 18 Jan 2013 17:01:03 -0500 Subject: [PATCH 09/53] ENH: Removed the sleep Otherwise it takes too long to receive transform (we are receiving all values between previous and next position, with a delay of 400ms between each value) --- Examples/SessionManager/SessionManagerServer.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Examples/SessionManager/SessionManagerServer.cxx b/Examples/SessionManager/SessionManagerServer.cxx index 7504aec8..2a076ba4 100644 --- a/Examples/SessionManager/SessionManagerServer.cxx +++ b/Examples/SessionManager/SessionManagerServer.cxx @@ -142,7 +142,6 @@ int main(int argc, char* argv[]) { break; } - igtl::Sleep(400); // Wait for 400 ms } // Stop session sm->Disconnect(); From 4c439641fa9192db757c6544f5412f1bbcc7a040 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 31 Jan 2013 19:30:49 -0500 Subject: [PATCH 10/53] ENH: Adding CapabilityMessage class --- Source/CMakeLists.txt | 2 + Source/igtlCapabilityMessage.cxx | 143 +++++++++++++++++++++++++++++++++++++++ Source/igtlCapabilityMessage.h | 90 ++++++++++++++++++++++++ Source/igtlLabelMetaMessage.cxx | 3 - 4 files changed, 235 insertions(+), 3 deletions(-) create mode 100755 Source/igtlCapabilityMessage.cxx create mode 100755 Source/igtlCapabilityMessage.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index c8c93623..88bb1966 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -119,6 +119,7 @@ if (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") igtlutil/igtl_qtrans.c igtlutil/igtl_polydata.c igtlColorTableMessage.cxx + igtlCapabilityMessage.cxx igtlImageMetaMessage.cxx igtlLabelMetaMessage.cxx igtlPointMessage.cxx @@ -149,6 +150,7 @@ if (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") igtlutil/igtl_qtrans.h igtlutil/igtl_polydata.h igtlColorTableMessage.h + igtlCapabilityMessage.h igtlImageMetaMessage.h igtlLabelMetaMessage.h igtlPointMessage.h diff --git a/Source/igtlCapabilityMessage.cxx b/Source/igtlCapabilityMessage.cxx new file mode 100755 index 00000000..1c690050 --- /dev/null +++ b/Source/igtlCapabilityMessage.cxx @@ -0,0 +1,143 @@ +/*========================================================================= + + Program: The OpenIGTLink Library + Module: + Language: C++ + Date: + Version: + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "igtlCapabilityMessage.h" + +#include + +#include +#include + +#include +#include + +// Disable warning C4996 (strncpy() may be unsafe) in Windows. +#define _CRT_SECURE_NO_WARNINGS + +#include + +namespace igtl { + +CapabilityMessage::CapabilityMessage(): + MessageBase() +{ + this->m_DefaultBodyType = "CAPABILITY"; + this->m_TypeNames.clear(); +} + + +CapabilityMessage::~CapabilityMessage() +{ + this->m_TypeNames.clear(); +} + + +void CapabilityMessage::SetTypes(int ntypes, const char typenames[][IGTL_HEADER_TYPE_SIZE]) +{ + this->m_TypeNames.clear(); + + for(int i = 0; i < ntypes; i++) + { + std::string buf; + if (strnlen(typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) + { + buf.append(typenames[i]); + } + else + { + buf.append(typenames[i], IGTL_HEADER_TYPE_SIZE); + } + this->m_TypeNames.push_back(buf); + } +} + + +void CapabilityMessage::SetTypes(std::vector types) +{ + this->m_TypeNames.clear(); + this->m_TypeNames = types; +} + + +int CapabilityMessage::GetBodyPackSize() +{ + return (sizeof(char) * IGTL_HEADER_TYPE_SIZE * this->m_TypeNames.size()); +} + + +int CapabilityMessage::PackBody() +{ + AllocatePack(); + + if (this->m_TypeNames.size() == 0) + { + return 0; + } + + igtl_capability_info info; + int nTypes = this->m_TypeNames.size(); + + igtl_capability_init_info(&info); + info.ntypes = nTypes; + igtl_capability_alloc_info(&info, nTypes); + + for(int i = 0; i < nTypes; i++ ) + { + memcpy(info.typenames[i], this->m_TypeNames[i].c_str(), IGTL_HEADER_TYPE_SIZE); + } + + igtl_capability_pack(&info, this->m_Body); + + return 1; +} + + +int CapabilityMessage::UnpackBody() +{ + + igtl_capability_info info; + + igtl_capability_init_info(&info); + igtl_capability_unpack(this->m_Body, &info, this->GetPackBodySize()); + + int ntypes = info.ntypes; + + if(ntypes == 0) + { + return 0; + } + + this->m_TypeNames.clear(); + for(unsigned int i = 0; i < ntypes; i++) + { + std::string buf; + if (strnlen((const char*)info.typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) + { + buf.append((const char*)info.typenames[i]); + } + else + { + buf.append((const char*)info.typenames[i], IGTL_HEADER_TYPE_SIZE); + } + this->m_TypeNames.push_back(buf); + } + + + return 1; +} + + +} // namespace igtl diff --git a/Source/igtlCapabilityMessage.h b/Source/igtlCapabilityMessage.h new file mode 100755 index 00000000..35777031 --- /dev/null +++ b/Source/igtlCapabilityMessage.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: The OpenIGTLink Library + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __igtlCapabilityMessage_h +#define __igtlCapabilityMessage_h + +#include +#include +#include +#include + +#include + +#include +#include + +namespace igtl +{ + +class IGTLCommon_EXPORT GetCapabilityMessage: public MessageBase +{ +public: + typedef GetCapabilityMessage Self; + typedef MessageBase Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::GetCapabilityMessage, igtl::MessageBase); + igtlNewMacro(igtl::GetCapabilityMessage); + +protected: + GetCapabilityMessage() : MessageBase() { this->m_DefaultBodyType = "GET_CAPABIL"; }; + ~GetCapabilityMessage() {}; +protected: + virtual int GetBodyPackSize() { return 0; }; + virtual int PackBody() { AllocatePack(); return 1; }; + virtual int UnpackBody() { return 1; }; +}; + + +class IGTLCommon_EXPORT CapabilityMessage: public MessageBase +{ + +public: + + typedef CapabilityMessage Self; + typedef MessageBase Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::CapabilityMessage, igtl::MessageBase); + igtlNewMacro(igtl::CapabilityMessage); + +public: + + void SetTypes(int ntypes, const char typenames[][IGTL_HEADER_TYPE_SIZE]); + void SetTypes(std::vector types); + int GetTypeLength(){ return IGTL_HEADER_TYPE_SIZE; } + int GetSize() { return m_TypeNames.size(); } + //char** GetTypeNames() { return m_TypeNames; } + std::vector GetTypes() { return m_TypeNames; } + +protected: + CapabilityMessage(); + ~CapabilityMessage(); + +protected: + + virtual int GetBodyPackSize(); + virtual int PackBody(); + virtual int UnpackBody(); + + std::vector m_TypeNames; + +}; + + +} // namespace igtl + +#endif // __igtlCapabilityMessage_h diff --git a/Source/igtlLabelMetaMessage.cxx b/Source/igtlLabelMetaMessage.cxx index b50b063c..af62a5eb 100644 --- a/Source/igtlLabelMetaMessage.cxx +++ b/Source/igtlLabelMetaMessage.cxx @@ -1,10 +1,7 @@ /*========================================================================= Program: Open IGT Link Library - Module: $HeadURL: http://svn.na-mic.org/NAMICSandBox/trunk/OpenIGTLink2_beta/Source/igtlStatusMessage.cxx $ Language: C++ - Date: $Date: 2010-01-17 13:04:20 -0500 (Sun, 17 Jan 2010) $ - Version: $Revision: 5575 $ Copyright (c) Insight Software Consortium. All rights reserved. From a9a41088b080ca48bb5dab0c3ae1ed2a861dab98 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 4 Mar 2013 18:44:52 -0500 Subject: [PATCH 11/53] ENH: Adding the capability message type and examples. --- Examples/CMakeLists.txt | 1 + Examples/Capability/CMakeLists.txt | 18 +++++++ Examples/Capability/CapabilityClient.cxx | 86 ++++++++++++++++++++++++++++++ Examples/Capability/CapabilityServer.cxx | 91 ++++++++++++++++++++++++++++++++ Examples/Receiver/ReceiveClient.cxx | 37 +++++++++++++ Examples/Receiver/ReceiveServer.cxx | 39 ++++++++++++++ Source/igtlCapabilityMessage.cxx | 57 ++++++++++++++------ Source/igtlCapabilityMessage.h | 11 ++-- 8 files changed, 320 insertions(+), 20 deletions(-) create mode 100644 Examples/Capability/CMakeLists.txt create mode 100644 Examples/Capability/CapabilityClient.cxx create mode 100644 Examples/Capability/CapabilityServer.cxx diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 6d7af02a..4e4a0430 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -25,6 +25,7 @@ if (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") String Bind PolyData + Capability ) endif (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") diff --git a/Examples/Capability/CMakeLists.txt b/Examples/Capability/CMakeLists.txt new file mode 100644 index 00000000..dac2a764 --- /dev/null +++ b/Examples/Capability/CMakeLists.txt @@ -0,0 +1,18 @@ +PROJECT(Capability) + +cmake_minimum_required(VERSION 2.4) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +find_package(OpenIGTLink REQUIRED) + +include(${OpenIGTLink_USE_FILE}) + +ADD_EXECUTABLE(CapabilityClient CapabilityClient.cxx) +TARGET_LINK_LIBRARIES(CapabilityClient OpenIGTLink) + +ADD_EXECUTABLE(CapabilityServer CapabilityServer.cxx) +TARGET_LINK_LIBRARIES(CapabilityServer OpenIGTLink) + + diff --git a/Examples/Capability/CapabilityClient.cxx b/Examples/Capability/CapabilityClient.cxx new file mode 100644 index 00000000..4eb1b883 --- /dev/null +++ b/Examples/Capability/CapabilityClient.cxx @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: OpenIGTLink -- Example for Sending Capability Messasge + Module: $RCSfile: $ + Language: C++ + Date: $Date: $ + Version: $Revision: $ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlCapabilityMessage.h" +#include "igtlClientSocket.h" + +#include "igtlTransformMessage.h" +#include "igtlImageMessage.h" +#include "igtlLabelMetaMessage.h" + +// +// Test comment +// + + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 3) // check number of arguments + { + // If not correct, print usage + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : IP or host name" << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + char* hostname = argv[1]; + int port = atoi(argv[2]); + int interval = (int) (1000); + + //------------------------------------------------------------ + // Establish Connection + + igtl::ClientSocket::Pointer socket; + socket = igtl::ClientSocket::New(); + int r = socket->ConnectToServer(hostname, port); + + if (r != 0) + { + std::cerr << "Cannot connect to the server." << std::endl; + exit(0); + } + + //------------------------------------------------------------ + // Allocate Capability Message Class + + igtl::CapabilityMessage::Pointer capabilityMsg; + capabilityMsg = igtl::CapabilityMessage::New(); + capabilityMsg->SetDeviceName("Device"); + + std::vector types; + types.push_back(std::string("TRANSFORM")); + types.push_back(std::string("GET_IMAGE")); + types.push_back(std::string("GET_LBMETA")); + capabilityMsg->SetTypes(types); + capabilityMsg->Pack(); + socket->Send(capabilityMsg->GetPackPointer(), capabilityMsg->GetPackSize()); + //------------------------------------------------------------ + // Close connection + + socket->CloseSocket(); + +} + + diff --git a/Examples/Capability/CapabilityServer.cxx b/Examples/Capability/CapabilityServer.cxx new file mode 100644 index 00000000..15476aeb --- /dev/null +++ b/Examples/Capability/CapabilityServer.cxx @@ -0,0 +1,91 @@ +/*========================================================================= + + Program: Open IGT Link -- Example for Tracker Server Program + Module: $RCSfile: $ + Language: C++ + Date: $Date: $ + Version: $Revision: $ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlCapabilityMessage.h" +#include "igtlServerSocket.h" + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 2) // check number of arguments + { + // If not correct, print usage + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + int port = atoi(argv[1]); + int interval = (int) 1000; + + //------------------------------------------------------------ + // Allocate Capability Message Class + + igtl::CapabilityMessage::Pointer capabilityMsg; + capabilityMsg = igtl::CapabilityMessage::New(); + capabilityMsg->SetDeviceName("Device"); + + igtl::ServerSocket::Pointer serverSocket; + serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + + igtl::Socket::Pointer socket; + + while (1) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + + if (socket.IsNotNull()) // if client connected + { + //------------------------------------------------------------ + // loop + for (int i = 0; i < 100; i ++) + { + std::vector types; + types.push_back(std::string("TRANSFORM")); + types.push_back(std::string("GET_IMAGE")); + types.push_back(std::string("GET_LBMETA")); + capabilityMsg->SetTypes(types); + capabilityMsg->Pack(); + socket->Send(capabilityMsg->GetPackPointer(), capabilityMsg->GetPackSize()); + igtl::Sleep(interval); // wait + } + } + } + + //------------------------------------------------------------ + // Close connection (The example code never reachs to this section ...) + + socket->CloseSocket(); + +} + + diff --git a/Examples/Receiver/ReceiveClient.cxx b/Examples/Receiver/ReceiveClient.cxx index 5882f523..db248b18 100644 --- a/Examples/Receiver/ReceiveClient.cxx +++ b/Examples/Receiver/ReceiveClient.cxx @@ -33,6 +33,7 @@ #include "igtlStringMessage.h" #include "igtlTrackingDataMessage.h" #include "igtlQuaternionTrackingDataMessage.h" +#include "igtlCapabilityMessage.h" #endif // OpenIGTLink_PROTOCOL_VERSION >= 2 int ReceiveTransform(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); @@ -45,6 +46,7 @@ int ReceiveStatus(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); int ReceiveString(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); int ReceiveTrackingData(igtl::ClientSocket::Pointer& socket, igtl::MessageHeader::Pointer& header); int ReceiveQuaternionTrackingData(igtl::ClientSocket::Pointer& socket, igtl::MessageHeader::Pointer& header); + int ReceiveCapability(igtl::Socket * socket, igtl::MessageHeader * header); #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 int main(int argc, char* argv[]) @@ -157,6 +159,10 @@ int main(int argc, char* argv[]) { ReceiveQuaternionTrackingData(socket, headerMsg); } + else if (strcmp(headerMsg->GetDeviceType(), "CAPABILITY") == 0) + { + ReceiveCapability(socket, headerMsg);; + } #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 else { @@ -478,4 +484,35 @@ int ReceiveQuaternionTrackingData(igtl::ClientSocket::Pointer& socket, igtl::Mes return 0; } +int ReceiveCapability(igtl::Socket * socket, igtl::MessageHeader * header) +{ + + std::cerr << "Receiving CAPABILITY data type." << std::endl; + + // Create a message buffer to receive transform data + igtl::CapabilityMessage::Pointer capabilMsg; + capabilMsg = igtl::CapabilityMessage::New(); + capabilMsg->SetMessageHeader(header); + capabilMsg->AllocatePack(); + + // Receive transform data from the socket + socket->Receive(capabilMsg->GetPackBodyPointer(), capabilMsg->GetPackBodySize()); + + // Deserialize the transform data + // If you want to skip CRC check, call Unpack() without argument. + int c = capabilMsg->Unpack(1); + + if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK + { + int nTypes = capabilMsg->GetNumberOfTypes(); + for (int i = 0; i < nTypes; i ++) + { + std::cerr << "Typename #" << i << ": " << capabilMsg->GetType(i) << std::endl; + } + } + + return 1; + +} + #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 diff --git a/Examples/Receiver/ReceiveServer.cxx b/Examples/Receiver/ReceiveServer.cxx index 16ee5ea8..3c8ecc64 100644 --- a/Examples/Receiver/ReceiveServer.cxx +++ b/Examples/Receiver/ReceiveServer.cxx @@ -32,6 +32,7 @@ #include "igtlPointMessage.h" #include "igtlStringMessage.h" #include "igtlBindMessage.h" +#include "igtlCapabilityMessage.h" #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 @@ -44,6 +45,7 @@ int ReceiveStatus(igtl::Socket * socket, igtl::MessageHeader * header); int ReceivePoint(igtl::Socket * socket, igtl::MessageHeader * header); int ReceiveString(igtl::Socket * socket, igtl::MessageHeader * header); int ReceiveBind(igtl::Socket * socket, igtl::MessageHeader * header); +int ReceiveCapability(igtl::Socket * socket, igtl::MessageHeader * header); #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 int main(int argc, char* argv[]) @@ -153,6 +155,10 @@ int main(int argc, char* argv[]) { ReceiveBind(socket, headerMsg); } + else if (strcmp(headerMsg->GetDeviceType(), "CAPABILITY") == 0) + { + ReceiveCapability(socket, headerMsg); + } #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 else { @@ -453,4 +459,37 @@ int ReceiveBind(igtl::Socket * socket, igtl::MessageHeader * header) return 1; } + +int ReceiveCapability(igtl::Socket * socket, igtl::MessageHeader * header) +{ + + std::cerr << "Receiving CAPABILITY data type." << std::endl; + + // Create a message buffer to receive transform data + igtl::CapabilityMessage::Pointer capabilMsg; + capabilMsg = igtl::CapabilityMessage::New(); + capabilMsg->SetMessageHeader(header); + capabilMsg->AllocatePack(); + + // Receive transform data from the socket + socket->Receive(capabilMsg->GetPackBodyPointer(), capabilMsg->GetPackBodySize()); + + // Deserialize the transform data + // If you want to skip CRC check, call Unpack() without argument. + int c = capabilMsg->Unpack(1); + + if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK + { + int nTypes = capabilMsg->GetNumberOfTypes(); + for (int i = 0; i < nTypes; i ++) + { + std::cerr << "Typename #" << i << ": " << capabilMsg->GetType(i) << std::endl; + } + } + + return 1; + +} + + #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 diff --git a/Source/igtlCapabilityMessage.cxx b/Source/igtlCapabilityMessage.cxx index 1c690050..005be20e 100755 --- a/Source/igtlCapabilityMessage.cxx +++ b/Source/igtlCapabilityMessage.cxx @@ -45,30 +45,57 @@ CapabilityMessage::~CapabilityMessage() } -void CapabilityMessage::SetTypes(int ntypes, const char typenames[][IGTL_HEADER_TYPE_SIZE]) +//void CapabilityMessage::SetTypes(int ntypes, const char names[][IGTL_HEADER_TYPE_SIZE]) +//{ +// this->m_TypeNames.clear(); +// +// for(int i = 0; i < ntypes; i++) +// { +// std::string buf; +// if (strnlen(names[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) +// { +// buf.append(names[i]); +// } +// else +// { +// buf.append(names[i], IGTL_HEADER_TYPE_SIZE); +// } +// this->m_TypeNames.push_back(buf); +// } +//} + + +void CapabilityMessage::SetTypes(std::vector types) { this->m_TypeNames.clear(); + this->m_TypeNames = types; +} + - for(int i = 0; i < ntypes; i++) +int CapabilityMessage::SetType(int id, const char* type) +{ + if (id < this->m_TypeNames.size() && strlen(type) < IGTL_HEADER_TYPE_SIZE) { - std::string buf; - if (strnlen(typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) - { - buf.append(typenames[i]); - } - else - { - buf.append(typenames[i], IGTL_HEADER_TYPE_SIZE); - } - this->m_TypeNames.push_back(buf); + this->m_TypeNames[id] = type; + return 1; + } + else + { + return 0; } } -void CapabilityMessage::SetTypes(std::vector types) +const char* CapabilityMessage::GetType(int id) { - this->m_TypeNames.clear(); - this->m_TypeNames = types; + if (id < this->m_TypeNames.size()) + { + return this->m_TypeNames[id].c_str(); + } + else + { + return ""; + } } diff --git a/Source/igtlCapabilityMessage.h b/Source/igtlCapabilityMessage.h index 35777031..762f86f0 100755 --- a/Source/igtlCapabilityMessage.h +++ b/Source/igtlCapabilityMessage.h @@ -19,8 +19,6 @@ #include #include -#include - #include #include @@ -63,10 +61,13 @@ class IGTLCommon_EXPORT CapabilityMessage: public MessageBase public: - void SetTypes(int ntypes, const char typenames[][IGTL_HEADER_TYPE_SIZE]); + //void SetTypes(int ntypes, const char names[][IGTL_HEADER_TYPE_SIZE]); void SetTypes(std::vector types); - int GetTypeLength(){ return IGTL_HEADER_TYPE_SIZE; } - int GetSize() { return m_TypeNames.size(); } + int SetType(int id, const char* name); + const char* GetType(int id); + + int SetNumberOfTypes(int n) { m_TypeNames.resize(n); } + int GetNumberOfTypes() { return m_TypeNames.size(); } //char** GetTypeNames() { return m_TypeNames; } std::vector GetTypes() { return m_TypeNames; } From f93dba835ba1bafbe02172a1caa2376cb28974ec Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 11 Mar 2013 14:32:59 +0900 Subject: [PATCH 12/53] BUG: Fixed the compile error caused by the last commit. --- Source/igtlCapabilityMessage.h | 2 +- Source/igtlSocket.cxx | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Source/igtlCapabilityMessage.h b/Source/igtlCapabilityMessage.h index 762f86f0..e836c359 100755 --- a/Source/igtlCapabilityMessage.h +++ b/Source/igtlCapabilityMessage.h @@ -66,7 +66,7 @@ class IGTLCommon_EXPORT CapabilityMessage: public MessageBase int SetType(int id, const char* name); const char* GetType(int id); - int SetNumberOfTypes(int n) { m_TypeNames.resize(n); } + void SetNumberOfTypes(int n) { m_TypeNames.resize(n); } int GetNumberOfTypes() { return m_TypeNames.size(); } //char** GetTypeNames() { return m_TypeNames; } std::vector GetTypes() { return m_TypeNames; } diff --git a/Source/igtlSocket.cxx b/Source/igtlSocket.cxx index d76294d9..3a9284c1 100644 --- a/Source/igtlSocket.cxx +++ b/Source/igtlSocket.cxx @@ -361,12 +361,7 @@ int Socket::Receive(void* data, int length, int readFully/*=1*/) #endif int n = recv(this->m_SocketDescriptor, buffer+total, length-total, 0); - if (n < 0 && this->m_ReceiveTimeoutFlag) // Timeout - { - return -1; - } - if(n < 1) - { + #if defined(_WIN32) && !defined(__CYGWIN__) if(n == 0) { From 90b81581960c5ac7e24fafb5284459ca94babb40 Mon Sep 17 00:00:00 2001 From: Bonny Biswas Date: Mon, 11 Mar 2013 18:43:31 -0400 Subject: [PATCH 13/53] ENH: Added set/get methods for coordinate system in ImageMessage classes --- Source/igtlImageMessage.h | 4 ++++ Source/igtlImageMessage2.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Source/igtlImageMessage.h b/Source/igtlImageMessage.h index 5756ef93..0f2c6f1a 100644 --- a/Source/igtlImageMessage.h +++ b/Source/igtlImageMessage.h @@ -147,6 +147,10 @@ class IGTLCommon_EXPORT ImageMessage: public MessageBase void SetEndian(int e) { endian = e; }; int GetEndian() { return endian; }; + // Coordinate System: RAS=1/LPS=2 + int GetCoordinateSystem() { return coordinate;}; + void SetCoordinateSystem(int c) {coordinate = c;}; + // TBD: Should returned value be 64-bit integer? int GetImageSize() { diff --git a/Source/igtlImageMessage2.h b/Source/igtlImageMessage2.h index 9aab0221..eec0cd20 100644 --- a/Source/igtlImageMessage2.h +++ b/Source/igtlImageMessage2.h @@ -160,6 +160,10 @@ class IGTLCommon_EXPORT ImageMessage2: public MessageBase void SetEndian(int e) { endian = e; }; int GetEndian() { return endian; }; + // Coordinate System: RAS=1/LPS=2 + int GetCoordinateSystem() { return coordinate;}; + void SetCoordinateSystem(int c) {coordinate = c;}; + // TBD: Should returned value be 64-bit integer? int GetImageSize() { From d3554cfdc4e260a5a4578cf19d341f81fc260bfe Mon Sep 17 00:00:00 2001 From: Bonny Biswas Date: Mon, 11 Mar 2013 18:53:53 -0400 Subject: [PATCH 14/53] BUG: LPS coordinate system value in ImageMessage does not match protocol The COORDINATE_LPS enum value is 0 in the ImageMessage & ImageMessage2 classes, but the protocol says this should be 2. It is defined as 2 in igtl_image.h (IGTL_IMAGE_COORD_LPS). The enum has been changed so that the LPS value is 2. --- Source/igtlImageMessage.h | 4 ++-- Source/igtlImageMessage2.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/igtlImageMessage.h b/Source/igtlImageMessage.h index 0f2c6f1a..65244d54 100644 --- a/Source/igtlImageMessage.h +++ b/Source/igtlImageMessage.h @@ -61,8 +61,8 @@ class IGTLCommon_EXPORT ImageMessage: public MessageBase public: enum { - COORDINATE_LPS, - COORDINATE_RAS + COORDINATE_RAS=1, + COORDINATE_LPS=2 }; enum { diff --git a/Source/igtlImageMessage2.h b/Source/igtlImageMessage2.h index eec0cd20..49f1d730 100644 --- a/Source/igtlImageMessage2.h +++ b/Source/igtlImageMessage2.h @@ -74,8 +74,8 @@ class IGTLCommon_EXPORT ImageMessage2: public MessageBase public: enum { - COORDINATE_LPS, - COORDINATE_RAS + COORDINATE_RAS=1, + COORDINATE_LPS=2 }; enum { From 04aba78af3bdc05bc57f74e8090613d34773d5e7 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 28 Mar 2013 12:14:25 -0400 Subject: [PATCH 15/53] ENH: Add igtlCreateDefaultQueryMessageClass() macro to help defining a class for query message. --- Source/igtlMessageBase.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Source/igtlMessageBase.h b/Source/igtlMessageBase.h index e4584591..6fd8d411 100644 --- a/Source/igtlMessageBase.h +++ b/Source/igtlMessageBase.h @@ -26,6 +26,30 @@ #include +/// A macro to help defining a class for query message types +/// that do not have message bodies. +// TODO: Need test. +#define igtlCreateDefaultQueryMessageClass(name, msgtype) \ +class IGTLCommon_EXPORT name : public MessageBase \ +{ \ +public: \ + typedef GetColorTableMessage Self; \ + typedef MessageBase Superclass; \ + typedef SmartPointer Pointer; \ + typedef SmartPointer ConstPointer; \ + \ + igtlTypeMacro(igtl::name, igtl::MessageBase); \ + igtlNewMacro(igtl::name); \ + \ +protected: \ + name() : MessageBase() { this->m_DefaultBodyType = ##msgtype; }; \ + ~##name() {}; \ + \ +protected: \ + virtual int GetBodyPackSize() { return 0; }; \ + virtual int PackBody() { AllocatePack(); return 1; }; \ + virtual int UnpackBody() { return 1; }; \ +}; namespace igtl { From 47995c63fe5211fa551a2300fae22060f0fc7629 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 28 Mar 2013 13:23:35 -0400 Subject: [PATCH 16/53] ENH: Create HeaderOnlyMessageBase as a base class for query message types. --- Source/igtlImageMessage.h | 13 +++----- Source/igtlMessageBase.h | 73 ++++++++++++++++++++++++++++--------------- Source/igtlTransformMessage.h | 22 +++++++++++++ 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/Source/igtlImageMessage.h b/Source/igtlImageMessage.h index c4489311..d278ce58 100644 --- a/Source/igtlImageMessage.h +++ b/Source/igtlImageMessage.h @@ -24,27 +24,24 @@ namespace igtl { // A class for the GEt_IMAGE message type. -class IGTLCommon_EXPORT GetImageMessage: public MessageBase +class IGTLCommon_EXPORT GetImageMessage: public HeaderOnlyMessageBase { public: typedef GetImageMessage Self; - typedef MessageBase Superclass; + typedef HeaderOnlyMessageBase Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; - igtlTypeMacro(igtl::GetImageMessage, igtl::MessageBase); + igtlTypeMacro(igtl::GetImageMessage, igtl::HeaderOnlyMessageBase); igtlNewMacro(igtl::GetImageMessage); protected: - GetImageMessage() : MessageBase() { this->m_DefaultBodyType = "GET_IMAGE"; }; + GetImageMessage() : HeaderOnlyMessageBase() {}; ~GetImageMessage() {}; protected: - - virtual int GetBodyPackSize() { return 0; }; - virtual int PackBody() { AllocatePack(); return 1; }; - virtual int UnpackBody() { return 1; }; + virtual const char* DefaultBodyType() { return "GET_IMAGE"; }; }; diff --git a/Source/igtlMessageBase.h b/Source/igtlMessageBase.h index 6fd8d411..c308a127 100644 --- a/Source/igtlMessageBase.h +++ b/Source/igtlMessageBase.h @@ -26,31 +26,6 @@ #include -/// A macro to help defining a class for query message types -/// that do not have message bodies. -// TODO: Need test. -#define igtlCreateDefaultQueryMessageClass(name, msgtype) \ -class IGTLCommon_EXPORT name : public MessageBase \ -{ \ -public: \ - typedef GetColorTableMessage Self; \ - typedef MessageBase Superclass; \ - typedef SmartPointer Pointer; \ - typedef SmartPointer ConstPointer; \ - \ - igtlTypeMacro(igtl::name, igtl::MessageBase); \ - igtlNewMacro(igtl::name); \ - \ -protected: \ - name() : MessageBase() { this->m_DefaultBodyType = ##msgtype; }; \ - ~##name() {}; \ - \ -protected: \ - virtual int GetBodyPackSize() { return 0; }; \ - virtual int PackBody() { AllocatePack(); return 1; }; \ - virtual int UnpackBody() { return 1; }; \ -}; - namespace igtl { @@ -242,6 +217,54 @@ class IGTLCommon_EXPORT MessageBase: public Object }; +/// A class for header-only message types, which are used for quearying. +class IGTLCommon_EXPORT HeaderOnlyMessageBase: public MessageBase +{ +public: + typedef HeaderOnlyMessageBase Self; + typedef MessageBase Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::HeaderOnlyMessageBase, igtl::MessageBase); + igtlNewMacro(igtl::HeaderOnlyMessageBase); + +protected: + HeaderOnlyMessageBase() { this->m_DefaultBodyType = this->DefaultBodyType(); }; + ~HeaderOnlyMessageBase() {}; + +protected: + + virtual const char * DefaultBodyType() { return ""; }; // Must be defined in a child class. + virtual int GetBodyPackSize() { return 0; }; + virtual int PackBody() { AllocatePack(); return 1; }; + virtual int UnpackBody() { return 1; }; + +}; + + +/// A macro to help defining a class for query message types +/// that do not have message bodies. +// TODO: Need test. +#define igtlCreateDefaultQueryMessageClass(name, msgtype) \ +class IGTLCommon_EXPORT name : public HeaderOnlyMessageBase\ +{ \ +public: \ + typedef name Self; \ + typedef HeaderOnlyMessageBase Superclass; \ + typedef SmartPointer Pointer; \ + typedef SmartPointer ConstPointer; \ + \ + igtlTypeMacro(igtl::name, igtl::HeaderOnlyMessageBase); \ + igtlNewMacro(igtl::name); \ + \ +protected: \ + name() : HeaderOnlyMessageBase() {}; \ + ~name() {}; \ +protedted: \ + virtual const char* DefaultBodyType() { return msgtype; }; \ +}; + } // namespace igtl #endif // _igtlMessageBase_h diff --git a/Source/igtlTransformMessage.h b/Source/igtlTransformMessage.h index 0fb30b18..da1f3802 100644 --- a/Source/igtlTransformMessage.h +++ b/Source/igtlTransformMessage.h @@ -22,6 +22,28 @@ namespace igtl { +/// A class for the GET_TRANS message type. +class IGTLCommon_EXPORT GetTransformMessage: public HeaderOnlyMessageBase +{ +public: + typedef GetTransformMessage Self; + typedef HeaderOnlyMessageBase Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::GetTransformMessage, igtl::HeaderOnlyMessageBase); + igtlNewMacro(igtl::GetTransformMessage); + +protected: + GetTransformMessage(); + ~GetTransformMessage(); + +protected: + virtual const char* DefaultBodyType() { return "GET_TRANS"; }; +}; + + + /// The TRANSFORM data type is used to transfer a homogeneous linear transformation /// in 4-by-4 matrix form. One such matrix was shown earlier in equation (1). /// Note that if a device is sending only translation and rotation, then TRANSFORM From 14c889dffb4bb7cfcc11f52f1163ea958335374a Mon Sep 17 00:00:00 2001 From: Per Inge Mathisen Date: Fri, 3 May 2013 15:29:18 +0200 Subject: [PATCH 17/53] Fix wrong use of delete operator --- Source/igtlNDArrayMessage.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/igtlNDArrayMessage.cxx b/Source/igtlNDArrayMessage.cxx index 5a02d1bc..e348a8fa 100644 --- a/Source/igtlNDArrayMessage.cxx +++ b/Source/igtlNDArrayMessage.cxx @@ -215,7 +215,7 @@ int NDArrayMessage::PackBody() s[i] = size[i]; } int r = igtl_ndarray_alloc_info(&info, s); - delete s; + delete [] s; if (r == 0) { From 727c4c181a2b954fcd52d12b227a420e1329f6ee Mon Sep 17 00:00:00 2001 From: Per Inge Mathisen Date: Fri, 3 May 2013 15:29:56 +0200 Subject: [PATCH 18/53] Fix wrong bitwise and operator --- Source/igtlutil/igtl_unit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/igtlutil/igtl_unit.c b/Source/igtlutil/igtl_unit.c index 1100d83a..1410b648 100644 --- a/Source/igtlutil/igtl_unit.c +++ b/Source/igtlutil/igtl_unit.c @@ -74,8 +74,8 @@ int igtl_export igtl_unit_unpack(igtl_unit pack, igtl_unit_data* data) /* Units */ for (i = 0; i < 6; i ++) { - data->unit[i] = (igtl_uint8) (pack >> (10*(5-i) + 4)) && 0x3F; - data->exp[i] = (igtl_uint8) (pack >> (10*(5-i))) && 0x0F; + data->unit[i] = (igtl_uint8) (pack >> (10*(5-i) + 4)) & 0x3F; + data->exp[i] = (igtl_uint8) (pack >> (10*(5-i))) & 0x0F; /* Convert signed value in exponent field from 4-bit to 8-bit */ if (data->exp[i] & 0x08) { From 0a4624653ba8dc45534a3be54ea2836777a82f8c Mon Sep 17 00:00:00 2001 From: Per Inge Mathisen Date: Fri, 3 May 2013 15:30:18 +0200 Subject: [PATCH 19/53] Fix compile warnings under clang --- Testing/igtlutil/igtl_capability_test.c | 1 + Testing/igtlutil/igtl_image_test.c | 1 + Testing/igtlutil/igtl_imgmeta_test.c | 1 + Testing/igtlutil/igtl_trajectory_test.c | 1 + 4 files changed, 4 insertions(+) diff --git a/Testing/igtlutil/igtl_capability_test.c b/Testing/igtlutil/igtl_capability_test.c index dedd8611..f137b219 100644 --- a/Testing/igtlutil/igtl_capability_test.c +++ b/Testing/igtlutil/igtl_capability_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" #include "igtl_capability.h" diff --git a/Testing/igtlutil/igtl_image_test.c b/Testing/igtlutil/igtl_image_test.c index ccfb8435..27a79d51 100644 --- a/Testing/igtlutil/igtl_image_test.c +++ b/Testing/igtlutil/igtl_image_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" diff --git a/Testing/igtlutil/igtl_imgmeta_test.c b/Testing/igtlutil/igtl_imgmeta_test.c index 20cef44a..1bce6b4c 100644 --- a/Testing/igtlutil/igtl_imgmeta_test.c +++ b/Testing/igtlutil/igtl_imgmeta_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" #include "igtl_imgmeta.h" diff --git a/Testing/igtlutil/igtl_trajectory_test.c b/Testing/igtlutil/igtl_trajectory_test.c index 15d27814..0825767c 100644 --- a/Testing/igtlutil/igtl_trajectory_test.c +++ b/Testing/igtlutil/igtl_trajectory_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" #include "igtl_trajectory.h" From 28bb2eab1b39e0f61f01714b16cb12d59e8e6ec8 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Sun, 9 Jun 2013 23:50:33 -0400 Subject: [PATCH 20/53] BUG: Fix Issue #14 Linker error in VS2012. --- Source/igtlCapabilityMessage.cxx | 6 +++--- Source/igtlTransformMessage.cxx | 1 + Source/igtlTransformMessage.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/igtlCapabilityMessage.cxx b/Source/igtlCapabilityMessage.cxx index 005be20e..d1619027 100755 --- a/Source/igtlCapabilityMessage.cxx +++ b/Source/igtlCapabilityMessage.cxx @@ -74,7 +74,7 @@ void CapabilityMessage::SetTypes(std::vector types) int CapabilityMessage::SetType(int id, const char* type) { - if (id < this->m_TypeNames.size() && strlen(type) < IGTL_HEADER_TYPE_SIZE) + if (id < (int)this->m_TypeNames.size() && strlen(type) < IGTL_HEADER_TYPE_SIZE) { this->m_TypeNames[id] = type; return 1; @@ -88,7 +88,7 @@ int CapabilityMessage::SetType(int id, const char* type) const char* CapabilityMessage::GetType(int id) { - if (id < this->m_TypeNames.size()) + if (id < (int)this->m_TypeNames.size()) { return this->m_TypeNames[id].c_str(); } @@ -148,7 +148,7 @@ int CapabilityMessage::UnpackBody() } this->m_TypeNames.clear(); - for(unsigned int i = 0; i < ntypes; i++) + for(int i = 0; i < ntypes; i++) { std::string buf; if (strnlen((const char*)info.typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) diff --git a/Source/igtlTransformMessage.cxx b/Source/igtlTransformMessage.cxx index 4c0d2035..49fcf8b2 100644 --- a/Source/igtlTransformMessage.cxx +++ b/Source/igtlTransformMessage.cxx @@ -21,6 +21,7 @@ namespace igtl { + TransformMessage::TransformMessage(): MessageBase() { diff --git a/Source/igtlTransformMessage.h b/Source/igtlTransformMessage.h index da1f3802..c4bcc040 100644 --- a/Source/igtlTransformMessage.h +++ b/Source/igtlTransformMessage.h @@ -35,8 +35,8 @@ class IGTLCommon_EXPORT GetTransformMessage: public HeaderOnlyMessageBase igtlNewMacro(igtl::GetTransformMessage); protected: - GetTransformMessage(); - ~GetTransformMessage(); + GetTransformMessage() : HeaderOnlyMessageBase() {}; + ~GetTransformMessage() {}; protected: virtual const char* DefaultBodyType() { return "GET_TRANS"; }; From f122ecfa69102f05efd7e9aab726e89ac049e600 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Sat, 29 Jun 2013 16:39:00 -0400 Subject: [PATCH 21/53] ENH: add StringEchoServer example --- Examples/String/CMakeLists.txt | 3 ++ Examples/String/StringEchoServer.cxx | 95 ++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 Examples/String/StringEchoServer.cxx diff --git a/Examples/String/CMakeLists.txt b/Examples/String/CMakeLists.txt index 72cee250..14b1562b 100644 --- a/Examples/String/CMakeLists.txt +++ b/Examples/String/CMakeLists.txt @@ -15,5 +15,8 @@ TARGET_LINK_LIBRARIES(StringClient OpenIGTLink) ADD_EXECUTABLE(StringServer StringServer.cxx) TARGET_LINK_LIBRARIES(StringServer OpenIGTLink) +ADD_EXECUTABLE(StringEchoServer StringEchoServer.cxx) +TARGET_LINK_LIBRARIES(StringEchoServer OpenIGTLink) + diff --git a/Examples/String/StringEchoServer.cxx b/Examples/String/StringEchoServer.cxx new file mode 100644 index 00000000..7542bb94 --- /dev/null +++ b/Examples/String/StringEchoServer.cxx @@ -0,0 +1,95 @@ +/*========================================================================= + + Program: Open IGT Link -- Example for Tracker Server Program + Module: $RCSfile: $ + Language: C++ + Date: $Date: $ + Version: $Revision: $ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlStringMessage.h" +#include "igtlServerSocket.h" + + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 2) // check number of arguments + { + // If not correct, print usage + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + int port = atoi(argv[1]); + + igtl::ServerSocket::Pointer serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + + igtl::Socket::Pointer socket; + + while (1) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + igtl::MessageHeader::Pointer hdrMsg = igtl::MessageHeader::New(); + + while (socket.IsNotNull() && socket->GetConnected()) + { + hdrMsg->InitPack(); + int r = socket->Receive(hdrMsg->GetPackPointer(), hdrMsg->GetPackSize()); + + // check message + if (r == 0) + { + socket->CloseSocket(); + continue; + } + if (r != hdrMsg->GetPackSize()) + continue; + + // get data + hdrMsg->Unpack(); + igtl::StringMessage::Pointer strMsg(igtl::StringMessage::New()); + strMsg->SetMessageHeader(hdrMsg); + strMsg->AllocatePack(); + socket->Receive(strMsg->GetPackBodyPointer(), strMsg->GetPackBodySize()); + int c = strMsg->Unpack(); + + // echo message back + std::cout << "Echoing: " << strMsg->GetString() << std::endl; + strMsg->SetDeviceName("StringEchoServer"); + strMsg->Pack(); + socket->Send(strMsg->GetPackPointer(), strMsg->GetPackSize()); + } + } + + //------------------------------------------------------------ + // Close connection (The example code never reachs to this section ...) + + socket->CloseSocket(); + +} + From f3690e987d59409ded32ded3bdac20f91b5d30c5 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 2 Jul 2013 22:08:04 -0400 Subject: [PATCH 22/53] STYLE: Fix wrong statement in help (coordinate -> string) --- Examples/String/StringClient.cxx | 2 +- Examples/String/StringEchoServer.cxx | 4 ++-- Examples/String/StringServer.cxx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Examples/String/StringClient.cxx b/Examples/String/StringClient.cxx index b8fb0285..1829ccf4 100644 --- a/Examples/String/StringClient.cxx +++ b/Examples/String/StringClient.cxx @@ -43,7 +43,7 @@ int main(int argc, char* argv[]) std::cerr << "Usage: " << argv[0] << " " << std::endl; std::cerr << " : IP or host name" << std::endl; std::cerr << " : Port # (18944 in Slicer default)" << std::endl; - std::cerr << " : Frequency (fps) to send coordinate" << std::endl; + std::cerr << " : Frequency (fps) to send string" << std::endl; exit(0); } diff --git a/Examples/String/StringEchoServer.cxx b/Examples/String/StringEchoServer.cxx index 7542bb94..5988a9ac 100644 --- a/Examples/String/StringEchoServer.cxx +++ b/Examples/String/StringEchoServer.cxx @@ -1,6 +1,6 @@ /*========================================================================= - Program: Open IGT Link -- Example for Tracker Server Program + Program: Open IGT Link -- Example for String Echo Server Program Module: $RCSfile: $ Language: C++ Date: $Date: $ @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) igtl::Socket::Pointer socket; while (1) - { + { //------------------------------------------------------------ // Waiting for Connection socket = serverSocket->WaitForConnection(1000); diff --git a/Examples/String/StringServer.cxx b/Examples/String/StringServer.cxx index fe073009..b394270d 100644 --- a/Examples/String/StringServer.cxx +++ b/Examples/String/StringServer.cxx @@ -42,7 +42,7 @@ int main(int argc, char* argv[]) // If not correct, print usage std::cerr << "Usage: " << argv[0] << " " << std::endl; std::cerr << " : Port # (18944 in Slicer default)" << std::endl; - std::cerr << " : Frequency (fps) to send coordinate" << std::endl; + std::cerr << " : Frequency (fps) to send string" << std::endl; exit(0); } From e50390f71e2003dc39bf9e3ba98a0b4c5328151a Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Sat, 20 Jul 2013 23:43:23 -0400 Subject: [PATCH 23/53] ENH: add PointListServer example --- Examples/Point/CMakeLists.txt | 3 + Examples/Point/PointListServer.cxx | 227 +++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 Examples/Point/PointListServer.cxx diff --git a/Examples/Point/CMakeLists.txt b/Examples/Point/CMakeLists.txt index 672a1119..08628718 100644 --- a/Examples/Point/CMakeLists.txt +++ b/Examples/Point/CMakeLists.txt @@ -15,3 +15,6 @@ TARGET_LINK_LIBRARIES(PointClient OpenIGTLink) ADD_EXECUTABLE(PointServer PointServer.cxx) TARGET_LINK_LIBRARIES(PointServer OpenIGTLink) +ADD_EXECUTABLE(PointListServer PointListServer.cxx) +TARGET_LINK_LIBRARIES(PointListServer OpenIGTLink) + diff --git a/Examples/Point/PointListServer.cxx b/Examples/Point/PointListServer.cxx new file mode 100644 index 00000000..0209f93b --- /dev/null +++ b/Examples/Point/PointListServer.cxx @@ -0,0 +1,227 @@ +/*========================================================================= + + Program: Open IGT Link -- Example for Image Meta Data Server + Module: $RCSfile: $ + Language: C++ + Date: $Date: $ + Version: $Revision: $ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlMessageHeader.h" +#include "igtlPointMessage.h" +#include "igtlServerSocket.h" + +using std::ifstream; +using std::stringstream; +using std::cerr; + +typedef struct { + double x; + double y; + double z; +} Point; + +typedef std::vector PointList; + +int SendPointList(igtl::Socket::Pointer& socket, const char *devicename, PointList points); +PointList DefaultPointList(); +PointList ReadPointList(char* ); + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + PointList pointlist; + + if (argc < 2 || argc > 3) + { + // If not correct, print usage + std::cerr << "Sends OpenIGTLink point list upon POINT_GET request(s)" << std::endl; + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + std::cerr << " : [optional] file name, wherein each line contains 3 points to send" << std::endl; + exit(0); + } + + int port = atoi(argv[1]); + + if (argc == 2) // check number of arguments + pointlist = DefaultPointList(); + else if (argc == 3) + { + char* filename = argv[2]; + pointlist = ReadPointList(filename); + } + + igtl::ServerSocket::Pointer serverSocket; + serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + + igtl::Socket::Pointer socket; + + while (1) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + + if (socket.IsNotNull()) // if client connected + { + std::cerr << "A client is connected." << std::endl; + + // Create a message buffer to receive header + igtl::MessageHeader::Pointer headerMsg; + headerMsg = igtl::MessageHeader::New(); + + //------------------------------------------------------------ + // loop + for (int i = 0; i < 100; i ++) + { + + // Initialize receive buffer + headerMsg->InitPack(); + + // Receive generic header from the socket + int rs = socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize()); + if (rs == 0) + { + socket->CloseSocket(); + } + if (rs != headerMsg->GetPackSize()) + { + continue; + } + + // Deserialize the header + headerMsg->Unpack(); + + std::cerr << "Receiving a message: " << std::endl; + std::cerr << " Device Type: \"" << headerMsg->GetDeviceType() << "\"" << std::endl; + std::cerr << " Device Name: \"" << headerMsg->GetDeviceName() << "\"" << std::endl; + + // Check data type and receive data body + if (strcmp(headerMsg->GetDeviceType(), "GET_POINT") == 0) + { + socket->Skip(headerMsg->GetBodySizeToRead(), 0); + SendPointList(socket, headerMsg->GetDeviceName(), pointlist); + } + else + { + // if the data type is unknown, skip reading. + socket->Skip(headerMsg->GetBodySizeToRead(), 0); + } + } + } + } + + //------------------------------------------------------------ + // Close connection (The example code never reaches to this section ...) + socket->CloseSocket(); +} + + +int SendPointList(igtl::Socket::Pointer& socket, const char* name, PointList points) +{ + std::cout << "Sending PointList" << std::endl; + //------------------------------------------------------------ + // Allocate Point Message Class + igtl::PointMessage::Pointer pointMsg; + pointMsg = igtl::PointMessage::New(); + pointMsg->SetDeviceName("PointSender"); + + //--------------------------- + // Create a point message + int i = 0; + PointList::iterator pt_iter; + for (pt_iter = points.begin(); + pt_iter != points.end(); + ++pt_iter) + { + igtl::PointElement::Pointer point; + point = igtl::PointElement::New(); + stringstream pt_name; + pt_name << "POINT_" << i; + + point->SetName(pt_name.str().c_str()); + point->SetGroupName("GROUP_0"); + point->SetRGBA(0x00, 0x00, 0xFF, 0xFF); + point->SetPosition(pt_iter->x, pt_iter->y, pt_iter->z); + point->SetRadius(75.0); + point->SetOwner("IMAGE_0"); + + //--------------------------- + // Pack into the point message + pointMsg->AddPointElement(point); + i++; + } + pointMsg->Pack(); + + //--------------------------- + // Send + socket->Send(pointMsg->GetPackPointer(), pointMsg->GetPackSize()); + + return 1; +} + +//------------------------------------------------------------ +// Function to create default point list +PointList DefaultPointList() +{ + PointList points; + Point pt1 = {10.0, 20.0, 30.0}; + Point pt2 = {40.0, 50.0, 60.0}; + Point pt3 = {70.0, 80.0, 90.0}; + points.push_back(pt1); + points.push_back(pt2); + points.push_back(pt3); + return points; +} + + +//------------------------------------------------------------ +// Function to read test point data +PointList ReadPointList(char* filename) +{ + PointList points; + + //------------------------------------------------------------ + // Load point list from file + // file format is x y z\n + ifstream f_in(filename); + std::string line; + if (!f_in.is_open()) + { + std::cerr << "Error opening file: " << filename << std::endl; + exit(0); + } + + Point pt; + while ( f_in >> pt.x >> pt.y >> pt.z ) + points.push_back(pt); + + std::cerr << "Read: " << points.size() << " points from file." << std::endl; + return points; +} From 7c011040004432fa7208ec3363ea65f72c8e8db2 Mon Sep 17 00:00:00 2001 From: Isaiah Norton Date: Wed, 14 Aug 2013 14:25:41 -0400 Subject: [PATCH 24/53] BUG: use shutdown() instead of close() for sockets This keeps the handle open long enough to raise the closed event to the client. --- Source/igtlSocket.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/igtlSocket.cxx b/Source/igtlSocket.cxx index 316dbca4..c19c12ee 100644 --- a/Source/igtlSocket.cxx +++ b/Source/igtlSocket.cxx @@ -48,7 +48,7 @@ #define WSA_VERSION MAKEWORD(1,1) #define igtlCloseSocketMacro(sock) (closesocket(sock)) #else -#define igtlCloseSocketMacro(sock) (close(sock)) +#define igtlCloseSocketMacro(sock) (shutdown(sock, 2)) #endif namespace igtl From 6ea26cf2ed6bd7ff5a7c69801989010d35a60492 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 15 Aug 2013 10:34:11 -0400 Subject: [PATCH 25/53] ENH: Add a class for GET_STATUS message type. --- Source/igtlStatusMessage.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Source/igtlStatusMessage.h b/Source/igtlStatusMessage.h index a05bf59d..0df38e25 100644 --- a/Source/igtlStatusMessage.h +++ b/Source/igtlStatusMessage.h @@ -23,6 +23,28 @@ namespace igtl { + +/// A class for the GET_STATUS message type. +class IGTLCommon_EXPORT GetStatusMessage: public HeaderOnlyMessageBase +{ +public: + typedef GetStatusMessage Self; + typedef HeaderOnlyMessageBase Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + igtlTypeMacro(igtl::GetStatusMessage, igtl::HeaderOnlyMessageBase); + igtlNewMacro(igtl::GetStatusMessage); + +protected: + GetStatusMessage() : HeaderOnlyMessageBase() {}; + ~GetStatusMessage() {}; + +protected: + virtual const char* DefaultBodyType() { return "GET_STATUS"; }; +}; + + /// The STATUS data type is used to notify the receiver about the current status of the sender. /// The data consist of status code in a 16-bit unsigned integer, sub code in a 64-bit integer, /// error name in a 20-byte-length character string, and a status message. The length of From d48f903e0448f9abcdeca33b5ee0e4da31e15f0e Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 10 Sep 2013 19:28:14 -0400 Subject: [PATCH 26/53] ENH: Add TrajectoryMessage example. --- Examples/CMakeLists.txt | 1 + Examples/Receiver/ReceiveClient.cxx | 55 ++++++++++++++ Examples/Receiver/ReceiveServer.cxx | 55 ++++++++++++++ Examples/Trajectory/CMakeLists.txt | 18 +++++ Examples/Trajectory/TrajectoryClient.cxx | 113 +++++++++++++++++++++++++++++ Examples/Trajectory/TrajectoryServer.cxx | 120 +++++++++++++++++++++++++++++++ 6 files changed, 362 insertions(+) create mode 100644 Examples/Trajectory/CMakeLists.txt create mode 100644 Examples/Trajectory/TrajectoryClient.cxx create mode 100644 Examples/Trajectory/TrajectoryServer.cxx diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index cd86635a..300de51d 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -24,6 +24,7 @@ if (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") String Bind PolyData + Trajectory ) endif (${OpenIGTLink_PROTOCOL_VERSION} STREQUAL "2") diff --git a/Examples/Receiver/ReceiveClient.cxx b/Examples/Receiver/ReceiveClient.cxx index 5882f523..6e37eb5f 100644 --- a/Examples/Receiver/ReceiveClient.cxx +++ b/Examples/Receiver/ReceiveClient.cxx @@ -30,6 +30,7 @@ #if OpenIGTLink_PROTOCOL_VERSION >= 2 #include "igtlPointMessage.h" +#include "igtlTrajectoryMessage.h" #include "igtlStringMessage.h" #include "igtlTrackingDataMessage.h" #include "igtlQuaternionTrackingDataMessage.h" @@ -42,6 +43,7 @@ int ReceiveStatus(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); #if OpenIGTLink_PROTOCOL_VERSION >= 2 int ReceivePoint(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); + int ReceiveTrajectory(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); int ReceiveString(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); int ReceiveTrackingData(igtl::ClientSocket::Pointer& socket, igtl::MessageHeader::Pointer& header); int ReceiveQuaternionTrackingData(igtl::ClientSocket::Pointer& socket, igtl::MessageHeader::Pointer& header); @@ -145,6 +147,10 @@ int main(int argc, char* argv[]) { ReceivePoint(socket, headerMsg); } + else if (strcmp(headerMsg->GetDeviceType(), "TRAJ") == 0) + { + ReceiveTrajectory(socket, headerMsg); + } else if (strcmp(headerMsg->GetDeviceType(), "STRING") == 0) { ReceiveString(socket, headerMsg); @@ -368,6 +374,55 @@ int ReceivePoint(igtl::Socket * socket, igtl::MessageHeader::Pointer& header) return 1; } +int ReceiveTrajectory(igtl::Socket * socket, igtl::MessageHeader::Pointer& header) +{ + + std::cerr << "Receiving TRAJECTORY data type." << std::endl; + + // Create a message buffer to receive transform data + igtl::TrajectoryMessage::Pointer trajectoryMsg; + trajectoryMsg = igtl::TrajectoryMessage::New(); + trajectoryMsg->SetMessageHeader(header); + trajectoryMsg->AllocatePack(); + + // Receive transform data from the socket + socket->Receive(trajectoryMsg->GetPackBodyPointer(), trajectoryMsg->GetPackBodySize()); + + // Deserialize the transform data + // If you want to skip CRC check, call Unpack() without argument. + int c = trajectoryMsg->Unpack(1); + + if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK + { + int nElements = trajectoryMsg->GetNumberOfTrajectoryElement(); + for (int i = 0; i < nElements; i ++) + { + igtl::TrajectoryElement::Pointer trajectoryElement; + trajectoryMsg->GetTrajectoryElement(i, trajectoryElement); + + igtlUint8 rgba[4]; + trajectoryElement->GetRGBA(rgba); + + igtlFloat32 entry[3]; + igtlFloat32 target[3]; + trajectoryElement->GetEntryPosition(entry); + trajectoryElement->GetTargetPosition(target); + + std::cerr << "========== Element #" << i << " ==========" << std::endl; + std::cerr << " Name : " << trajectoryElement->GetName() << std::endl; + std::cerr << " GroupName : " << trajectoryElement->GetGroupName() << std::endl; + std::cerr << " RGBA : ( " << (int)rgba[0] << ", " << (int)rgba[1] << ", " << (int)rgba[2] << ", " << (int)rgba[3] << " )" << std::endl; + std::cerr << " Entry Pt : ( " << std::fixed << entry[0] << ", " << entry[1] << ", " << entry[2] << " )" << std::endl; + std::cerr << " Target Pt : ( " << std::fixed << target[0] << ", " << target[1] << ", " << target[2] << " )" << std::endl; + std::cerr << " Radius : " << std::fixed << trajectoryElement->GetRadius() << std::endl; + std::cerr << " Owner : " << trajectoryElement->GetOwner() << std::endl; + std::cerr << "================================" << std::endl << std::endl; + } + } + + return 1; +} + int ReceiveString(igtl::Socket * socket, igtl::MessageHeader::Pointer& header) { diff --git a/Examples/Receiver/ReceiveServer.cxx b/Examples/Receiver/ReceiveServer.cxx index 16ee5ea8..d2cfc434 100644 --- a/Examples/Receiver/ReceiveServer.cxx +++ b/Examples/Receiver/ReceiveServer.cxx @@ -30,6 +30,7 @@ #if OpenIGTLink_PROTOCOL_VERSION >= 2 #include "igtlPointMessage.h" +#include "igtlTrajectoryMessage.h" #include "igtlStringMessage.h" #include "igtlBindMessage.h" #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 @@ -42,6 +43,7 @@ int ReceiveStatus(igtl::Socket * socket, igtl::MessageHeader * header); #if OpenIGTLink_PROTOCOL_VERSION >= 2 int ReceivePoint(igtl::Socket * socket, igtl::MessageHeader * header); +int ReceiveTrajectory(igtl::Socket * socket, igtl::MessageHeader::Pointer& header); int ReceiveString(igtl::Socket * socket, igtl::MessageHeader * header); int ReceiveBind(igtl::Socket * socket, igtl::MessageHeader * header); #endif //OpenIGTLink_PROTOCOL_VERSION >= 2 @@ -145,6 +147,10 @@ int main(int argc, char* argv[]) { ReceivePoint(socket, headerMsg); } + else if (strcmp(headerMsg->GetDeviceType(), "TRAJ") == 0) + { + ReceiveTrajectory(socket, headerMsg); + } else if (strcmp(headerMsg->GetDeviceType(), "STRING") == 0) { ReceiveString(socket, headerMsg); @@ -371,6 +377,55 @@ int ReceivePoint(igtl::Socket * socket, igtl::MessageHeader * header) return 1; } +int ReceiveTrajectory(igtl::Socket * socket, igtl::MessageHeader::Pointer& header) +{ + + std::cerr << "Receiving TRAJECTORY data type." << std::endl; + + // Create a message buffer to receive transform data + igtl::TrajectoryMessage::Pointer trajectoryMsg; + trajectoryMsg = igtl::TrajectoryMessage::New(); + trajectoryMsg->SetMessageHeader(header); + trajectoryMsg->AllocatePack(); + + // Receive transform data from the socket + socket->Receive(trajectoryMsg->GetPackBodyPointer(), trajectoryMsg->GetPackBodySize()); + + // Deserialize the transform data + // If you want to skip CRC check, call Unpack() without argument. + int c = trajectoryMsg->Unpack(1); + + if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK + { + int nElements = trajectoryMsg->GetNumberOfTrajectoryElement(); + for (int i = 0; i < nElements; i ++) + { + igtl::TrajectoryElement::Pointer trajectoryElement; + trajectoryMsg->GetTrajectoryElement(i, trajectoryElement); + + igtlUint8 rgba[4]; + trajectoryElement->GetRGBA(rgba); + + igtlFloat32 entry[3]; + igtlFloat32 target[3]; + trajectoryElement->GetEntryPosition(entry); + trajectoryElement->GetTargetPosition(target); + + std::cerr << "========== Element #" << i << " ==========" << std::endl; + std::cerr << " Name : " << trajectoryElement->GetName() << std::endl; + std::cerr << " GroupName : " << trajectoryElement->GetGroupName() << std::endl; + std::cerr << " RGBA : ( " << (int)rgba[0] << ", " << (int)rgba[1] << ", " << (int)rgba[2] << ", " << (int)rgba[3] << " )" << std::endl; + std::cerr << " Entry Pt : ( " << std::fixed << entry[0] << ", " << entry[1] << ", " << entry[2] << " )" << std::endl; + std::cerr << " Target Pt : ( " << std::fixed << target[0] << ", " << target[1] << ", " << target[2] << " )" << std::endl; + std::cerr << " Radius : " << std::fixed << trajectoryElement->GetRadius() << std::endl; + std::cerr << " Owner : " << trajectoryElement->GetOwner() << std::endl; + std::cerr << "================================" << std::endl << std::endl; + } + } + + return 1; +} + int ReceiveString(igtl::Socket * socket, igtl::MessageHeader * header) { diff --git a/Examples/Trajectory/CMakeLists.txt b/Examples/Trajectory/CMakeLists.txt new file mode 100644 index 00000000..a892e3d2 --- /dev/null +++ b/Examples/Trajectory/CMakeLists.txt @@ -0,0 +1,18 @@ +PROJECT(Trajectory) + +cmake_minimum_required(VERSION 2.4) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +find_package(OpenIGTLink REQUIRED) + +include(${OpenIGTLink_USE_FILE}) + +ADD_EXECUTABLE(TrajectoryClient TrajectoryClient.cxx) +TARGET_LINK_LIBRARIES(TrajectoryClient OpenIGTLink) + +ADD_EXECUTABLE(TrajectoryServer TrajectoryServer.cxx) +TARGET_LINK_LIBRARIES(TrajectoryServer OpenIGTLink) + + diff --git a/Examples/Trajectory/TrajectoryClient.cxx b/Examples/Trajectory/TrajectoryClient.cxx new file mode 100644 index 00000000..12ec2274 --- /dev/null +++ b/Examples/Trajectory/TrajectoryClient.cxx @@ -0,0 +1,113 @@ +/*========================================================================= + + Program: OpenIGTLink -- Example for Trajectory message + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlTrajectoryMessage.h" +#include "igtlClientSocket.h" + + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 3) // check number of arguments + { + // If not correct, print usage + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : IP or host name" << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + char* hostname = argv[1]; + int port = atoi(argv[2]); + + //------------------------------------------------------------ + // Establish Connection + + igtl::ClientSocket::Pointer socket; + socket = igtl::ClientSocket::New(); + int r = socket->ConnectToServer(hostname, port); + + if (r != 0) + { + std::cerr << "Cannot connect to the server." << std::endl; + exit(0); + } + + //------------------------------------------------------------ + // Allocate Transform Message Class + + igtl::TrajectoryMessage::Pointer trajectoryMsg; + trajectoryMsg = igtl::TrajectoryMessage::New(); + trajectoryMsg->SetDeviceName("TrajectorySender"); + + //--------------------------- + // Create 1st trajectory + igtl::TrajectoryElement::Pointer trajectory0; + trajectory0 = igtl::TrajectoryElement::New(); + trajectory0->SetName("TRAJECTORY_0"); + trajectory0->SetGroupName("GROUP_0"); + trajectory0->SetRGBA(0xFF, 0x00, 0x00, 0xFF); + trajectory0->SetEntryPosition(10.0, 20.0, 30.0); + trajectory0->SetTargetPosition(20.0, 20.0, 40.0); + trajectory0->SetRadius(15.0); + trajectory0->SetOwner("IMAGE_0"); + + //--------------------------- + // Create 2nd trajectory + igtl::TrajectoryElement::Pointer trajectory1; + trajectory1 = igtl::TrajectoryElement::New(); + trajectory1->SetName("TRAJECTORY_1"); + trajectory1->SetGroupName("GROUP_0"); + trajectory1->SetRGBA(0x00, 0xFF, 0x00, 0xFF); + trajectory1->SetEntryPosition(40.0, 50.0, 60.0); + trajectory1->SetTargetPosition(20.0, 30.0, 10.0); + trajectory1->SetRadius(45.0); + trajectory1->SetOwner("IMAGE_0"); + + //--------------------------- + // Create 3rd trajectory + igtl::TrajectoryElement::Pointer trajectory2; + trajectory2 = igtl::TrajectoryElement::New(); + trajectory2->SetName("TRAJECTORY_2"); + trajectory2->SetGroupName("GROUP_0"); + trajectory2->SetRGBA(0x00, 0x00, 0xFF, 0xFF); + trajectory2->SetEntryPosition(70.0, 80.0, 90.0); + trajectory1->SetTargetPosition(10.0, 40.0, 20.0); + trajectory2->SetRadius(75.0); + trajectory2->SetOwner("IMAGE_0"); + + //--------------------------- + // Pack into the trajectory message + trajectoryMsg->AddTrajectoryElement(trajectory0); + trajectoryMsg->AddTrajectoryElement(trajectory1); + trajectoryMsg->AddTrajectoryElement(trajectory2); + trajectoryMsg->Pack(); + + //------------------------------------------------------------ + // Send + socket->Send(trajectoryMsg->GetPackPointer(), trajectoryMsg->GetPackSize()); + + + //------------------------------------------------------------ + // Close the socket + socket->CloseSocket(); + +} + diff --git a/Examples/Trajectory/TrajectoryServer.cxx b/Examples/Trajectory/TrajectoryServer.cxx new file mode 100644 index 00000000..e4260c59 --- /dev/null +++ b/Examples/Trajectory/TrajectoryServer.cxx @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: OpenIGTLink -- Example for Trajectory message + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include +#include +#include + +#include "igtlOSUtil.h" +#include "igtlTrajectoryMessage.h" +#include "igtlServerSocket.h" + +int main(int argc, char* argv[]) +{ + //------------------------------------------------------------ + // Parse Arguments + + if (argc != 2) // check number of arguments + { + // If not correct, print usage + std::cerr << "Usage: " << argv[0] << " " << std::endl; + std::cerr << " : Port # (18944 in Slicer default)" << std::endl; + exit(0); + } + + int port = atoi(argv[1]); + + igtl::ServerSocket::Pointer serverSocket; + serverSocket = igtl::ServerSocket::New(); + int r = serverSocket->CreateServer(port); + + if (r < 0) + { + std::cerr << "Cannot create a server socket." << std::endl; + exit(0); + } + + igtl::Socket::Pointer socket; + + while (1) + { + //------------------------------------------------------------ + // Waiting for Connection + socket = serverSocket->WaitForConnection(1000); + + if (socket.IsNotNull()) // if client connected + { + + //--------------------------- + // Create a trajectory message + igtl::TrajectoryMessage::Pointer trajectoryMsg; + trajectoryMsg = igtl::TrajectoryMessage::New(); + trajectoryMsg->SetDeviceName("TrajectorySender"); + + //--------------------------- + // Create 1st trajectory + igtl::TrajectoryElement::Pointer trajectory0; + trajectory0 = igtl::TrajectoryElement::New(); + trajectory0->SetName("TRAJECTORY_0"); + trajectory0->SetGroupName("GROUP_0"); + trajectory0->SetRGBA(0xFF, 0x00, 0x00, 0xFF); + trajectory0->SetEntryPosition(10.0, 20.0, 30.0); + trajectory0->SetTargetPosition(20.0, 20.0, 40.0); + trajectory0->SetRadius(15.0); + trajectory0->SetOwner("IMAGE_0"); + + //--------------------------- + // Create 2nd trajectory + igtl::TrajectoryElement::Pointer trajectory1; + trajectory1 = igtl::TrajectoryElement::New(); + trajectory1->SetName("TRAJECTORY_1"); + trajectory1->SetGroupName("GROUP_0"); + trajectory1->SetRGBA(0x00, 0xFF, 0x00, 0xFF); + trajectory1->SetEntryPosition(40.0, 50.0, 60.0); + trajectory1->SetTargetPosition(20.0, 30.0, 10.0); + trajectory1->SetRadius(45.0); + trajectory1->SetOwner("IMAGE_0"); + + //--------------------------- + // Create 3rd trajectory + igtl::TrajectoryElement::Pointer trajectory2; + trajectory2 = igtl::TrajectoryElement::New(); + trajectory2->SetName("TRAJECTORY_2"); + trajectory2->SetGroupName("GROUP_0"); + trajectory2->SetRGBA(0x00, 0x00, 0xFF, 0xFF); + trajectory2->SetEntryPosition(70.0, 80.0, 90.0); + trajectory2->SetTargetPosition(10.0, 40.0, 20.0); + trajectory2->SetRadius(75.0); + trajectory2->SetOwner("IMAGE_0"); + + //--------------------------- + // Pack into the trajectory message + trajectoryMsg->AddTrajectoryElement(trajectory0); + trajectoryMsg->AddTrajectoryElement(trajectory1); + trajectoryMsg->AddTrajectoryElement(trajectory2); + trajectoryMsg->Pack(); + + //--------------------------- + // Send + socket->Send(trajectoryMsg->GetPackPointer(), trajectoryMsg->GetPackSize()); + } + + //------------------------------------------------------------ + // Close connection (The example code never reachs to this section ...) + } + + socket->CloseSocket(); + +} + + From 61cb0a866926825db03cf9b1fb4ef0e9a2d8d1c9 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Wed, 11 Sep 2013 15:10:43 -0400 Subject: [PATCH 27/53] STYLE: Fixed revision number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03baaaa5..3070df9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ if(COMMAND cmake_policy) #----------------------------------------------------------------------------- # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") -SET(OpenIGTLink_VERSION_MINOR "10") +SET(OpenIGTLink_VERSION_MINOR "9") SET(OpenIGTLink_VERSION_PATCH "9") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From a4a31a8c4c81fe6bef6e30c927d850efb27f2d4c Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Wed, 11 Sep 2013 15:40:00 -0400 Subject: [PATCH 28/53] COMP: Fix warning 'converting to non-pointer type int from NULL'. --- Source/igtlImageMessage2.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/igtlImageMessage2.cxx b/Source/igtlImageMessage2.cxx index 4577e8df..78fcc97d 100644 --- a/Source/igtlImageMessage2.cxx +++ b/Source/igtlImageMessage2.cxx @@ -493,7 +493,7 @@ int ImageMessage2::GetPackFragmentSize(int id) return GetSubVolumeImageSize(); } - return NULL; + return 0; } #endif // FRAGMENTED_PACK From cda1b18e7a932d5135f229c2a1272a442239c2e2 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Thu, 12 Sep 2013 22:15:09 -0400 Subject: [PATCH 29/53] STYLE: Update version number. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 305052ff..1b9c63f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ if(COMMAND cmake_policy) #----------------------------------------------------------------------------- # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") -SET(OpenIGTLink_VERSION_MINOR "9") -SET(OpenIGTLink_VERSION_PATCH "8") +SET(OpenIGTLink_VERSION_MINOR "10") +SET(OpenIGTLink_VERSION_PATCH "0") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From 093f7c1762ca0d366a2f9d5be1c566b5423252bc Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Sun, 15 Sep 2013 02:43:52 -0400 Subject: [PATCH 30/53] BUG: Avoid * ((igtl_uint16 *) ptr) = to address issue #20. Need testing. --- Source/igtlutil/igtl_bind.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/igtlutil/igtl_bind.c b/Source/igtlutil/igtl_bind.c index a5222536..c21aaaad 100644 --- a/Source/igtlutil/igtl_bind.c +++ b/Source/igtlutil/igtl_bind.c @@ -352,6 +352,7 @@ int igtl_bind_pack_normal(igtl_bind_info * info, void * byte_array) igtl_uint16 * nts; size_t wb; size_t len; + igtl_uint16 tmp16; igtl_uint64 tmp64; ptr = (char *) byte_array; @@ -366,11 +367,14 @@ int igtl_bind_pack_normal(igtl_bind_info * info, void * byte_array) /* Number of child messages */ if (igtl_is_little_endian()) { - *((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + //*((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + tmp16 = BYTE_SWAP_INT16(info->ncmessages); + memcpy(ptr, &tmp16, sizeof(igtl_uint16)); } else { - *((igtl_uint16*) ptr) = info->ncmessages; + //*((igtl_uint16*) ptr) = info->ncmessages; + memcpy(ptr, &(info->ncmessages), sizeof(igtl_uint16)); } ptr += sizeof(igtl_uint16); @@ -452,6 +456,7 @@ int igtl_bind_pack_request(igtl_bind_info * info, void * byte_array) igtl_uint16 * nts; size_t wb; size_t len; + igtl_uint16 tmp16; ptr = (char *) byte_array; nc = info->ncmessages; @@ -471,11 +476,14 @@ int igtl_bind_pack_request(igtl_bind_info * info, void * byte_array) /* Number of child messages */ if (igtl_is_little_endian()) { - *((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + //*((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + tmp16 = BYTE_SWAP_INT16(info->ncmessages); + memcpy(ptr, &tmp16, sizeof(igtl_uint16)); } else { - *((igtl_uint16*) ptr) = info->ncmessages; + //*((igtl_uint16*) ptr) = info->ncmessages; + memcpy(ptr, &(info->ncmessages), sizeof(igtl_uint16)); } ptr += sizeof(igtl_uint16); From af6a507c3ad41130cd5897240e33d821a92533e9 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 1 Oct 2013 09:43:33 -0400 Subject: [PATCH 31/53] STYLE: Format README using Markdown --- README => README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) rename README => README.md (53%) diff --git a/README b/README.md similarity index 53% rename from README rename to README.md index 030fbe2e..3b76337c 100644 --- a/README +++ b/README.md @@ -1,10 +1,13 @@ +The OpenIGTLink Library +======================= + This project provides an implementation of the OpenIGTLink protocol defined in - http://openigtlink.org/ + http://openigtlink.org/ The code is distributed as open source under the new BSD liccense: - http://www.opensource.org/licenses/bsd-license.php + http://www.opensource.org/licenses/bsd-license.php From c051626fabe0ae5ef2ea8b6aa1383324ff635760 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 1 Oct 2013 17:57:01 -0400 Subject: [PATCH 32/53] BUG: Address issue #21.. replace this->m_DefaultBodyType = this->DefaultBodyType() with this->m_DefaultBodyType = "" --- Examples/Status/StatusClient.cxx | 13 +++++++------ Source/igtlImageMessage.h | 4 +--- Source/igtlMessageBase.h | 7 ++----- Source/igtlStatusMessage.h | 5 +---- Source/igtlTransformMessage.h | 5 +---- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/Examples/Status/StatusClient.cxx b/Examples/Status/StatusClient.cxx index a33c167d..f7a862d0 100644 --- a/Examples/Status/StatusClient.cxx +++ b/Examples/Status/StatusClient.cxx @@ -20,6 +20,7 @@ #include "igtlOSUtil.h" #include "igtlStatusMessage.h" +#include "igtlImageMessage.h" #include "igtlClientSocket.h" // @@ -61,18 +62,18 @@ int main(int argc, char* argv[]) //------------------------------------------------------------ // Allocate Status Message Class - igtl::StatusMessage::Pointer statusMsg; - statusMsg = igtl::StatusMessage::New(); + igtl::GetStatusMessage::Pointer statusMsg; + statusMsg = igtl::GetStatusMessage::New(); statusMsg->SetDeviceName("Device"); //------------------------------------------------------------ // loop for (int i = 0; i < 100; i ++) { - statusMsg->SetCode(igtl::StatusMessage::STATUS_OK); - statusMsg->SetSubCode(128); - statusMsg->SetErrorName("OK!"); - statusMsg->SetStatusString("This is a test to send status message."); + //statusMsg->SetCode(igtl::StatusMessage::STATUS_OK); + //statusMsg->SetSubCode(128); + //statusMsg->SetErrorName("OK!"); + //statusMsg->SetStatusString("This is a test to send status message."); statusMsg->Pack(); socket->Send(statusMsg->GetPackPointer(), statusMsg->GetPackSize()); igtl::Sleep(interval); // wait diff --git a/Source/igtlImageMessage.h b/Source/igtlImageMessage.h index a85898aa..672c23b6 100644 --- a/Source/igtlImageMessage.h +++ b/Source/igtlImageMessage.h @@ -37,11 +37,9 @@ class IGTLCommon_EXPORT GetImageMessage: public HeaderOnlyMessageBase protected: - GetImageMessage() : HeaderOnlyMessageBase() {}; + GetImageMessage() : HeaderOnlyMessageBase() { this->m_DefaultBodyType = "GET_IMAGE"; }; ~GetImageMessage() {}; -protected: - virtual const char* DefaultBodyType() { return "GET_IMAGE"; }; }; diff --git a/Source/igtlMessageBase.h b/Source/igtlMessageBase.h index c308a127..66d238cc 100644 --- a/Source/igtlMessageBase.h +++ b/Source/igtlMessageBase.h @@ -230,12 +230,11 @@ class IGTLCommon_EXPORT HeaderOnlyMessageBase: public MessageBase igtlNewMacro(igtl::HeaderOnlyMessageBase); protected: - HeaderOnlyMessageBase() { this->m_DefaultBodyType = this->DefaultBodyType(); }; + HeaderOnlyMessageBase() { this->m_DefaultBodyType = ""; }; ~HeaderOnlyMessageBase() {}; protected: - virtual const char * DefaultBodyType() { return ""; }; // Must be defined in a child class. virtual int GetBodyPackSize() { return 0; }; virtual int PackBody() { AllocatePack(); return 1; }; virtual int UnpackBody() { return 1; }; @@ -259,10 +258,8 @@ public: \ igtlNewMacro(igtl::name); \ \ protected: \ - name() : HeaderOnlyMessageBase() {}; \ + name() : HeaderOnlyMessageBase() { this->m_DefaultBodyType = msgtype; }; \ ~name() {}; \ -protedted: \ - virtual const char* DefaultBodyType() { return msgtype; }; \ }; } // namespace igtl diff --git a/Source/igtlStatusMessage.h b/Source/igtlStatusMessage.h index 0df38e25..c7bd1693 100644 --- a/Source/igtlStatusMessage.h +++ b/Source/igtlStatusMessage.h @@ -37,11 +37,8 @@ class IGTLCommon_EXPORT GetStatusMessage: public HeaderOnlyMessageBase igtlNewMacro(igtl::GetStatusMessage); protected: - GetStatusMessage() : HeaderOnlyMessageBase() {}; + GetStatusMessage() : HeaderOnlyMessageBase() { this->m_DefaultBodyType = "GET_STATUS"; }; ~GetStatusMessage() {}; - -protected: - virtual const char* DefaultBodyType() { return "GET_STATUS"; }; }; diff --git a/Source/igtlTransformMessage.h b/Source/igtlTransformMessage.h index c4bcc040..202c617b 100644 --- a/Source/igtlTransformMessage.h +++ b/Source/igtlTransformMessage.h @@ -35,11 +35,8 @@ class IGTLCommon_EXPORT GetTransformMessage: public HeaderOnlyMessageBase igtlNewMacro(igtl::GetTransformMessage); protected: - GetTransformMessage() : HeaderOnlyMessageBase() {}; + GetTransformMessage() : HeaderOnlyMessageBase() { this->m_DefaultBodyType = "GET_TRANS"; }; ~GetTransformMessage() {}; - -protected: - virtual const char* DefaultBodyType() { return "GET_TRANS"; }; }; From 8f81fcb13f3b4726935f09e390007718e27827ce Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 1 Oct 2013 18:51:29 -0400 Subject: [PATCH 33/53] BUG: Reset changes in Example/Status/StatusClient --- Examples/Status/StatusClient.cxx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Examples/Status/StatusClient.cxx b/Examples/Status/StatusClient.cxx index f7a862d0..a33c167d 100644 --- a/Examples/Status/StatusClient.cxx +++ b/Examples/Status/StatusClient.cxx @@ -20,7 +20,6 @@ #include "igtlOSUtil.h" #include "igtlStatusMessage.h" -#include "igtlImageMessage.h" #include "igtlClientSocket.h" // @@ -62,18 +61,18 @@ int main(int argc, char* argv[]) //------------------------------------------------------------ // Allocate Status Message Class - igtl::GetStatusMessage::Pointer statusMsg; - statusMsg = igtl::GetStatusMessage::New(); + igtl::StatusMessage::Pointer statusMsg; + statusMsg = igtl::StatusMessage::New(); statusMsg->SetDeviceName("Device"); //------------------------------------------------------------ // loop for (int i = 0; i < 100; i ++) { - //statusMsg->SetCode(igtl::StatusMessage::STATUS_OK); - //statusMsg->SetSubCode(128); - //statusMsg->SetErrorName("OK!"); - //statusMsg->SetStatusString("This is a test to send status message."); + statusMsg->SetCode(igtl::StatusMessage::STATUS_OK); + statusMsg->SetSubCode(128); + statusMsg->SetErrorName("OK!"); + statusMsg->SetStatusString("This is a test to send status message."); statusMsg->Pack(); socket->Send(statusMsg->GetPackPointer(), statusMsg->GetPackSize()); igtl::Sleep(interval); // wait From ac5d4fe1bd1323e2bba89c6cd557ea764e2fe560 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 4 Oct 2013 22:01:31 +0000 Subject: [PATCH 34/53] BUG: Fixing Issue #20. 'signed' is explicitly specified for igtl_int8. Tested on Ubuntu + armv7l. --- CMakeLists.txt | 2 +- Source/igtlutil/igtl_types.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cffd43d..d2e146e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "1") +SET(OpenIGTLink_VERSION_PATCH "2") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Source/igtlutil/igtl_types.h b/Source/igtlutil/igtl_types.h index 57935ea2..af67ba41 100644 --- a/Source/igtlutil/igtl_types.h +++ b/Source/igtlutil/igtl_types.h @@ -20,7 +20,7 @@ /* 8-bit integer type */ #if IGTL_SIZEOF_CHAR == 1 typedef unsigned char igtl_uint8; - typedef char igtl_int8; + typedef signed char igtl_int8; #else # error "No native data type can represent an 8-bit integer." #endif From 3408ee2af4f326bf1b26964599402f1791c46edd Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 4 Oct 2013 18:23:18 -0400 Subject: [PATCH 35/53] STYLE: Use C-style comments in .c files. --- Source/igtlutil/igtl_bind.c | 8 ++++---- Source/igtlutil/igtl_qtdata.c | 2 +- Source/igtlutil/igtl_sensor.c | 2 +- Source/igtlutil/igtl_tdata.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/igtlutil/igtl_bind.c b/Source/igtlutil/igtl_bind.c index c21aaaad..2862fe3c 100644 --- a/Source/igtlutil/igtl_bind.c +++ b/Source/igtlutil/igtl_bind.c @@ -367,13 +367,13 @@ int igtl_bind_pack_normal(igtl_bind_info * info, void * byte_array) /* Number of child messages */ if (igtl_is_little_endian()) { - //*((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + /* *((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); */ tmp16 = BYTE_SWAP_INT16(info->ncmessages); memcpy(ptr, &tmp16, sizeof(igtl_uint16)); } else { - //*((igtl_uint16*) ptr) = info->ncmessages; + /* *((igtl_uint16*) ptr) = info->ncmessages; */ memcpy(ptr, &(info->ncmessages), sizeof(igtl_uint16)); } ptr += sizeof(igtl_uint16); @@ -476,13 +476,13 @@ int igtl_bind_pack_request(igtl_bind_info * info, void * byte_array) /* Number of child messages */ if (igtl_is_little_endian()) { - //*((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); + /* *((igtl_uint16*) ptr) = BYTE_SWAP_INT16(info->ncmessages); */ tmp16 = BYTE_SWAP_INT16(info->ncmessages); memcpy(ptr, &tmp16, sizeof(igtl_uint16)); } else { - //*((igtl_uint16*) ptr) = info->ncmessages; + /* *((igtl_uint16*) ptr) = info->ncmessages; */ memcpy(ptr, &(info->ncmessages), sizeof(igtl_uint16)); } ptr += sizeof(igtl_uint16); diff --git a/Source/igtlutil/igtl_qtdata.c b/Source/igtlutil/igtl_qtdata.c index a780d12a..7d62c4d4 100644 --- a/Source/igtlutil/igtl_qtdata.c +++ b/Source/igtlutil/igtl_qtdata.c @@ -60,7 +60,7 @@ void igtl_export igtl_stt_qtdata_convert_byte_order(igtl_stt_qtdata* stt_qtdata) void igtl_export igtl_rts_qtdata_convert_byte_order(igtl_rts_qtdata* rts_qtdata) { - // do nothing + /* do nothing */ } diff --git a/Source/igtlutil/igtl_sensor.c b/Source/igtlutil/igtl_sensor.c index fe1c4ad4..32eac1e0 100644 --- a/Source/igtlutil/igtl_sensor.c +++ b/Source/igtlutil/igtl_sensor.c @@ -37,7 +37,7 @@ void igtl_export igtl_sensor_convert_byte_order(igtl_sensor_header* header, igtl if (igtl_is_little_endian()) { - larray = (int) header->larray; // NOTE: larray is 8-bit (doesn't depend on endianness) + larray = (int) header->larray; /* NOTE: larray is 8-bit (doesn't depend on endianness) */ header->unit = BYTE_SWAP_INT64(header->unit); tmp = (igtl_uint64*) data; diff --git a/Source/igtlutil/igtl_tdata.c b/Source/igtlutil/igtl_tdata.c index b01f80f1..7542857e 100644 --- a/Source/igtlutil/igtl_tdata.c +++ b/Source/igtlutil/igtl_tdata.c @@ -54,7 +54,7 @@ void igtl_export igtl_stt_tdata_convert_byte_order(igtl_stt_tdata* stt_tdata) void igtl_export igtl_rts_tdata_convert_byte_order(igtl_rts_tdata* rts_tdata) { - // do nothing + /* do nothing */ } From 754a90cb2f0f2cb48523f7be49b7ca7af29ce51a Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 21 Oct 2013 22:31:51 -0400 Subject: [PATCH 36/53] ENH: Add LBMETA message to ImageDatabaseServer example. --- CMakeLists.txt | 2 +- .../ImageDatabaseServer/ImageDatabaseServer.cxx | 78 +++++++++++++++++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2e146e3..bed541e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "2") +SET(OpenIGTLink_VERSION_PATCH "3") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Examples/ImageDatabaseServer/ImageDatabaseServer.cxx b/Examples/ImageDatabaseServer/ImageDatabaseServer.cxx index 72456685..332a6b65 100644 --- a/Examples/ImageDatabaseServer/ImageDatabaseServer.cxx +++ b/Examples/ImageDatabaseServer/ImageDatabaseServer.cxx @@ -25,10 +25,13 @@ #include "igtlMessageHeader.h" #include "igtlImageMessage.h" #include "igtlImageMetaMessage.h" +#include "igtlLabelMetaMessage.h" #include "igtlServerSocket.h" int SendImageMeta(igtl::Socket::Pointer& socket, const char* name); +int SendLabelMeta(igtl::Socket::Pointer& socket, const char* name); int SendImage(igtl::Socket::Pointer& socket, const char* name, const char* filedir); +int SendLabel(igtl::Socket::Pointer& socket, const char* name, const char* filedir); int GetTestImage(igtl::ImageMessage::Pointer& msg, const char* dir, int i); int main(int argc, char* argv[]) @@ -107,6 +110,10 @@ int main(int argc, char* argv[]) //socket->Skip(headerMsg->GetBodySizeToRead(), 0); SendImageMeta(socket, headerMsg->GetDeviceName()); } + else if (strcmp(headerMsg->GetDeviceType(), "GET_LBMETA") == 0) + { + SendLabelMeta(socket, headerMsg->GetDeviceName()); + } else if (strcmp(headerMsg->GetDeviceType(), "GET_IMAGE") == 0) { SendImage(socket, headerMsg->GetDeviceName(), filedir); @@ -209,6 +216,62 @@ int SendImageMeta(igtl::Socket::Pointer& socket, const char* name) } +int SendLabelMeta(igtl::Socket::Pointer& socket, const char* name) +{ + //------------------------------------------------------------ + // Allocate Status Message Class + + igtl::LabelMetaMessage::Pointer lbMetaMsg; + lbMetaMsg = igtl::LabelMetaMessage::New(); + // NOTE: the server should send a message with the same device name + // as the received query message. + lbMetaMsg->SetDeviceName(name); + + //--------------------------- + // Create 1st meta data + igtl::LabelMetaElement::Pointer lbMeta0; + lbMeta0 = igtl::LabelMetaElement::New(); + lbMeta0->SetName("LABEL_DESCRIPTION_0"); + lbMeta0->SetDeviceName("LABEL_0"); + lbMeta0->SetOwner("IMAGE_0"); + lbMeta0->SetSize(512, 512, 64); + + //--------------------------- + // Create 2nd meta data + igtl::LabelMetaElement::Pointer lbMeta1; + lbMeta1 = igtl::LabelMetaElement::New(); + lbMeta1->SetName("LABEL_DESCRIPTION_1"); + lbMeta1->SetDeviceName("LABEL_1"); + lbMeta1->SetOwner("IMAGE_1"); + + lbMeta1->SetSize(256, 128, 32); + + //--------------------------- + // Create 3rd meta data + igtl::LabelMetaElement::Pointer lbMeta2; + lbMeta2 = igtl::LabelMetaElement::New(); + lbMeta2->SetName("LABEL_DESCRIPTION_2"); + lbMeta2->SetDeviceName("LABEL_2"); + lbMeta2->SetOwner("IMAGE_2"); + lbMeta2->SetSize(256, 256, 32); + + lbMetaMsg->AddLabelMetaElement(lbMeta0); + lbMetaMsg->AddLabelMetaElement(lbMeta1); + lbMetaMsg->AddLabelMetaElement(lbMeta2); + + lbMetaMsg->Pack(); + std::cerr << "Size of pack: " << lbMetaMsg->GetPackSize() << std::endl; + std::cerr << "Name of type: " << lbMetaMsg->GetDeviceType() << std::endl; + std::cerr << "Sending a LBMETA message..." << std::endl; + + socket->Send(lbMetaMsg->GetPackPointer(), lbMetaMsg->GetPackSize()); + + return 1; + +} + + + int SendImage(igtl::Socket::Pointer& socket, const char* name, const char* filedir) { int index = 0; @@ -225,6 +288,18 @@ int SendImage(igtl::Socket::Pointer& socket, const char* name, const char* filed { index = 3; } + if (strcmp(name, "LABEL_0") == 0) + { + index = 4; + } + else if (strcmp(name, "LABEL_1") == 0) + { + index = 5; + } + else if (strcmp(name, "LABEL_2") == 0) + { + index = 6; + } if (index > 0) { @@ -268,7 +343,6 @@ int SendImage(igtl::Socket::Pointer& socket, const char* name, const char* filed } - //------------------------------------------------------------ // Function to read test image data int GetTestImage(igtl::ImageMessage::Pointer& msg, const char* dir, int i) @@ -276,7 +350,7 @@ int GetTestImage(igtl::ImageMessage::Pointer& msg, const char* dir, int i) //------------------------------------------------------------ // Check if image index is in the range - if (i < 0 || i >= 5) + if (i < 0 || i >= 7) { std::cerr << "Image index is invalid." << std::endl; return 0; From 661d4bd26baa056a5e7f609ce4ffedf1ee84205d Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 22 Oct 2013 00:35:06 -0400 Subject: [PATCH 37/53] BUG: Fixed bug in LabelMetaMessage. It could not extract owner image information from a LBMETA message. --- Source/igtlLabelMetaMessage.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/igtlLabelMetaMessage.cxx b/Source/igtlLabelMetaMessage.cxx index bff59255..0ffbd236 100644 --- a/Source/igtlLabelMetaMessage.cxx +++ b/Source/igtlLabelMetaMessage.cxx @@ -285,7 +285,7 @@ int LabelMetaMessage::UnpackBody() elemClass->SetSize(element->size); strbuf[IGTL_LBMETA_LEN_OWNER] = '\n'; - strncpy(strbuf, (char*)element->device_name, IGTL_LBMETA_LEN_OWNER); + strncpy(strbuf, (char*)element->owner, IGTL_LBMETA_LEN_OWNER); elemClass->SetOwner(strbuf); this->m_LabelMetaList.push_back(elemClass); From 0ef0475ba457a244a07572a864d9667c1e99b60e Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 4 Nov 2013 20:51:36 -0500 Subject: [PATCH 38/53] BUG: Implement igtl::Strnlen() for platforms that do not have strnlen. See issue #25. --- CMake/OpenIGTLinkCMakeTests.cmake | 5 +++++ Source/igtlCapabilityMessage.cxx | 3 ++- Source/igtlOSUtil.cxx | 20 ++++++++++++++++++++ Source/igtlOSUtil.h | 10 ++++++++++ igtlConfigure.h.in | 4 +++- 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CMake/OpenIGTLinkCMakeTests.cmake b/CMake/OpenIGTLinkCMakeTests.cmake index 7c4406be..54447444 100644 --- a/CMake/OpenIGTLinkCMakeTests.cmake +++ b/CMake/OpenIGTLinkCMakeTests.cmake @@ -1,6 +1,7 @@ # See if we need to link the socket library INCLUDE(CheckLibraryExists) INCLUDE(CheckSymbolExists) +INCLUDE(CheckFunctionExists) CHECK_LIBRARY_EXISTS("socket" getsockname "" OpenIGTLink_HAVE_LIBSOCKET) @@ -33,6 +34,10 @@ IF("OpenIGTLink_HAVE_GETSOCKNAME_WITH_SOCKLEN_T" MATCHES "^OpenIGTLink_HAVE_GETS ENDIF(OpenIGTLink_HAVE_GETSOCKNAME_WITH_SOCKLEN_T) ENDIF("OpenIGTLink_HAVE_GETSOCKNAME_WITH_SOCKLEN_T" MATCHES "^OpenIGTLink_HAVE_GETSOCKNAME_WITH_SOCKLEN_T$") + +# e.g. Mac OS X Snow Leopard does not have strnlen(). +CHECK_FUNCTION_EXISTS(strnlen OpenIGTLink_HAVE_STRNLEN) + # e.g. IBM BlueGene/L doesn't have SO_REUSEADDR, because "setsockopt is not needed for # BlueGene/L applications" according to the BlueGene/L Application Development handbook CHECK_SYMBOL_EXISTS(SO_REUSEADDR "sys/types.h;sys/socket.h" OpenIGTLink_HAVE_SO_REUSEADDR) diff --git a/Source/igtlCapabilityMessage.cxx b/Source/igtlCapabilityMessage.cxx index d1619027..2ae24ca7 100755 --- a/Source/igtlCapabilityMessage.cxx +++ b/Source/igtlCapabilityMessage.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -151,7 +152,7 @@ int CapabilityMessage::UnpackBody() for(int i = 0; i < ntypes; i++) { std::string buf; - if (strnlen((const char*)info.typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) + if (igtl::Strnlen((const char*)info.typenames[i], IGTL_HEADER_TYPE_SIZE) < IGTL_HEADER_TYPE_SIZE) { buf.append((const char*)info.typenames[i]); } diff --git a/Source/igtlOSUtil.cxx b/Source/igtlOSUtil.cxx index 17e119bf..0e021eed 100644 --- a/Source/igtlOSUtil.cxx +++ b/Source/igtlOSUtil.cxx @@ -20,6 +20,8 @@ #include #endif +#include + namespace igtl { @@ -39,7 +41,25 @@ void Sleep(int milliseconds) nanosleep(&req, NULL); #endif +} + + + +// strnlen(), if not defined +#ifndef OpenIGTLink_HAVE_STRNLEN +size_t Strnlen(const char* s, size_t maxlen) +{ + + size_t i; + + for(i = 0; i < maxlen; i++) { + if(s[i] == '\0') return i; + } + return maxlen; + } +#endif + } diff --git a/Source/igtlOSUtil.h b/Source/igtlOSUtil.h index f6d1ac75..4b8f7d1b 100644 --- a/Source/igtlOSUtil.h +++ b/Source/igtlOSUtil.h @@ -15,6 +15,8 @@ #ifndef __igltOSUtil_h #define __igltOSUtil_h +#include + #include "igtlWin32Header.h" namespace igtl { @@ -24,6 +26,14 @@ namespace igtl * */ void IGTLCommon_EXPORT Sleep(int millisecond); + /** Just in case strnlen() is not defined (e.g. Mac OS X Snow Leopard) */ +#ifndef OpenIGTLink_HAVE_STRNLEN + size_t IGTLCommon_EXPORT Strnlen(const char* s, size_t maxlen); +#else + inline size_t IGTLCommon_EXPORT Strnlen(const char* s, size_t maxlen) + { return strnlen(s, maxlen); } +#endif + } #endif // __igltOSUtil_h diff --git a/igtlConfigure.h.in b/igtlConfigure.h.in index 0b89b46c..ae1b98e3 100644 --- a/igtlConfigure.h.in +++ b/igtlConfigure.h.in @@ -1,6 +1,6 @@ /*========================================================================= - Program: Open IGT Link Library + Program: OpenIGTLink Library Module: $HeadURL: http://svn.na-mic.org/NAMICSandBox/trunk/OpenIGTLink/igtlConfigure.h.in $ Language: C Date: $Date: 2010-06-09 16:16:36 -0400 (Wed, 09 Jun 2010) $ @@ -35,6 +35,8 @@ #cmakedefine OpenIGTLink_USE_WIN32_THREADS #cmakedefine OpenIGTLink_USE_SPROC #cmakedefine OpenIGTLink_HAVE_GETSOCKNAME_WITH_SOCKLEN_T +#cmakedefine OpenIGTLink_HAVE_STRNLEN + #define OpenIGTLink_PROTOCOL_VERSION @OpenIGTLink_PROTOCOL_VERSION@ #endif /*__IGTL_CONFIGURE_H*/ From e9a56c985aae4da573db34a71ba403ce40cf61ba Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 4 Nov 2013 22:26:22 -0500 Subject: [PATCH 39/53] STYLE: Increment the patch number. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bed541e2..fb4b0b6c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "3") +SET(OpenIGTLink_VERSION_PATCH "4") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From f703226091f9bff0f7936cb5412e7081fa498fa2 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Mon, 4 Nov 2013 22:46:15 -0500 Subject: [PATCH 40/53] COMP: Fix compiler warnings for Mac OS X Mavericks. --- Source/igtlutil/igtl_capability.c | 4 ++-- Testing/igtlutil/igtl_bind_test.c | 1 + Testing/igtlutil/igtl_capability_test.c | 8 ++++---- Testing/igtlutil/igtl_colortable_test.c | 2 ++ Testing/igtlutil/igtl_lbmeta_test.c | 1 + Testing/igtlutil/igtl_ndarray_test.c | 1 + Testing/igtlutil/igtl_point_test.c | 2 ++ Testing/igtlutil/igtl_polydata_test.c | 1 + Testing/igtlutil/igtl_string_test.c | 2 +- Testing/igtlutil/igtl_tdata_test.c | 1 + Testing/igtlutil/igtl_test_data_polydata.h | 2 +- 11 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Source/igtlutil/igtl_capability.c b/Source/igtlutil/igtl_capability.c index 1cb16e8e..0ac83675 100644 --- a/Source/igtlutil/igtl_capability.c +++ b/Source/igtlutil/igtl_capability.c @@ -128,7 +128,7 @@ int igtl_export igtl_capability_unpack(void * byte_array, igtl_capability_info * ptr = byte_array; for (i = 0; i < ntypes; i ++) { - strncpy(info->typenames[i], ptr, IGTL_HEADER_TYPE_SIZE); + strncpy((char*)info->typenames[i], (char*)ptr, IGTL_HEADER_TYPE_SIZE); info->typenames[i][IGTL_HEADER_TYPE_SIZE] = '\0'; ptr += IGTL_HEADER_TYPE_SIZE; } @@ -157,7 +157,7 @@ int igtl_export igtl_capability_pack(igtl_capability_info * info, void * byte_ar for (i = 0; i < info->ntypes; i ++) { - strncpy(ptr, info->typenames[i], IGTL_HEADER_TYPE_SIZE); + strncpy((char*)ptr, (char*)info->typenames[i], IGTL_HEADER_TYPE_SIZE); ptr += IGTL_HEADER_TYPE_SIZE; } diff --git a/Testing/igtlutil/igtl_bind_test.c b/Testing/igtlutil/igtl_bind_test.c index 3cbb7811..f03ae46e 100644 --- a/Testing/igtlutil/igtl_bind_test.c +++ b/Testing/igtlutil/igtl_bind_test.c @@ -24,6 +24,7 @@ #include "igtl_transform.h" #include #include +#include #define EXIT_SUCCESS 0 diff --git a/Testing/igtlutil/igtl_capability_test.c b/Testing/igtlutil/igtl_capability_test.c index f137b219..69676785 100644 --- a/Testing/igtlutil/igtl_capability_test.c +++ b/Testing/igtlutil/igtl_capability_test.c @@ -54,10 +54,10 @@ int main( int argc, char * argv [] ) return EXIT_FAILURE; } - strcpy(info.typenames[0], "IMAGE"); - strcpy(info.typenames[1], "GET_IMAGE"); - strcpy(info.typenames[2], "TRANSFORM"); - strcpy(info.typenames[3], "GET_TRANS"); + strcpy((char*)info.typenames[0], "IMAGE"); + strcpy((char*)info.typenames[1], "GET_IMAGE"); + strcpy((char*)info.typenames[2], "TRANSFORM"); + strcpy((char*)info.typenames[3], "GET_TRANS"); igtl_capability_pack(&info, message.body); diff --git a/Testing/igtlutil/igtl_colortable_test.c b/Testing/igtlutil/igtl_colortable_test.c index 654870a7..da9e0fe9 100644 --- a/Testing/igtlutil/igtl_colortable_test.c +++ b/Testing/igtlutil/igtl_colortable_test.c @@ -15,6 +15,8 @@ =========================================================================*/ #include +#include + #include "igtl_types.h" #include "igtl_header.h" #include "igtl_colortable.h" diff --git a/Testing/igtlutil/igtl_lbmeta_test.c b/Testing/igtlutil/igtl_lbmeta_test.c index 499253f1..eaa8807c 100644 --- a/Testing/igtlutil/igtl_lbmeta_test.c +++ b/Testing/igtlutil/igtl_lbmeta_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" #include "igtl_lbmeta.h" diff --git a/Testing/igtlutil/igtl_ndarray_test.c b/Testing/igtlutil/igtl_ndarray_test.c index f184fec7..63bf7ad8 100644 --- a/Testing/igtlutil/igtl_ndarray_test.c +++ b/Testing/igtlutil/igtl_ndarray_test.c @@ -21,6 +21,7 @@ #include "igtl_util.h" #include #include +#include #define EXIT_SUCCESS 0 diff --git a/Testing/igtlutil/igtl_point_test.c b/Testing/igtlutil/igtl_point_test.c index 4d5bf2b6..a8990cfc 100644 --- a/Testing/igtlutil/igtl_point_test.c +++ b/Testing/igtlutil/igtl_point_test.c @@ -15,6 +15,8 @@ =========================================================================*/ #include +#include + #include "igtl_types.h" #include "igtl_header.h" #include "igtl_point.h" diff --git a/Testing/igtlutil/igtl_polydata_test.c b/Testing/igtlutil/igtl_polydata_test.c index c4f7965d..57d7538f 100644 --- a/Testing/igtlutil/igtl_polydata_test.c +++ b/Testing/igtlutil/igtl_polydata_test.c @@ -20,6 +20,7 @@ #include "igtl_util.h" #include #include +#include #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 diff --git a/Testing/igtlutil/igtl_string_test.c b/Testing/igtlutil/igtl_string_test.c index 054349b9..8257f141 100644 --- a/Testing/igtlutil/igtl_string_test.c +++ b/Testing/igtlutil/igtl_string_test.c @@ -60,7 +60,7 @@ int main( int argc, char * argv [] ) /* Set dummy string header and values */ message.string_header.encoding = 3; message.string_header.length = IGTL_STRING_TEST_STRING_LEN; - strncpy(message.string, IGTL_STRING_TEST_STRING, IGTL_STRING_TEST_STRING_LEN); + strncpy((char*)message.string, IGTL_STRING_TEST_STRING, IGTL_STRING_TEST_STRING_LEN); igtl_string_convert_byte_order(&(message.string_header)); /* Set header */ diff --git a/Testing/igtlutil/igtl_tdata_test.c b/Testing/igtlutil/igtl_tdata_test.c index e930c1ad..e55609f2 100644 --- a/Testing/igtlutil/igtl_tdata_test.c +++ b/Testing/igtlutil/igtl_tdata_test.c @@ -15,6 +15,7 @@ =========================================================================*/ #include +#include #include "igtl_types.h" #include "igtl_header.h" #include "igtl_tdata.h" diff --git a/Testing/igtlutil/igtl_test_data_polydata.h b/Testing/igtlutil/igtl_test_data_polydata.h index 501c5683..42d1e877 100644 --- a/Testing/igtlutil/igtl_test_data_polydata.h +++ b/Testing/igtlutil/igtl_test_data_polydata.h @@ -76,7 +76,7 @@ char test_polydata_message_body[] = { 0x3f, 0x80, 0x00, 0x00, /* Point #7 - y*/ 0x3f, 0x80, 0x00, 0x00, /* Point #7 - z*/ - /* No vertices * + /* No vertices */ /* No lines */ From 0308b5d159feb197c40145e53d3fcd3e0f5276c7 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Tue, 3 Dec 2013 18:57:51 -0500 Subject: [PATCH 41/53] BUG: Address issue #29: copy igtl_win32hearder.h to the install directory. --- CMakeLists.txt | 2 +- Source/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb4b0b6c..55b5511b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "4") +SET(OpenIGTLink_VERSION_PATCH "5") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 88bb1966..df08e6ba 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -67,6 +67,7 @@ SET(OpenIGTLink_INCLUDE_FILES igtlutil/igtl_types.h igtlutil/igtl_util.h igtlutil/igtl_capability.h + igtlutil/igtl_win32header.h igtlMessageHandler.h igtlMessageHandlerMacro.h igtlClientSocket.h From 752019697037fbb868807e9eee76e59949764d08 Mon Sep 17 00:00:00 2001 From: z0022myy Date: Tue, 13 May 2014 10:02:06 +0200 Subject: [PATCH 42/53] BUG: Intializing pointer should not be in a loop Pointer initialization should be done before the loop. Otherwise, the attr is reassigned at each iteration, attr++ do not have any affect, so that only the first attribute is pushed many times in the vector m_Attributes #34 --- Source/igtlPolyDataMessage.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/igtlPolyDataMessage.cxx b/Source/igtlPolyDataMessage.cxx index 1ced66fe..83214020 100644 --- a/Source/igtlPolyDataMessage.cxx +++ b/Source/igtlPolyDataMessage.cxx @@ -805,9 +805,10 @@ int PolyDataMessage::UnpackBody() // Attributes this->m_Attributes.clear(); + igtl_polydata_attribute * attr = info.attributes; for (unsigned int i = 0; i < info.header.nattributes; i ++) { - igtl_polydata_attribute * attr = info.attributes; + PolyDataAttribute::Pointer pda = PolyDataAttribute::New(); if (pda.IsNotNull()) From 904bc1e155662e9296db578e6013bfad6e7d3744 Mon Sep 17 00:00:00 2001 From: Andras Lasso Date: Mon, 19 May 2014 09:17:36 -0400 Subject: [PATCH 43/53] Add the MSG_NOSIGNAL flag to socket send calls to prevent application crash on disconnect on linux systems --- Source/igtlSocket.cxx | 19 +++++++++++++------ Source/igtlSocket.h | 2 ++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Source/igtlSocket.cxx b/Source/igtlSocket.cxx index 7028dca3..199fdfd3 100644 --- a/Source/igtlSocket.cxx +++ b/Source/igtlSocket.cxx @@ -309,12 +309,19 @@ int Socket::Send(const void* data, int length) do { int flags; -#if defined(_WIN32) && !defined(__CYGWIN__) - flags = 0; -#else - // disabling, since not present on SUN. - // flags = MSG_NOSIGNAL; //disable signal on Unix boxes. - flags = 0; +#if defined(_WIN32) && !defined(__CYGWIN__) + flags = 0; +#else + // On unix boxes if the client disconnects and the server attempts + // to send data through the socket then the application crashes + // due to SIGPIPE signal. Disable the signal to prevent crash. + #ifndef __sun + flags = MSG_NOSIGNAL; + #else + // Signal is not present on SUN systems, the signal has + // to be managed at application level. + flags = 0; + #endif #endif int n = send(this->m_SocketDescriptor, buffer+total, length-total, flags); if(n < 0) diff --git a/Source/igtlSocket.h b/Source/igtlSocket.h index e6bf5c8a..2327c404 100644 --- a/Source/igtlSocket.h +++ b/Source/igtlSocket.h @@ -82,6 +82,8 @@ class IGTLCommon_EXPORT Socket : public Object /// These methods send data over the socket. /// Returns 1 on success, 0 on error and raises vtkCommand::ErrorEvent. + /// SIGPIPE or other signal may be raised on systems (e.g., Sun Solaris) where + /// MSG_NOSIGNAL flag is not supported for the socket send method. int Send(const void* data, int length); /// Receive data from the socket. From 9f60ee5cd6dba2561cedeebd681ef1e1c9cf301f Mon Sep 17 00:00:00 2001 From: Laurent Chauvin Date: Fri, 27 Jun 2014 08:59:59 -0400 Subject: [PATCH 44/53] BUG: Initialize ImageMessage matrix to identity (issue #39) --- Source/igtlImageMessage.cxx | 9 ++------- Source/igtlImageMessage.h | 1 + Source/igtlImageMessage2.cxx | 9 ++------- Source/igtlImageMessage2.h | 1 + 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/Source/igtlImageMessage.cxx b/Source/igtlImageMessage.cxx index ba0d4e60..b0231c31 100644 --- a/Source/igtlImageMessage.cxx +++ b/Source/igtlImageMessage.cxx @@ -30,19 +30,14 @@ ImageMessage::ImageMessage(): subDimensions[i] = 0; subOffset[i] = 0; } - for (int i = 0; i < 3; i ++) + for (int i = 0; i < 4; i ++) { for (int j = 0; j < 4; j ++) { - matrix[i][j] = 0.0; + matrix[i][j] = (i == j ? 1.0 : 0.0); } } - matrix[3][0] = 0.0; - matrix[3][1] = 0.0; - matrix[3][2] = 0.0; - matrix[3][3] = 1.0; - endian = ENDIAN_BIG; coordinate = COORDINATE_RAS; scalarType = TYPE_UINT8; diff --git a/Source/igtlImageMessage.h b/Source/igtlImageMessage.h index 672c23b6..31b11bb3 100644 --- a/Source/igtlImageMessage.h +++ b/Source/igtlImageMessage.h @@ -283,6 +283,7 @@ class IGTLCommon_EXPORT ImageMessage: public MessageBase int subOffset[3]; /// A matrix representing the origin and the orientation of the image. + /// The matrix is set to identity by default Matrix4x4 matrix; /// A variable for the Endian of the scalar values in the image. diff --git a/Source/igtlImageMessage2.cxx b/Source/igtlImageMessage2.cxx index 78fcc97d..d5fa8671 100644 --- a/Source/igtlImageMessage2.cxx +++ b/Source/igtlImageMessage2.cxx @@ -32,19 +32,14 @@ ImageMessage2::ImageMessage2(): subDimensions[i] = 0; subOffset[i] = 0; } - for (int i = 0; i < 3; i ++) + for (int i = 0; i < 4; i ++) { for (int j = 0; j < 4; j ++) { - matrix[i][j] = 0.0; + matrix[i][j] = (i == j ? 1.0 : 0.0); } } - matrix[3][0] = 0.0; - matrix[3][1] = 0.0; - matrix[3][2] = 0.0; - matrix[3][3] = 1.0; - endian = ENDIAN_BIG; coordinate = COORDINATE_RAS; scalarType = TYPE_UINT8; diff --git a/Source/igtlImageMessage2.h b/Source/igtlImageMessage2.h index 6bbaf727..d400e256 100644 --- a/Source/igtlImageMessage2.h +++ b/Source/igtlImageMessage2.h @@ -340,6 +340,7 @@ class IGTLCommon_EXPORT ImageMessage2: public MessageBase int subOffset[3]; /// A matrix representing the origin and the orientation of the image. + /// The matrix is set to identity by default Matrix4x4 matrix; /// A variable for the Endian of the scalar values in the image. From a60dfbecf806703dbe17ae1c5d859dad3650d745 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Thu, 10 Jul 2014 15:40:18 +0100 Subject: [PATCH 45/53] #44: Put nanosleep in loop to ensure sleep is for the correct time. --- Source/igtlOSUtil.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/igtlOSUtil.cxx b/Source/igtlOSUtil.cxx index 0e021eed..692bf95b 100644 --- a/Source/igtlOSUtil.cxx +++ b/Source/igtlOSUtil.cxx @@ -18,6 +18,7 @@ #include #else #include + #include #endif #include @@ -37,8 +38,11 @@ void Sleep(int milliseconds) struct timespec req; req.tv_sec = (int) milliseconds / 1000; req.tv_nsec = (milliseconds % 1000) * 1000000; - - nanosleep(&req, NULL); + + while ((nanosleep(&req, &req) == -1) && (errno == EINTR)) + { + continue; + } #endif } From becb16cddc0dfbbeaf5915c4f1d2314d6bf21d8c Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Fri, 11 Jul 2014 14:40:30 +0100 Subject: [PATCH 46/53] #49: Avoid crash on division by zero, which should never happen --- Source/igtlutil/igtl_image.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Source/igtlutil/igtl_image.c b/Source/igtlutil/igtl_image.c index c52679da..914aa907 100644 --- a/Source/igtlutil/igtl_image.c +++ b/Source/igtlutil/igtl_image.c @@ -104,15 +104,26 @@ void igtl_export igtl_image_get_matrix(float spacing[3], float origin[3], spacing[0] = sqrtf(tx*tx + ty*ty + tz*tz); spacing[1] = sqrtf(sx*sx + sy*sy + sz*sz); spacing[2] = sqrtf(nx*nx + ny*ny + nz*nz); - norm_i[0] = header->matrix[0] / spacing[0]; - norm_i[1] = header->matrix[1] / spacing[0]; - norm_i[2] = header->matrix[2] / spacing[0]; - norm_j[0] = header->matrix[3] / spacing[1]; - norm_j[1] = header->matrix[4] / spacing[1]; - norm_j[2] = header->matrix[5] / spacing[1]; - norm_k[0] = header->matrix[6] / spacing[2]; - norm_k[1] = header->matrix[7] / spacing[2]; - norm_k[2] = header->matrix[8] / spacing[2]; + + if (spacing[0] != 0) + { + norm_i[0] = header->matrix[0] / spacing[0]; + norm_i[1] = header->matrix[1] / spacing[0]; + norm_i[2] = header->matrix[2] / spacing[0]; + } + if (spacing[1] != 0) + { + norm_j[0] = header->matrix[3] / spacing[1]; + norm_j[1] = header->matrix[4] / spacing[1]; + norm_j[2] = header->matrix[5] / spacing[1]; + } + if (spacing[2] != 0) + { + norm_k[0] = header->matrix[6] / spacing[2]; + norm_k[1] = header->matrix[7] / spacing[2]; + norm_k[2] = header->matrix[8] / spacing[2]; + } + origin[0] = header->matrix[9]; origin[1] = header->matrix[10]; origin[2] = header->matrix[11]; From 89e0ac4e40ff7056e3cb5083b1d8ed393e4295f0 Mon Sep 17 00:00:00 2001 From: Matt Clarkson Date: Fri, 11 Jul 2014 14:43:37 +0100 Subject: [PATCH 47/53] #50: Convenience methods to set/get igtl_image matrix from 4x4 array of floats --- Source/igtlutil/igtl_image.c | 39 +++++++++++++++++++++++++++++++++++++++ Source/igtlutil/igtl_image.h | 6 ++++++ 2 files changed, 45 insertions(+) diff --git a/Source/igtlutil/igtl_image.c b/Source/igtlutil/igtl_image.c index c52679da..c1d47ddc 100644 --- a/Source/igtlutil/igtl_image.c +++ b/Source/igtlutil/igtl_image.c @@ -71,6 +71,22 @@ void igtl_export igtl_image_set_matrix(float spacing[3], float origin[3], header->matrix[11] = (igtl_float32) (origin[2]); } +void igtl_export igtl_image_set_matrix_4x4(float _matrix [4][4], igtl_image_header * header) +{ + header->matrix[0] = _matrix[0][0]; + header->matrix[1] = _matrix[0][1]; + header->matrix[2] = _matrix[0][2]; + header->matrix[3] = _matrix[1][0]; + header->matrix[4] = _matrix[1][1]; + header->matrix[5] = _matrix[1][2]; + header->matrix[6] = _matrix[2][0]; + header->matrix[7] = _matrix[2][1]; + header->matrix[8] = _matrix[2][2]; + header->matrix[9] = _matrix[0][3]; + header->matrix[10] = _matrix[1][3]; + header->matrix[11] = _matrix[2][3]; +} + void igtl_export igtl_image_get_matrix(float spacing[3], float origin[3], float norm_i[3], float norm_j[3], float norm_k[3], igtl_image_header * header) @@ -120,6 +136,29 @@ void igtl_export igtl_image_get_matrix(float spacing[3], float origin[3], } +void igtl_export igtl_image_get_matrix_4x4(float _matrix[4][4], igtl_image_header * header) +{ + _matrix[0][0] = header->matrix[0]; + _matrix[0][1] = header->matrix[1]; + _matrix[0][2] = header->matrix[2]; + _matrix[1][0] = header->matrix[3]; + _matrix[1][1] = header->matrix[4]; + _matrix[1][2] = header->matrix[5]; + _matrix[2][0] = header->matrix[6]; + _matrix[2][1] = header->matrix[7]; + _matrix[2][2] = header->matrix[8]; + + _matrix[0][3] = header->matrix[9]; + _matrix[1][3] = header->matrix[10]; + _matrix[2][3] = header->matrix[11]; + + _matrix[3][0] = 0; + _matrix[3][1] = 0; + _matrix[3][2] = 0; + _matrix[3][3] = 1; +} + + void igtl_export igtl_image_convert_byte_order(igtl_image_header * header) { int i; diff --git a/Source/igtlutil/igtl_image.h b/Source/igtlutil/igtl_image.h index 7fa939e3..e8db0567 100644 --- a/Source/igtlutil/igtl_image.h +++ b/Source/igtlutil/igtl_image.h @@ -98,6 +98,12 @@ void igtl_export igtl_image_get_matrix(float spacing[3], float origin[3], float norm_i[3], float norm_j[3], float norm_k[3], igtl_image_header * header); +/** Sets the image orientation/origin matrix in 4x4 format */ +void igtl_export igtl_image_set_matrix_4x4(float _matrix[4][4],igtl_image_header * header); + +/** Gets the image orientation/origin matrix in 4x4 format */ +void igtl_export igtl_image_get_matrix_4x4(float _matrix[4][4],igtl_image_header * header); + /** Converts endianness of each member variable in igtl_image_header from host * byte order to network byte order, or vice versa. */ void igtl_export igtl_image_convert_byte_order(igtl_image_header * header); From 67c6a100490e78854be537ccbaca7d59387f8137 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 11:40:37 -0400 Subject: [PATCH 48/53] ENH: Update patch number. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 55b5511b..2ae4672e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "5") +SET(OpenIGTLink_VERSION_PATCH "6") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From b844399cf904afe0844d36ee4f5373d2649ccf79 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 11:51:30 -0400 Subject: [PATCH 49/53] STYLE: Update patch number. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ae4672e..d0ac4736 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "6") +SET(OpenIGTLink_VERSION_PATCH "7") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From 479cdc93c9d912cf1ac3fe7e21e1936de608d864 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 16:21:55 -0400 Subject: [PATCH 50/53] COMP: Fix compilation error due to lack of MSG_NOSIGNAL option in send() in Mac OS X. For Mac OS X, call setsockopt() with SO_NOSIGPIPE instead. --- Source/igtlSocket.cxx | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Source/igtlSocket.cxx b/Source/igtlSocket.cxx index 199fdfd3..b447ccc2 100644 --- a/Source/igtlSocket.cxx +++ b/Source/igtlSocket.cxx @@ -309,19 +309,28 @@ int Socket::Send(const void* data, int length) do { int flags; -#if defined(_WIN32) && !defined(__CYGWIN__) - flags = 0; -#else - // On unix boxes if the client disconnects and the server attempts - // to send data through the socket then the application crashes - // due to SIGPIPE signal. Disable the signal to prevent crash. - #ifndef __sun - flags = MSG_NOSIGNAL; - #else - // Signal is not present on SUN systems, the signal has - // to be managed at application level. - flags = 0; - #endif +#if defined(_WIN32) && !defined(__CYGWIN__) + flags = 0; +#else + // On unix boxes if the client disconnects and the server attempts + // to send data through the socket then the application crashes + // due to SIGPIPE signal. Disable the signal to prevent crash. + //#ifndef __sun + // flags = MSG_NOSIGNAL; + //#else + // // Signal is not present on SUN systems, the signal has + // // to be managed at application level. + // flags = 0; + //#endif + #if defined(MSG_NOSIGNAL) // For Linux > 2.2 + flags = MSG_NOSIGNAL; + #else + #if defined(SO_NOSIGPIPE) // Mac OS X + int set = 1; + setsockopt(this->m_SocketDescriptor, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); + #endif + flags = 0; + #endif #endif int n = send(this->m_SocketDescriptor, buffer+total, length-total, flags); if(n < 0) From ad210e9226a1731b4979cf6e6beafdd2630d25a4 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 16:23:04 -0400 Subject: [PATCH 51/53] STYLE: Update revision number. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0ac4736..991a2096 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "7") +SET(OpenIGTLink_VERSION_PATCH "8") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) From 07a91d937cf076f4abd29823cacc3fe272a81916 Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 16:59:50 -0400 Subject: [PATCH 52/53] BUG: Set timestamp zero, when no timestamp object is registered to image meta message. --- CMakeLists.txt | 2 +- Source/igtlImageMetaMessage.cxx | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 991a2096..03baaaa5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "8") +SET(OpenIGTLink_VERSION_PATCH "9") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON) diff --git a/Source/igtlImageMetaMessage.cxx b/Source/igtlImageMetaMessage.cxx index 514b01fe..b811f624 100644 --- a/Source/igtlImageMetaMessage.cxx +++ b/Source/igtlImageMetaMessage.cxx @@ -257,7 +257,14 @@ int ImageMetaMessage::PackBody() igtl::TimeStamp::Pointer ts; (*iter)->GetTimeStamp(ts); - element->timestamp = ts->GetTimeStampUint64(); + if (ts.IsNotNull()) + { + element->timestamp = ts->GetTimeStampUint64(); + } + else + { + element->timestamp = 0; + } igtlUint16 size[3]; (*iter)->GetSize(size); element->size[0] = size[0]; From 8d5765bba87d6601d13c5fda6d48c24bcc3772be Mon Sep 17 00:00:00 2001 From: Junichi Tokuda Date: Fri, 11 Jul 2014 17:06:44 -0400 Subject: [PATCH 53/53] STYLE: Update patch number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03baaaa5..371aae27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ if(COMMAND cmake_policy) # OpenIGTlink version number. SET(OpenIGTLink_VERSION_MAJOR "1") SET(OpenIGTLink_VERSION_MINOR "10") -SET(OpenIGTLink_VERSION_PATCH "9") +SET(OpenIGTLink_VERSION_PATCH "10") option(OpenIGTLink_PROTOCOL_VERSION_2 "Build Library for Protocol Version 2" ON)