diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp index bafb56e16b..610bcbb1c0 100644 --- a/Modules/OpenIGTLink/mitkIGTLServer.cpp +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -1,218 +1,216 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIGTLServer.h" #include #include #include #include #include #include #include mitk::IGTLServer::IGTLServer(bool ReadFully) : IGTLDevice(ReadFully) { m_ReceiveListMutex = itk::FastMutexLock::New(); m_SentListMutex = itk::FastMutexLock::New(); } mitk::IGTLServer::~IGTLServer() { m_ReceiveListMutex = nullptr; m_SentListMutex = nullptr; } bool mitk::IGTLServer::OpenConnection() { if (this->GetState() != Setup) { mitkThrowException(mitk::Exception) << "Can only try to create a server if in setup mode"; return false; } int portNumber = this->GetPortNumber(); if (portNumber == -1) { //port number was not correct return false; } //create a new server socket m_Socket = igtl::ServerSocket::New(); //try to create the igtl server int response = dynamic_cast(m_Socket.GetPointer())-> CreateServer(portNumber); //check the response if (response != 0) { mitkThrowException(mitk::Exception) << "The server could not be created. Port: " << portNumber; return false; } // everything is initialized and connected so the communication can be started this->SetState(Ready); return true; } bool mitk::IGTLServer::CloseConnection() { //remove all registered clients m_SentListMutex->Lock(); m_ReceiveListMutex->Lock(); SocketListType allRegisteredSockets(m_RegisteredClients); m_SentListMutex->Unlock(); m_ReceiveListMutex->Unlock(); this->StopCommunicationWithSocket(allRegisteredSockets); return mitk::IGTLDevice::CloseConnection(); } void mitk::IGTLServer::Connect() { igtl::Socket::Pointer socket; //check if another igtl device wants to connect to this socket socket = ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(1); //if there is a new connection the socket is not null if (socket.IsNotNull()) { //add the new client socket to the list of registered clients m_SentListMutex->Lock(); m_ReceiveListMutex->Lock(); this->m_RegisteredClients.push_back(socket); m_SentListMutex->Unlock(); m_ReceiveListMutex->Unlock(); //inform observers about this new client this->InvokeEvent(NewClientConnectionEvent()); MITK_INFO("IGTLServer") << "Connected to a new client: " << socket; } } void mitk::IGTLServer::Receive() { unsigned int status = IGTL_STATUS_OK; SocketListType socketsToBeRemoved; //the server can be connected with several clients, therefore it has to check //all registered clients SocketListIteratorType it; m_ReceiveListMutex->Lock(); auto it_end = this->m_RegisteredClients.end(); for (it = this->m_RegisteredClients.begin(); it != it_end; ++it) { //it is possible that ReceivePrivate detects that the current socket is //already disconnected. Therefore, it is necessary to remove this socket //from the registered clients list status = this->ReceivePrivate(*it); if (status == IGTL_STATUS_NOT_PRESENT) { //remember this socket for later, it is not a good idea to remove it //from the list directly because we iterate over the list at this point socketsToBeRemoved.push_back(*it); MITK_WARN("IGTLServer") << "Lost connection to a client socket. "; } else if (status != 1) { - MITK_WARN("IGTLServer") << "IGTL Message with status: " << status; + MITK_DEBUG("IGTLServer") << "IGTL Message with status: " << status; } } m_ReceiveListMutex->Unlock(); if (socketsToBeRemoved.size() > 0) { //remove the sockets that are not connected anymore this->StopCommunicationWithSocket(socketsToBeRemoved); //inform observers about loosing the connection to these sockets this->InvokeEvent(LostConnectionEvent()); } } void mitk::IGTLServer::Send() { - igtl::MessageBase::Pointer curMessage; - //get the latest message from the queue - curMessage = this->m_MessageQueue->PullSendMessage(); + mitk::IGTLMessage::Pointer curMessage = this->m_MessageQueue->PullSendMessage(); // there is no message => return if (curMessage.IsNull()) return; //the server can be connected with several clients, therefore it has to check //all registered clients //sending a message to all registered clients might not be the best solution, //it could be better to store the client together with the requested type. Then //the data would be send to the appropriate client and to noone else. //(I know it is no excuse but PLUS is doing exactly the same, they broadcast //everything) m_SentListMutex->Lock(); SocketListIteratorType it; auto it_end = this->m_RegisteredClients.end(); for (it = this->m_RegisteredClients.begin(); it != it_end; ++it) { //maybe there should be a check here if the current socket is still active - this->SendMessagePrivate(curMessage.GetPointer(), *it); + this->SendMessagePrivate(curMessage, *it); MITK_DEBUG("IGTLServer") << "Sent IGTL Message"; } m_SentListMutex->Unlock(); } void mitk::IGTLServer::StopCommunicationWithSocket( SocketListType& toBeRemovedSockets) { for (auto i = toBeRemovedSockets.begin(); i != toBeRemovedSockets.end(); i++) this->StopCommunicationWithSocket(*i); } void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) { m_SentListMutex->Lock(); m_ReceiveListMutex->Lock(); auto i = m_RegisteredClients.begin(); auto end = m_RegisteredClients.end(); while (i != end) { if ((*i) == client) { // //close the socket (*i)->CloseSocket(); //and remove it from the list i = this->m_RegisteredClients.erase(i); MITK_INFO("IGTLServer") << "Removed client socket from server client list."; break; } else { ++i; } } m_SentListMutex->Unlock(); m_ReceiveListMutex->Unlock(); } unsigned int mitk::IGTLServer::GetNumberOfConnections() { return this->m_RegisteredClients.size(); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp index 1f99fadace..075e100236 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp @@ -1,293 +1,293 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLDeviceCommandWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLDeviceCommandWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLDeviceCommandWidget::QmitkIGTLDeviceCommandWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false), m_MessageReceivedObserverTag(0), m_CommandReceivedObserverTag(0), m_LostConnectionObserverTag(0), m_NewConnectionObserverTag(0), m_StateModifiedObserverTag(0) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLDeviceCommandWidget::~QmitkIGTLDeviceCommandWidget() { if (m_MessageReceivedObserverTag) this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); if (m_CommandReceivedObserverTag) this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); if (m_LostConnectionObserverTag) this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); if (m_NewConnectionObserverTag) this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); if (m_StateModifiedObserverTag) this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } void QmitkIGTLDeviceCommandWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceCommandWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceCommandWidget::CreateConnections() { if (m_Controls) { // connect the widget items with the methods connect( m_Controls->butSendCommand, SIGNAL(clicked()), this, SLOT(OnSendCommand())); connect( m_Controls->commandsComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(OnCommandChanged(const QString &))); } //this is used for thread seperation, otherwise the worker thread would change the ui elements //which would cause an exception connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); } void QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged() { //this->AdaptGUIToState(); emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::AdaptGUIToState() { if (this->m_IGTLDevice.IsNotNull()) { //check the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: this->m_Controls->commandsComboBox->setEnabled(false); this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Ready: this->m_Controls->commandsComboBox->setEnabled(true); this->m_Controls->butSendCommand->setEnabled(true); this->m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Running: if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) { //just a server can run and have 0 connections this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); this->m_Controls->commandsComboBox->setEnabled(false); } else { this->m_Controls->commandsComboBox->setEnabled(true); this->m_Controls->butSendCommand->setEnabled(true); // this->m_Controls->fpsSpinBox->setEnabled(true); } break; default: mitkThrow() << "Invalid Device State"; break; } } else { this->DisableSourceControls(); } } void QmitkIGTLDeviceCommandWidget::Initialize(mitk::IGTLDevice::Pointer device) { //reset the GUI DisableSourceControls(); //reset the observers if ( this->m_IGTLDevice.IsNotNull() ) { this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } if(device.IsNotNull()) { //get the device this->m_IGTLDevice = device; //check if the device is a server or a client if ( dynamic_cast( this->m_IGTLDevice.GetPointer()) == NULL ) { m_IsClient = false; } else { m_IsClient = true; } typedef itk::SimpleMemberCommand< QmitkIGTLDeviceCommandWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLDeviceCommandWidget::OnMessageReceived ); // this->m_MessageReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); // commandReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLDeviceCommandWidget::OnCommandReceived ); // this->m_CommandReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnLostConnection ); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnNewConnection ); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged ); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); //Fill the commands combo box with all available commands FillCommandsComboBox(); } else { m_IGTLDevice = NULL; } this->AdaptGUIToState(); } void QmitkIGTLDeviceCommandWidget::DisableSourceControls() { this->m_Controls->commandsComboBox->setEnabled(false); this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); } void QmitkIGTLDeviceCommandWidget::OnSendCommand() { //Set the frames per second of the current command in case of a STT_ command if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_BIND" ) == 0 ) { ((igtl::StartBindMessage*)this->m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) { ((igtl::StartQuaternionTrackingDataMessage*)m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) { ((igtl::StartTrackingDataMessage*)this->m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } - m_IGTLDevice->SendMessage(m_CurrentCommand.GetPointer()); + m_IGTLDevice->SendMessage(mitk::IGTLMessage::New(m_CurrentCommand, "")); } void QmitkIGTLDeviceCommandWidget::OnCommandChanged( const QString & curCommand) { if ( curCommand.isEmpty() ) return; mitk::IGTLMessageFactory::Pointer msgFactory = this->m_IGTLDevice->GetMessageFactory(); //create a new message that fits to the selected get message type command this->m_CurrentCommand = msgFactory->CreateInstance( curCommand.toStdString()); //enable/disable the FPS spinbox this->m_Controls->fpsSpinBox->setEnabled(curCommand.contains("STT_")); } void QmitkIGTLDeviceCommandWidget::OnLostConnection() { //get the IGTL device that invoked this event // mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; //this->AdaptGUIToState(); emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::OnNewConnection() { //this->AdaptGUIToState(); emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::FillCommandsComboBox() { //load the msg factory from the client (maybe this will be moved later on) mitk::IGTLMessageFactory::Pointer msgFactory = this->m_IGTLDevice->GetMessageFactory(); //get the available commands as std::list std::list commandsList_ = msgFactory->GetAvailableMessageRequestTypes(); //create a string list to convert the std::list this->m_Controls->commandsComboBox->clear(); while ( commandsList_.size() ) { //fill the combo box with life this->m_Controls->commandsComboBox->addItem( QString::fromStdString(commandsList_.front())); commandsList_.pop_front(); } }