diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp index ae326785ac..667cbf648b 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp @@ -1,359 +1,369 @@ /*=================================================================== 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 "mitkIGTLMessageProvider.h" #include "mitkIGTLDevice.h" #include "mitkIGTLMessage.h" #include "mitkIGTLMessageFactory.h" #include "mitkCallbackFromGUIThread.h" //Microservices #include "usServiceReference.h" #include "usModuleContext.h" #include "usServiceEvent.h" #include "mitkServiceInterface.h" #include "usGetModuleContext.h" //igt (remove this later) #include "igtlBindMessage.h" #include "igtlQuaternionTrackingDataMessage.h" #include "igtlTrackingDataMessage.h" #ifndef WIN32 #include #endif mitk::IGTLMessageProvider::IGTLMessageProvider() : mitk::IGTLDeviceSource() { this->SetName("IGTLMessageProvider"); m_MultiThreader = itk::MultiThreader::New(); m_StreamingTimeMutex = itk::FastMutexLock::New(); m_StopStreamingThreadMutex = itk::FastMutexLock::New(); m_ThreadId = 0; + m_IsStreaming = false; } mitk::IGTLMessageProvider::~IGTLMessageProvider() { // terminate worker thread on destruction this->m_StopStreamingThreadMutex->Lock(); this->m_StopStreamingThread = true; this->m_StopStreamingThreadMutex->Unlock(); if ( m_ThreadId >= 0) { this->m_MultiThreader->TerminateThread(m_ThreadId); } } void mitk::IGTLMessageProvider::GenerateData() { if (this->m_IGTLDevice.IsNull()) return; for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) { const IGTLMessage* msg = this->GetInput(index); assert(msg); if ( !msg->IsDataValid() ) { continue; } igtl::MessageBase::Pointer igtlMsg = msg->GetMessage(); if ( igtlMsg.IsNotNull() ) { //send the message this->m_IGTLDevice->SendMessage(igtlMsg); } } } void mitk::IGTLMessageProvider::CreateOutputs() { //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--) this->RemoveOutput(numOP); this->Modified(); } //fill the outputs if a valid OpenIGTLink device is set if (m_IGTLDevice.IsNull()) return; this->SetNumberOfIndexedOutputs(1); if (this->GetOutput(0) == NULL) { DataObjectPointer newOutput = this->MakeOutput(0); this->SetNthOutput(0, newOutput); this->Modified(); } } //void mitk::IGTLMessageProvider::UpdateOutputInformation() //{ // this->Modified(); // make sure that we need to be updated // Superclass::UpdateOutputInformation(); //} void mitk::IGTLMessageProvider::OnIncomingMessage() { } std::string RemoveRequestPrefixes(std::string requestType) { return requestType.substr(4); } void mitk::IGTLMessageProvider::OnIncomingCommand() { //get the next command igtl::MessageBase::Pointer curCommand = this->m_IGTLDevice->GetNextCommand(); //extract the type const char * requestType = curCommand->GetDeviceType(); //check the type std::string reqType(requestType); bool isGetMsg = !reqType.find("GET_"); bool isSTTMsg = !reqType.find("STT_"); bool isSTPMsg = !reqType.find("STP_"); bool isRTSMsg = !reqType.find("RTS_"); //get the type from the request type (remove STT_, STP_, GET_, RTS_) std::string type = RemoveRequestPrefixes(requestType); //check all microservices if there is a fitting source for the requested type mitk::IGTLMessageSource::Pointer source = this->GetFittingSource(type.c_str()); //if there is no fitting source return a RTS message, if there is a RTS //type defined in the message factory send it if ( source.IsNull() ) { if ( !this->GetIGTLDevice()->SendRTSMessage(type.c_str()) ) { //sending RTS message failed, probably because the type is not in the //message factory MITK_WARN("IGTLMessageProvider") << "Tried to send a RTS message but did " "not succeed. Check if this type ( " << type << " ) was added to the message " "factory. "; } } else { if ( isGetMsg ) //if it is a single value push it into sending queue { //first it is necessary to update the source. This needs additional time //but is necessary. But are we really allowed to call this here? In which //thread are we? Is the source thread safe? source->Update(); mitk::IGTLMessage::Pointer sourceOutput = source->GetOutput(); if (sourceOutput.IsNotNull() && sourceOutput->IsDataValid()) { igtl::MessageBase::Pointer sourceMsg = sourceOutput->GetMessage(); if ( source.IsNotNull() ) { this->GetIGTLDevice()->SendMessage(sourceMsg); } } } else if ( isSTTMsg ) { //read the requested frames per second int fps = 10; //read the fps from the command igtl::MessageBase* curCommandPt = curCommand.GetPointer(); if ( std::strcmp( curCommand->GetDeviceType(), "STT_BIND" ) == 0 ) { fps = ((igtl::StartBindMessage*)curCommandPt)->GetResolution(); } else if ( std::strcmp( curCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) { fps = ((igtl::StartQuaternionTrackingDataMessage*)curCommandPt)->GetResolution(); } else if ( std::strcmp( curCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) { fps = ((igtl::StartTrackingDataMessage*)curCommandPt)->GetResolution(); } this->StartStreamingOfSource(source, fps); } else if ( isSTPMsg ) { this->StopStreamingOfSource(source); } else { //do nothing } } } +bool mitk::IGTLMessageProvider::IsStreaming() +{ + return m_IsStreaming; +} + void mitk::IGTLMessageProvider::StartStreamingOfSource(IGTLMessageSource* src, unsigned int fps) { if ( src == NULL ) return; //so far the provider allows the streaming of a single source only //if the streaming thread is already running return a RTS message - if ( this->m_ThreadId == 0 ) + if ( !m_IsStreaming ) { //if it is a stream establish a connection between the provider and the //source this->ConnectTo(src); // calculate the streaming time this->m_StreamingTimeMutex->Lock(); this->m_StreamingTime = 1.0 / (double) fps * 1000.0; this->m_StreamingTimeMutex->Unlock(); // Create a command object. The function will be called later from the // main thread this->m_StreamingCommand = ProviderCommand::New(); m_StreamingCommand->SetCallbackFunction(this, &mitk::IGTLMessageProvider::Update); // For streaming we need a continues time signal, since there is no timer // available we start a thread that generates a timing signal // This signal is invoked from the other thread the update of the pipeline // has to be executed from the main thread. Thus, we use the // callbackfromGUIThread class to pass the execution to the main thread this->m_ThreadId = m_MultiThreader->SpawnThread(this->TimerThread, this); + this->m_IsStreaming = true; } else { MITK_WARN("IGTLMessageProvider") << "This provider just supports the " "streaming of one source."; } } void mitk::IGTLMessageProvider::StopStreamingOfSource(IGTLMessageSource* src) { this->DisconnectFrom(src); this->m_StopStreamingThreadMutex->Lock(); this->m_StopStreamingThread = true; this->m_StopStreamingThreadMutex->Unlock(); + + //does this flag needs a mutex??? + this->m_IsStreaming = false; } mitk::IGTLMessageSource::Pointer mitk::IGTLMessageProvider::GetFittingSource(const char* requestedType) { //get the context us::ModuleContext* context = us::GetModuleContext(); //define the interface name std::string interface = mitk::IGTLMessageSource::US_INTERFACE_NAME; //specify a filter that defines the requested type std::string filter = "(" + mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE + "=" + requestedType + ")"; //find the fitting service std::vector serviceReferences = context->GetServiceReferences(interface, filter); //check if a service reference was found. It is also possible that several //services were found. This is not checked here, just the first one is taken. if ( serviceReferences.size() ) { mitk::IGTLMessageSource::Pointer curSource = context->GetService(serviceReferences.front()); if ( curSource.IsNotNull() ) return curSource; } //no service reference was found or found service reference has no valid source return NULL; } void mitk::IGTLMessageProvider::Send(const mitk::IGTLMessage* msg) { if (msg != NULL) this->m_IGTLDevice->SendMessage(msg); } void mitk::IGTLMessageProvider::ConnectTo( mitk::IGTLMessageSource* UpstreamFilter ) { for (DataObjectPointerArraySizeType i = 0; i < UpstreamFilter->GetNumberOfOutputs(); i++) { this->SetInput(i, UpstreamFilter->GetOutput(i)); } } void mitk::IGTLMessageProvider::DisconnectFrom( mitk::IGTLMessageSource* UpstreamFilter ) { for (DataObjectPointerArraySizeType i = 0; i < UpstreamFilter->GetNumberOfOutputs(); i++) { this->RemoveInput(UpstreamFilter->GetOutput(i)); } } ITK_THREAD_RETURN_TYPE mitk::IGTLMessageProvider::TimerThread(void* pInfoStruct) { // extract this pointer from thread info structure struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::IGTLMessageProvider* thisObject = static_cast(pInfo->UserData); itk::SimpleMutexLock mutex; mutex.Lock(); thisObject->m_StopStreamingThreadMutex->Lock(); thisObject->m_StopStreamingThread = false; thisObject->m_StopStreamingThreadMutex->Unlock(); thisObject->m_StreamingTimeMutex->Lock(); unsigned int waitingTime = thisObject->m_StreamingTime; thisObject->m_StreamingTimeMutex->Unlock(); while (true) { thisObject->m_StopStreamingThreadMutex->Lock(); bool stopThread = thisObject->m_StopStreamingThread; thisObject->m_StopStreamingThreadMutex->Unlock(); if (stopThread) { break; } //wait for the time given //I know it is not the nicest solution but we just need an approximate time //sleeps for 20 ms #if defined (WIN32) || defined (_WIN32) Sleep(waitingTime); #else usleep(waitingTime * 1000); #endif // Ask to execute that command from the GUI thread mitk::CallbackFromGUIThread::GetInstance()->CallThisFromGUIThread( thisObject->m_StreamingCommand); } thisObject->m_ThreadId = 0; mutex.Unlock(); return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.h b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h index f84877df73..f60f765467 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageProvider.h +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.h @@ -1,170 +1,178 @@ /*=================================================================== 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. ===================================================================*/ #ifndef IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ #define IGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ #include "mitkIGTLDevice.h" #include "mitkIGTLDeviceSource.h" //itk #include "itkCommand.h" namespace mitk { /** * \brief Provides information/objects from a MITK-Pipeline to other OpenIGTLink * devices * * This class is intended as the drain of the pipeline. Other OpenIGTLink * devices connect with the IGTLDevice hold by this provider. The other device * asks for a certain data type. The provider checks if there are other * IGTLMessageSources available that provide this data type. If yes the provider * connects with this source and sends the message to the requesting device. * * If a STT message was received the provider looks for fitting messageSources. * Once found it connects with it, starts a timing thread (which updates the * pipeline) and sends the result to the requesting device. * * If a GET message was received the provider just calls an update of the * found source and sends the result without connecting to the source. * * If a STP message was received it stops the thread and disconnects from the * previous source. * * So far the provider can just connect with one source. * * \ingroup OpenIGTLink */ class MITK_OPENIGTLINK_EXPORT IGTLMessageProvider : public IGTLDeviceSource { public: mitkClassMacro(IGTLMessageProvider, IGTLDeviceSource); itkFactorylessNewMacro(Self) itkCloneMacro(Self) typedef itk::SimpleMemberCommand ProviderCommand; /** * \brief sends the msg to the requesting client * * Note: so far it broadcasts the message to all registered clients */ void Send(const IGTLMessage* msg); /** * \brief Starts the streaming of the given message source with the given fps. */ void StartStreamingOfSource(mitk::IGTLMessageSource* src, unsigned int fps); /** * \brief Stops the streaming of the given message source. */ void StopStreamingOfSource(mitk::IGTLMessageSource* src); + /** + * \brief Returns the streaming state. + */ + bool IsStreaming(); + protected: IGTLMessageProvider(); virtual ~IGTLMessageProvider(); /** * \brief filter execute method * * queries the OpenIGTLink device for new messages and updates its output * igtl::MessageBase objects with it. * \warning Will raise a std::out_of_range exception, if tools were added to * the OpenIGTLink device after it was set as input for this filter */ virtual void GenerateData(); /** * \brief Create the necessary outputs for the m_IGTLDevice * * This Method is called internally whenever outputs need to be reset. Old * Outputs are deleted when called. **/ void CreateOutputs(); /** * \brief This method is called when the IGTL device hold by this class * receives a new message **/ virtual void OnIncomingMessage(); /** * \brief This method is called when the IGTL device hold by this class * receives a new command **/ virtual void OnIncomingCommand(); /** *\brief Connects the input of this filter to the outputs of the given * IGTLMessageSource * * This method does not support smartpointer. use FilterX.GetPointer() to * retrieve a dumbpointer. */ void ConnectTo( mitk::IGTLMessageSource* UpstreamFilter ); /** *\brief Disconnects this filter from the outputs of the given * IGTLMessageSource * * This method does not support smartpointer. use FilterX.GetPointer() to * retrieve a dumbpointer. */ void DisconnectFrom( mitk::IGTLMessageSource* UpstreamFilter ); /** * \brief Looks for microservices that provide messages with the requested * type. **/ mitk::IGTLMessageSource::Pointer GetFittingSource(const char* requestedType); private: /** * \brief a command that has to be executed in the main thread */ ProviderCommand::Pointer m_StreamingCommand; /** * \brief Timer thread for generating a continuous time signal for the stream * * Everyt time the time is passed a time signal is invoked. * * \param pInfoStruct pointer to the mitkIGTLMessageProvider object * \return */ static ITK_THREAD_RETURN_TYPE TimerThread(void* pInfoStruct); int m_ThreadId; /** \brief timer thread will terminate after the next wakeup if set to true */ bool m_StopStreamingThread; itk::SmartPointer m_MultiThreader; /** \brief the time used for streaming */ - unsigned int m_StreamingTime; + unsigned int m_StreamingTime; /** \brief mutex for guarding m_Time */ itk::SmartPointer m_StreamingTimeMutex; /** \brief mutex for guarding m_StopStreamingThread */ itk::SmartPointer m_StopStreamingThreadMutex; + /** \brief flag to indicate if the provider is streaming */ + bool m_IsStreaming; + }; } // namespace mitk #endif /* MITKIGTLMESSAGEPROVIDER_H_HEADER_INCLUDED_ */ diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp index 964c8abb75..c747e27cb0 100644 --- a/Modules/OpenIGTLink/mitkIGTLServer.cpp +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -1,191 +1,194 @@ /*=================================================================== 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 mitk::IGTLServer::IGTLServer() : IGTLDevice() { } mitk::IGTLServer::~IGTLServer() { } 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 SocketListType allRegisteredSockets = m_RegisteredClients; 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 this->m_RegisteredClients.push_back(socket); //inform observers about this new client this->InvokeEvent(NewClientConnectionEvent()); MITK_INFO("IGTLServer") << "Connected to a new client."; } } 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; SocketListIteratorType 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 iterator over the list at this point socketsToBeRemoved.push_back(*it); MITK_WARN("IGTLServer") << "Lost connection to a client socket. "; } } - //remove the sockets that are not connected anymore - this->StopCommunicationWithSocket(socketsToBeRemoved); - //inform observers about loosing the connection to these sockets - this->InvokeEvent(LostConnectionEvent()); + 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_SendQueue->PullMessage(); // 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) SocketListIteratorType it; SocketListIteratorType 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); } } void mitk::IGTLServer::StopCommunicationWithSocket( SocketListType& toBeRemovedSockets) { SocketListIteratorType it = toBeRemovedSockets.begin(); SocketListIteratorType itEnd = toBeRemovedSockets.end(); for (; it != itEnd; ++it ) { this->StopCommunicationWithSocket(*it); } } void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) { SocketListIteratorType it = this->m_RegisteredClients.begin(); SocketListIteratorType itEnd = this->m_RegisteredClients.end(); for (; it != itEnd; ++it ) { if ( (*it) == client ) { //close the socket (*it)->CloseSocket(); //and remove it from the list this->m_RegisteredClients.remove(*it); break; } } MITK_INFO("IGTLServer") << "Removed client socket from server client list."; } unsigned int mitk::IGTLServer::GetNumberOfConnections() { return this->m_RegisteredClients.size(); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp index 1e82b1cbff..234992bc88 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLMessageSourceSelectionWidget.cpp @@ -1,86 +1,87 @@ /*=================================================================== 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 "QmitkIGTLMessageSourceSelectionWidget.h" //mitk headers #include #include QmitkIGTLMessageSourceSelectionWidget::QmitkIGTLMessageSourceSelectionWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; + m_CurrentIGTLMessageSource = NULL; CreateQtPartControl(this); } QmitkIGTLMessageSourceSelectionWidget::~QmitkIGTLMessageSourceSelectionWidget() { } void QmitkIGTLMessageSourceSelectionWidget::CreateQtPartControl(QWidget *parent) { if ( !m_Controls ) { // create GUI widgets m_Controls = new Ui::QmitkIGTLMessageSourceSelectionWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } CreateConnections(); } void QmitkIGTLMessageSourceSelectionWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_ServiceListWidget, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(IGTLMessageSourceSelected(us::ServiceReferenceU)) ); //initialize service list widget std::string empty = ""; m_Controls->m_ServiceListWidget->Initialize( mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME, empty); } } void QmitkIGTLMessageSourceSelectionWidget::IGTLMessageSourceSelected(us::ServiceReferenceU s) { if (!s) //nothing selected { //reset everything this->m_CurrentIGTLMessageSource = NULL; emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); return; } // Get storage us::ModuleContext* context = us::GetModuleContext(); this->m_CurrentIGTLMessageSource = context->GetService(s); emit IGTLMessageSourceSelected(this->m_CurrentIGTLMessageSource); } mitk::IGTLMessageSource::Pointer QmitkIGTLMessageSourceSelectionWidget::GetSelectedIGTLMessageSource() - { +{ return this->m_CurrentIGTLMessageSource; - } +} diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp index 6f72d922ea..f4608eb86f 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp @@ -1,340 +1,307 @@ /*=================================================================== 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 "QmitkIGTLStreamingManagementWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLStreamingManagementWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLStreamingManagementWidget::QmitkIGTLStreamingManagementWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLStreamingManagementWidget::~QmitkIGTLStreamingManagementWidget() { } void QmitkIGTLStreamingManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLStreamingManagementWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLStreamingManagementWidget::CreateConnections() { if (m_Controls) { connect( (QObject*)(m_Controls->messageSourceSelectionWidget), SIGNAL(IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer)), this, SLOT(SourceSelected(mitk::IGTLMessageSource::Pointer)) ); connect( m_Controls->startStreamPushButton, SIGNAL(clicked()), this, SLOT(OnStartStreaming())); + connect( m_Controls->stopStreamPushButton, SIGNAL(clicked()), + this, SLOT(OnStopStreaming())); } } -void QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged() -{ - this->AdaptGUIToState(); -} - void QmitkIGTLStreamingManagementWidget::AdaptGUIToState() { if (this->m_IGTLMsgProvider.IsNotNull()) { //get the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: case mitk::IGTLDevice::Ready: m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Running: - //check if the user already selected a source to stream - if ( this->m_IGTLMsgSource.IsNull() ) // he did not so far + //check the number of connections of the device, a server can be in + //the running state even if there is no connected device, this part of + //the GUI shall just be available when there is a connection + if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) { - m_Controls->messageSourceSelectionWidget->setEnabled(true); + m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } - else //user already selected a source + else //there is a connection { - QString nameOfSource = - QString::fromStdString(m_IGTLMsgSource->GetName()); - m_Controls->messageSourceSelectionWidget->setEnabled(true); - m_Controls->selectedSourceLabel->setText(nameOfSource); - m_Controls->startStreamPushButton->setEnabled(true); - m_Controls->selectedSourceLabel->setEnabled(true); - m_Controls->label->setEnabled(true); - m_Controls->stopStreamPushButton->setEnabled(false); - m_Controls->fpsLabel->setEnabled(true); - m_Controls->fpsSpinBox->setEnabled(true); - //check here if the current source is already streaming if yes adapt - //the send and stop button + //check if the user already selected a source to stream + if ( this->m_IGTLMsgSource.IsNull() ) // he did not so far + { + m_Controls->messageSourceSelectionWidget->setEnabled(true); + m_Controls->selectedSourceLabel->setText(""); + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->selectedSourceLabel->setEnabled(false); + m_Controls->label->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + } + else //user already selected a source + { + QString nameOfSource = + QString::fromStdString(m_IGTLMsgSource->GetName()); + m_Controls->messageSourceSelectionWidget->setEnabled(true); + m_Controls->selectedSourceLabel->setText(nameOfSource); + m_Controls->selectedSourceLabel->setEnabled(true); + m_Controls->label->setEnabled(true); + + //check if the streaming is already running + if (this->m_IGTLMsgProvider->IsStreaming()) + { + m_Controls->startStreamPushButton->setEnabled(false); + m_Controls->stopStreamPushButton->setEnabled(true); + m_Controls->fpsLabel->setEnabled(false); + m_Controls->fpsSpinBox->setEnabled(false); + } + else + { + m_Controls->startStreamPushButton->setEnabled(true); + m_Controls->stopStreamPushButton->setEnabled(false); + m_Controls->fpsLabel->setEnabled(true); + m_Controls->fpsSpinBox->setEnabled(true); + } + } } break; default: mitkThrow() << "Invalid Device State"; break; } } else { this->DisableSourceControls(); } } void QmitkIGTLStreamingManagementWidget::LoadSource( mitk::IGTLMessageProvider::Pointer provider) { //reset the GUI DisableSourceControls(); if ( provider.IsNull() ) return; -// //reset the observers -// if ( this->m_IGTLDevice.IsNotNull() ) -// { + //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); -// } + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } this->m_IGTLMsgProvider = provider; //get the device this->m_IGTLDevice = this->m_IGTLMsgProvider->GetIGTLDevice(); //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< QmitkIGTLStreamingManagementWidget > CurCommandType; + typedef itk::SimpleMemberCommand< QmitkIGTLStreamingManagementWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnMessageReceived ); // this->m_MessageReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); // commandReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnCommandReceived ); // this->m_CommandReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); -// CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); -// connectionLostCommand->SetCallbackFunction( -// this, &QmitkIGTLStreamingManagementWidget::OnLostConnection ); -// this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( -// mitk::LostConnectionEvent(), connectionLostCommand); + CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); + connectionLostCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnLostConnection ); + this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::LostConnectionEvent(), connectionLostCommand); -// CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); -// newConnectionCommand->SetCallbackFunction( -// this, &QmitkIGTLStreamingManagementWidget::OnNewConnection ); -// this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( -// mitk::NewClientConnectionEvent(), newConnectionCommand); + CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); + newConnectionCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnNewConnection ); + this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( + mitk::NewClientConnectionEvent(), newConnectionCommand); -// CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); -// stateModifiedCommand->SetCallbackFunction( -// this, &QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged ); -// this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( -// itk::ModifiedEvent(), stateModifiedCommand); + CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); + stateModifiedCommand->SetCallbackFunction( + this, &QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged ); + this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( + itk::ModifiedEvent(), stateModifiedCommand); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::DisableSourceControls() { m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->messageSourceSelectionWidget->setEnabled(false); } void QmitkIGTLStreamingManagementWidget::SourceSelected( mitk::IGTLMessageSource::Pointer source) { //reset everything this->DisableSourceControls(); if (source.IsNotNull()) //no source selected { this->m_IGTLMsgSource = source; } this->AdaptGUIToState(); } - void QmitkIGTLStreamingManagementWidget::OnStartStreaming() { unsigned int fps = this->m_Controls->fpsSpinBox->value(); this->m_IGTLMsgProvider->StartStreamingOfSource(this->m_IGTLMsgSource, fps); + this->AdaptGUIToState(); +} + +void QmitkIGTLStreamingManagementWidget::OnStopStreaming() +{ + this->m_IGTLMsgProvider->StopStreamingOfSource(this->m_IGTLMsgSource); + this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnMessageReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) -// { -// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a message: " -// << dev->GetReceiveQueue()->GetLatestMsgInformationString(); -// } } void QmitkIGTLStreamingManagementWidget::OnCommandReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) -// { -// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a command: " -// << dev->GetCommandQueue()->GetLatestMsgInformationString(); -// } +} + +void QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged() +{ + this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnLostConnection() { this->AdaptGUIToState(); -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections == 0 ) -// { -// if ( this->m_IsClient ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(true); -// m_Controls->editPort->setEnabled(true); -// m_Controls->butConnect->setText("Connect"); -// m_Controls->logSendReceiveMsg->setEnabled(false); -// m_Controls->bufferMsgCheckBox->setEnabled(false); -// //send string messages groupbox -// m_Controls->editSend->setEnabled(false); -// m_Controls->butSend->setEnabled(false); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(false); -// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(false); -// } -// else -// { -// //send string messages groupbox -// m_Controls->editSend->setEnabled(false); -// m_Controls->butSend->setEnabled(false); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(false); -// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(false); -// } -// } } void QmitkIGTLStreamingManagementWidget::OnNewConnection() { - this->AdaptGUIToState(); -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections != 0 ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(false); -// m_Controls->editPort->setEnabled(false); -// m_Controls->butConnect->setText("Disconnect"); -// m_Controls->logSendReceiveMsg->setEnabled(true); -// m_Controls->bufferMsgCheckBox->setEnabled(true); -// //send string messages groupbox -// m_Controls->editSend->setEnabled(true); -// m_Controls->butSend->setEnabled(true); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(true); -//// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(true); -// } + //get the current selection and call SourceSelected which will call AdaptGUI + mitk::IGTLMessageSource::Pointer curSelSrc = + m_Controls->messageSourceSelectionWidget->GetSelectedIGTLMessageSource(); + SourceSelected(curSelSrc); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h index 011991d802..b89d5af0bb 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h @@ -1,134 +1,135 @@ /*=================================================================== 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. ===================================================================*/ #ifndef QMITKIGTLStreamingMANAGEMENTWIDGET_H #define QMITKIGTLStreamingMANAGEMENTWIDGET_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLMessageProvider.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLStreamingManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage the streaming of * message sources. * * * \ingroup OpenIGTLinkUI */ class MITK_OPENIGTLINKUI_EXPORT QmitkIGTLStreamingManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Loads a provider to the widget. The old source is dropped, so be careful, * if the source is not saved somewhere else it might be lost. You might * want to ask the user if he wants to save the changes before calling this * method. * @param provider This provider will be loaded and might be modified * by the user. */ void LoadSource(mitk::IGTLMessageProvider::Pointer provider); - /** \brief Is called when a new source is selected. - * @param source the newly selected source - */ - void SourceSelected(mitk::IGTLMessageSource::Pointer source); - QmitkIGTLStreamingManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLStreamingManagementWidget(); /** * \brief Is called when the current device received a message */ void OnMessageReceived(); /** * \brief Is called when the current device received a command */ void OnCommandReceived(); /** * \brief Is called when the current device lost a connection to one of its * sockets */ void OnLostConnection(); /** * \brief Is called when the current device connected to another device */ void OnNewConnection(); protected slots: void OnStartStreaming(); + void OnStopStreaming(); + + /** \brief Is called when a new source is selected. + * @param source the newly selected source + */ + void SourceSelected(mitk::IGTLMessageSource::Pointer source); protected: /** * \brief Adapts the GUI to the state of the device */ void AdaptGUIToState(); /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /// \brief Fills the commands combo box with available commands void FillCommandsComboBox(); /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLStreamingManagementWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; /** @brief holds the IGTL Message Provider that will send the stream */ mitk::IGTLMessageProvider::Pointer m_IGTLMsgProvider; /** @brief holds the IGTLDeviceSource we are working with. */ mitk::IGTLMessageSource::Pointer m_IGTLMsgSource; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; //############## private help methods ####################### void DisableSourceControls(); }; #endif diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp index f5d50cfa83..72397c9036 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManager.cpp @@ -1,84 +1,84 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // #include "OpenIGTLinkManager.h" const std::string OpenIGTLinkManager::VIEW_ID = "org.mitk.views.openigtlinkmanager"; OpenIGTLinkManager::OpenIGTLinkManager() : QmitkAbstractView() { } OpenIGTLinkManager::~OpenIGTLinkManager() { for(unsigned int i=0; i < m_AllSourcesHandledByThisWidget.size(); i++) m_AllSourcesHandledByThisWidget.at(i)->UnRegisterMicroservice(); } void OpenIGTLinkManager::SetFocus() { } void OpenIGTLinkManager::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // create GUI widgets from the Qt Designer's .ui file - connect( (QObject*)(m_Controls.m_SourceManagerWidget), - SIGNAL(NewSourceAdded(mitk::IGTLDeviceSource::Pointer, std::string)), - this, - SLOT(NewSourceByWidget(mitk::IGTLDeviceSource::Pointer,std::string)) ); +// connect( (QObject*)(m_Controls.m_SourceManagerWidget), +// SIGNAL(NewSourceAdded(mitk::IGTLDeviceSource::Pointer, std::string)), +// this, +// SLOT(NewSourceByWidget(mitk::IGTLDeviceSource::Pointer,std::string)) ); connect( (QObject*)(m_Controls.m_SourceListWidget), SIGNAL(IGTLDeviceSourceSelected(mitk::IGTLDeviceSource::Pointer)), this, SLOT(SourceSelected(mitk::IGTLDeviceSource::Pointer)) ); } void OpenIGTLinkManager::NewSourceByWidget( mitk::IGTLDeviceSource::Pointer source,std::string /*sourceName*/) { source->RegisterAsMicroservice(/*sourceName*/); m_AllSourcesHandledByThisWidget.push_back(source); } void OpenIGTLinkManager::SourceSelected( mitk::IGTLDeviceSource::Pointer source) { if (source.IsNull()) //no source selected { //reset everything return; } this->m_Controls.m_SourceManagerWidget->LoadSource(source); //check if the current selected source is also a message provider mitk::IGTLMessageProvider::Pointer msgProvider = mitk::IGTLMessageProvider::New(); msgProvider = dynamic_cast(source.GetPointer()); this->m_Controls.m_StreamManagerWidget->LoadSource(msgProvider); } diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui index 0e8b516334..fc8aeba7ed 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkManagerControls.ui @@ -1,98 +1,98 @@ OpenIGTLinkManagerControls 0 0 668 392 0 0 QmitkTemplate 12 75 true Select OpenIGTLink Device Source: 12 75 true Manage Device: 12 75 true - Mange Streams: + Manage Streams: QmitkIGTLDeviceSourceSelectionWidget QTextEdit
QmitkIGTLDeviceSourceSelectionWidget.h
QmitkIGTLDeviceSourceManagementWidget QWidget
QmitkIGTLDeviceSourceManagementWidget.h
1
QmitkIGTLStreamingManagementWidget QWidget
QmitkIGTLStreamingManagementWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp index 766773c6f1..851cf2096d 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp @@ -1,235 +1,238 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include #include // mitk #include #include #include #include #include #include // vtk #include // #include "OpenIGTLinkProviderExample.h" //igtl #include "igtlStringMessage.h" const std::string OpenIGTLinkProviderExample::VIEW_ID = "org.mitk.views.OpenIGTLinkProviderExample"; OpenIGTLinkProviderExample::~OpenIGTLinkProviderExample() { this->GetDataStorage()->Remove(m_DemoNodeT1); this->GetDataStorage()->Remove(m_DemoNodeT2); this->GetDataStorage()->Remove(m_DemoNodeT3); } void OpenIGTLinkProviderExample::SetFocus() { } void OpenIGTLinkProviderExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( m_Controls.butOpenNavData, SIGNAL(clicked()), this, SLOT(OnOpenFile()) ); connect( &m_VisualizerTimer, SIGNAL(timeout()), this, SLOT(UpdateVisualization())); } void OpenIGTLinkProviderExample::CreatePipeline() { //create a new OpenIGTLink Client m_IGTLServer = mitk::IGTLServer::New(); m_IGTLServer->SetName("OIGTL Provider Example Device"); //create a new OpenIGTLink Device source m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); //set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); //register the provider so that it can be configured with the IGTL manager //plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); //create a filter that converts navigation data into IGTL messages m_NavDataToIGTLMsgFilter = mitk::NavigationDataToIGTLMessageFilter::New(); //define the operation mode for this filter, we want to send tracking data //messages m_NavDataToIGTLMsgFilter->SetOperationMode( mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); + //set the name of this filter to identify it easier + m_NavDataToIGTLMsgFilter->SetName("Tracking Data Source From Example"); + //register this filter as micro service. The message provider looks for //provided IGTLMessageSources, once it found this microservice and someone //requested this data type then the provider will connect with this filter //automatically (this is not implemented so far, check m_StreamingConnector //for more information) m_NavDataToIGTLMsgFilter->RegisterAsMicroservice(); //create a navigation data player object that will play nav data from a //recorded file m_NavDataPlayer = mitk::NavigationDataPlayer::New(); //set the currently read navigation data set m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); //connect the filters with each other //the navigation data player reads a file with recorded navigation data, //passes this data to a filter that converts it into a IGTLMessage. //The provider is not connected because it will search for fitting services. //Once it found the filter it will automatically connect to it (this is not // implemented so far, check m_StreamingConnector for more information). m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); //create an object that will be moved respectively to the navigation data m_DemoNodeT1 = mitk::DataNode::New(); m_DemoNodeT1->SetName("DemoNode IGTLProviderExmpl T1"); m_DemoNodeT2 = mitk::DataNode::New(); m_DemoNodeT2->SetName("DemoNode IGTLProviderExmpl T2"); m_DemoNodeT3 = mitk::DataNode::New(); m_DemoNodeT3->SetName("DemoNode IGTLProviderExmpl T3"); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(2.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); m_DemoNodeT1->SetData(mySphere); mitk::Surface::Pointer mySphere2 = mySphere->Clone(); m_DemoNodeT2->SetData(mySphere2); mitk::Surface::Pointer mySphere3 = mySphere->Clone(); m_DemoNodeT3->SetData(mySphere3); // add node to DataStorage this->GetDataStorage()->Add(m_DemoNodeT1); this->GetDataStorage()->Add(m_DemoNodeT2); this->GetDataStorage()->Add(m_DemoNodeT3); //initialize the streaming connector //the streaming connector is checking if the data from the filter has to be //streamed. The message provider is used for sending the messages. // m_StreamingConnector.Initialize(m_NavDataToIGTLMsgFilter.GetPointer(), // m_IGTLMessageProvider); //also create a visualize filter to visualize the data m_NavDataVisualizer = mitk::NavigationDataObjectVisualizationFilter::New(); m_NavDataVisualizer->SetRepresentationObject(0, mySphere); m_NavDataVisualizer->SetRepresentationObject(1, mySphere2); m_NavDataVisualizer->SetRepresentationObject(2, mySphere3); m_NavDataVisualizer->ConnectTo(m_NavDataPlayer); //start the player this->Start(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); } void OpenIGTLinkProviderExample::DestroyPipeline() { m_NavDataPlayer->StopPlaying(); this->GetDataStorage()->Remove(m_DemoNodeT1); } void OpenIGTLinkProviderExample::Start() { if ( this->m_Controls.butStart->text().contains("Start") ) { m_NavDataPlayer->SetRepeat(true); m_NavDataPlayer->StartPlaying(); this->m_Controls.butStart->setText("Stop Playing Recorded Navigation Data "); //start the visualization this->m_VisualizerTimer.start(100); } else { m_NavDataPlayer->StopPlaying(); this->m_Controls.butStart->setText("Start Playing Recorded Navigation Data "); //stop the visualization this->m_VisualizerTimer.stop(); } } void OpenIGTLinkProviderExample::OnOpenFile(){ mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); // FIXME Filter for correct files and use correct Reader QString fileName = QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", "XML files (*.xml)"); if ( fileName.isNull() ) { return; } // user pressed cancel try { m_NavDataSet = reader->Read(fileName.toStdString()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } this->m_Controls.butStart->setEnabled(true); //Setup the pipeline this->CreatePipeline(); // Update Labels // m_Controls->m_LblFilePath->setText(fileName); // m_Controls->m_LblTools->setText(QString::number(m_NavDataSet->GetNumberOfTools())); } void OpenIGTLinkProviderExample::UpdateVisualization() { //update the filter this->m_NavDataVisualizer->Update(); //update the bounds mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); }