diff options
-rw-r--r-- | sd/Library_sd.mk | 1 | ||||
-rw-r--r-- | sd/source/ui/dlg/RemoteDialog.cxx | 6 | ||||
-rw-r--r-- | sd/source/ui/inc/RemoteServer.hxx | 42 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Communicator.cxx | 128 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Communicator.hxx | 62 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Listener.cxx | 13 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Listener.hxx | 6 | ||||
-rw-r--r-- | sd/source/ui/remotecontrol/Server.cxx | 173 |
8 files changed, 304 insertions, 127 deletions
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index 1fb99e02ca51..92db929a067a 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -327,6 +327,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\ sd/source/ui/presenter/PresenterPreviewCache \ sd/source/ui/presenter/PresenterTextView \ sd/source/ui/presenter/SlideRenderer \ + sd/source/ui/remotecontrol/Communicator \ sd/source/ui/remotecontrol/DiscoveryService \ sd/source/ui/remotecontrol/ImagePreparer \ sd/source/ui/remotecontrol/Server \ diff --git a/sd/source/ui/dlg/RemoteDialog.cxx b/sd/source/ui/dlg/RemoteDialog.cxx index 85d5ad2c91e5..465febc5fba9 100644 --- a/sd/source/ui/dlg/RemoteDialog.cxx +++ b/sd/source/ui/dlg/RemoteDialog.cxx @@ -26,12 +26,12 @@ RemoteDialog::RemoteDialog( Window *pWindow ) : { FreeResource(); - vector<ClientInfo> aClients( RemoteServer::getClients() ); + vector<ClientInfo*> aClients( RemoteServer::getClients() ); - for ( vector<ClientInfo>::const_iterator aIt( aClients.begin() ); + for ( vector<ClientInfo*>::const_iterator aIt( aClients.begin() ); aIt < aClients.end(); aIt++ ) { - mClientBox.addEntry( *aIt ); + mClientBox.addEntry( **aIt ); } mButtonConnect.SetClickHdl( LINK( this, RemoteDialog, HandleConnectButton ) ); diff --git a/sd/source/ui/inc/RemoteServer.hxx b/sd/source/ui/inc/RemoteServer.hxx index d3e202ba7fae..a77f5aba873c 100644 --- a/sd/source/ui/inc/RemoteServer.hxx +++ b/sd/source/ui/inc/RemoteServer.hxx @@ -16,6 +16,7 @@ #include <sys/types.h> #include <vector> +#include <osl/mutex.hxx> #include <osl/socket.hxx> #include <rtl/ref.hxx> #include <salhelper/thread.hxx> @@ -36,10 +37,7 @@ namespace css = ::com::sun::star; namespace sd { - - class Transmitter; - class Listener; - class ImagePreparer; + class Communicator; struct ClientInfo { @@ -47,33 +45,53 @@ namespace sd rtl::OUString mAddress; enum PROTOCOL { NETWORK = 1, BLUETOOTH }; - ClientInfo( OUString rName, OUString rAddress) : + ClientInfo( const rtl::OUString rName, const rtl::OUString rAddress ) : mName( rName ), mAddress( rAddress ) {} }; + struct ClientInfoInternal: + ClientInfo + { + osl::StreamSocket mStreamSocket; + rtl::OUString mPin; + + ClientInfoInternal( const rtl::OUString rName, + const rtl::OUString rAddress, + osl::StreamSocket &rSocket, rtl::OUString rPin ): + ClientInfo( rName, rAddress ), + mStreamSocket( rSocket ), + mPin( rPin ) {} + }; + class RemoteServer : public salhelper::Thread { public: + // Internal setup static void setup(); + + // For slideshowimpl to inform us. static void presentationStarted( const css::uno::Reference< css::presentation::XSlideShowController > &rController ); static void presentationStopped(); - void informListenerDestroyed(); - SD_DLLPUBLIC static std::vector<ClientInfo> getClients(); + // For the control dialog + SD_DLLPUBLIC static std::vector<ClientInfo*> getClients(); SD_DLLPUBLIC static void connectClient( ClientInfo aClient, rtl::OString aPin ); + + // For the communicator + static void removeCommunicator( Communicator* pCommunicator ); private: RemoteServer(); ~RemoteServer(); static RemoteServer *spServer; osl::AcceptorSocket mSocket; - osl::StreamSocket mStreamSocket; - void pairClient(); - void listenThread(); + + ::osl::Mutex mDataMutex; + ::std::vector<Communicator*> mCommunicators; + ::std::vector<ClientInfoInternal*> mAvailableClients; + void execute(); - static Transmitter *pTransmitter; - static rtl::Reference<Listener> mListener; }; } diff --git a/sd/source/ui/remotecontrol/Communicator.cxx b/sd/source/ui/remotecontrol/Communicator.cxx new file mode 100644 index 000000000000..d4775f9264bf --- /dev/null +++ b/sd/source/ui/remotecontrol/Communicator.cxx @@ -0,0 +1,128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#include <algorithm> +#include <vector> + +#include <comphelper/processfactory.hxx> + +#include "Communicator.hxx" +#include "ImagePreparer.hxx" +#include "Listener.hxx" +#include "Receiver.hxx" +#include "RemoteServer.hxx" + +using namespace sd; +using namespace std; +using namespace com::sun::star; +using namespace osl; + +Communicator::Communicator( StreamSocket &aSocket ): + Thread( "CommunicatorThread" ), + mSocket( aSocket ), + pTransmitter( 0 ), + mListener( 0 ) +{ +} + +Communicator::~Communicator() +{ +} + +// Run as a thread +void Communicator::execute() +{ + pTransmitter = new Transmitter( mSocket ); + pTransmitter->launch(); + Receiver aReceiver( pTransmitter ); + try { + uno::Reference< lang::XMultiServiceFactory > xServiceManager( + ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); + uno::Reference< frame::XFramesSupplier > xFramesSupplier( xServiceManager->createInstance( + "com.sun.star.frame.Desktop" ) , uno::UNO_QUERY_THROW ); + uno::Reference< frame::XFrame > xFrame ( xFramesSupplier->getActiveFrame(), uno::UNO_QUERY_THROW ); + uno::Reference<presentation::XPresentationSupplier> xPS ( xFrame->getController()->getModel(), uno::UNO_QUERY_THROW); + uno::Reference<presentation::XPresentation2> xPresentation( + xPS->getPresentation(), uno::UNO_QUERY_THROW); + if ( xPresentation->isRunning() ) + { + presentationStarted( xPresentation->getController() ); + } + } + catch (uno::RuntimeException &) + { + } + + sal_uInt64 aRet, aRead; + vector<char> aBuffer; + vector<OString> aCommand; + aRead = 0; + while ( true ) + { + aBuffer.resize( aRead + 100 ); + aRet = mSocket.recv( &aBuffer[aRead], 100 ); + if ( aRet == 0 ) + { + break; // I.e. transmission finished. + } + aRead += aRet; + vector<char>::iterator aIt; + while ( (aIt = find( aBuffer.begin(), aBuffer.end(), '\n' )) + != aBuffer.end() ) + { + sal_uInt64 aLocation = aIt - aBuffer.begin(); + + aCommand.push_back( OString( &(*aBuffer.begin()), aLocation ) ); + if ( aIt == aBuffer.begin() ) + { + aReceiver.parseCommand( aCommand ); + aCommand.clear(); + } + aBuffer.erase( aBuffer.begin(), aIt + 1 ); // Also delete the empty line + aRead -= (aLocation + 1); + } + } + // TODO: deal with transmision errors gracefully. + disposeListener(); + + pTransmitter->notifyFinished(); + pTransmitter->join(); + pTransmitter = NULL; + + RemoteServer::removeCommunicator( this ); +} + +void Communicator::informListenerDestroyed() +{ + mListener.clear(); +} + +void Communicator::presentationStarted( const css::uno::Reference< + css::presentation::XSlideShowController > &rController ) +{ + if ( pTransmitter ) + { + mListener = rtl::Reference<Listener>( new Listener( this, pTransmitter ) ); + mListener->init( rController ); + } +} + +void Communicator::disposeListener() +{ + if ( mListener.is() ) + { + mListener->disposing(); + mListener = NULL; + } +} + +Transmitter* Communicator::getTransmitter() +{ + return pTransmitter; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/Communicator.hxx b/sd/source/ui/remotecontrol/Communicator.hxx new file mode 100644 index 000000000000..089fffa7b3dd --- /dev/null +++ b/sd/source/ui/remotecontrol/Communicator.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#ifndef _SD_IMPRESSREMOTE_COMMUNICATOR_HXX +#define _SD_IMPRESSREMOTE_COMMUNICATOR_HXX + +// SERVER +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <vector> + +#include <osl/socket.hxx> +#include <rtl/ref.hxx> +#include <salhelper/thread.hxx> + +#include <com/sun/star/presentation/XSlideShowController.hpp> + +#define CHARSET RTL_TEXTENCODING_UTF8 +namespace css = ::com::sun::star; + +namespace sd +{ + + class Transmitter; + class Listener; + class ImagePreparer; + + /** Class used for communication with one single client, dealing with all + * tasks specific to this client. + * + * Needs to be created, then started using launch(), disposes itself. + */ + class Communicator : public salhelper::Thread + { + public: + Communicator( osl::StreamSocket &aSocket ); + ~Communicator(); + + Transmitter* getTransmitter(); + void presentationStarted( const css::uno::Reference< + css::presentation::XSlideShowController > &rController ); + void informListenerDestroyed(); + void disposeListener(); + + private: + void execute(); + osl::StreamSocket mSocket; + + Transmitter *pTransmitter; + rtl::Reference<Listener> mListener; + }; +} + +#endif // _SD_IMPRESSREMOTE_COMMUNICATOR_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/Listener.cxx b/sd/source/ui/remotecontrol/Listener.cxx index e326ea56c585..5044169606c6 100644 --- a/sd/source/ui/remotecontrol/Listener.cxx +++ b/sd/source/ui/remotecontrol/Listener.cxx @@ -22,9 +22,10 @@ using rtl::OString; using rtl::OStringBuffer; -Listener::Listener( const ::rtl::Reference<RemoteServer>& rServer, sd::Transmitter *aTransmitter ) - : ::cppu::WeakComponentImplHelper1< XSlideShowListener >( m_aMutex ), - mServer( rServer ), +Listener::Listener( const ::rtl::Reference<Communicator>& rCommunicator, + sd::Transmitter *aTransmitter ): + ::cppu::WeakComponentImplHelper1< XSlideShowListener >( m_aMutex ), + mCommunicator( rCommunicator ), pTransmitter( NULL ), mPreparer() { @@ -43,11 +44,11 @@ void Listener::init( const css::uno::Reference< css::presentation::XSlideShowCon aController->addSlideShowListener( this ); sal_Int32 aSlides = aController->getSlideCount(); - sal_Int32 aCurrentSlide = aController->getCurrentSlideIndex(); + sal_Int32 aCurrentSlide = aController->getCurrentSlideIndex(); OStringBuffer aBuffer; aBuffer.append( "slideshow_started\n" ) .append( OString::valueOf( aSlides ) ).append("\n") - .append( OString::valueOf( aCurrentSlide ) ).append( "\n\n" ); + .append( OString::valueOf( aCurrentSlide ) ).append( "\n\n" ); pTransmitter->addMessage( aBuffer.makeStringAndClear(), Transmitter::PRIORITY_HIGH ); @@ -146,7 +147,7 @@ void SAL_CALL Listener::disposing (void) mController->removeSlideShowListener( this ); mController = NULL; } - mServer->informListenerDestroyed(); + mCommunicator->informListenerDestroyed(); } void SAL_CALL Listener::disposing ( diff --git a/sd/source/ui/remotecontrol/Listener.hxx b/sd/source/ui/remotecontrol/Listener.hxx index 1a1226db82f9..3eb7f10ae7d6 100644 --- a/sd/source/ui/remotecontrol/Listener.hxx +++ b/sd/source/ui/remotecontrol/Listener.hxx @@ -19,7 +19,7 @@ #include <osl/socket.hxx> #include <rtl/ref.hxx> -#include "RemoteServer.hxx" +#include "Communicator.hxx" #include "Transmitter.hxx" #include "ImagePreparer.hxx" @@ -35,7 +35,7 @@ class Listener public ::cppu::WeakComponentImplHelper1< css::presentation::XSlideShowListener > { public: - Listener( const ::rtl::Reference<RemoteServer>& rServer, sd::Transmitter *aTransmitter ); + Listener( const ::rtl::Reference<Communicator>& rServer, sd::Transmitter *aTransmitter ); ~Listener(); void init( const css::uno::Reference< css::presentation::XSlideShowController >& aController ); @@ -65,7 +65,7 @@ public: throw (com::sun::star::uno::RuntimeException); private: - rtl::Reference<RemoteServer> mServer; + rtl::Reference<Communicator> mCommunicator; sd::Transmitter *pTransmitter; css::uno::Reference< css::presentation::XSlideShowController > mController; rtl::Reference<sd::ImagePreparer> mPreparer; diff --git a/sd/source/ui/remotecontrol/Server.cxx b/sd/source/ui/remotecontrol/Server.cxx index 61284ffd6c8a..eb4adc13dc9f 100644 --- a/sd/source/ui/remotecontrol/Server.cxx +++ b/sd/source/ui/remotecontrol/Server.cxx @@ -25,9 +25,27 @@ using namespace std; using namespace sd; using namespace ::com::sun::star; using rtl::OString; - -RemoteServer::RemoteServer() -: Thread( "RemoteServerThread" ), mSocket() +using namespace ::osl; + +// struct ClientInfoInternal: +// ClientInfo +// { +// osl::StreamSocket mStreamSocket; +// rtl::OUString mPin; +// ClientInfoInternal( const rtl::OUString rName, +// const rtl::OUString rAddress, +// osl::StreamSocket &rSocket, rtl::OUString rPin ): +// ClientInfo( rName, rAddress ), +// mStreamSocket( rSocket ), +// mPin( rPin ) {} +// }; + +RemoteServer::RemoteServer() : + Thread( "RemoteServerThread" ), + mSocket(), + mDataMutex(), + mCommunicators(), + mAvailableClients() { } @@ -35,75 +53,6 @@ RemoteServer::~RemoteServer() { } -// Run as a thread -void RemoteServer::listenThread() -{ - pTransmitter = new Transmitter( mStreamSocket ); - pTransmitter->launch(); - Receiver aReceiver( pTransmitter ); - try { - uno::Reference< lang::XMultiServiceFactory > xServiceManager( - ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW ); - uno::Reference< frame::XFramesSupplier > xFramesSupplier( xServiceManager->createInstance( - "com.sun.star.frame.Desktop" ) , uno::UNO_QUERY_THROW ); - uno::Reference< frame::XFrame > xFrame ( xFramesSupplier->getActiveFrame(), uno::UNO_QUERY_THROW ); - uno::Reference<presentation::XPresentationSupplier> xPS ( xFrame->getController()->getModel(), uno::UNO_QUERY_THROW); - uno::Reference<presentation::XPresentation2> xPresentation( - xPS->getPresentation(), uno::UNO_QUERY_THROW); - if ( xPresentation->isRunning() ) - { - presentationStarted( xPresentation->getController() ); - } - } - catch (uno::RuntimeException &) - { - } - - sal_uInt64 aRet, aRead; - vector<char> aBuffer; - vector<OString> aCommand; - aRead = 0; - while ( true ) - { - aBuffer.resize( aRead + 100 ); - aRet = mStreamSocket.recv( &aBuffer[aRead], 100 ); - if ( aRet == 0 ) - { - break; // I.e. transmission finished. - } - aRead += aRet; - vector<char>::iterator aIt; - while ( (aIt = find( aBuffer.begin(), aBuffer.end(), '\n' )) - != aBuffer.end() ) - { - sal_uInt64 aLocation = aIt - aBuffer.begin(); - - aCommand.push_back( OString( &(*aBuffer.begin()), aLocation ) ); - if ( aIt == aBuffer.begin() ) - { - aReceiver.parseCommand( aCommand ); - aCommand.clear(); - } - aBuffer.erase( aBuffer.begin(), aIt + 1 ); // Also delete the empty line - aRead -= (aLocation + 1); - } - } - // TODO: deal with transmision errors gracefully. - presentationStopped(); - - pTransmitter->notifyFinished(); - pTransmitter->join(); - pTransmitter = NULL; - fprintf( stderr, "Finished listening\n" ); -} - -void RemoteServer::pairClient() -{ - // Pairing: client sends PIN, server asks user, replies with accepted/rejected. - // We have to wait here until the user opens the dialog via the menu, - // typs in the pin etc. -} - void RemoteServer::execute() { osl::SocketAddr aAddr( "0", PORT ); @@ -118,60 +67,78 @@ void RemoteServer::execute() } while ( true ) { - fprintf( stderr, "Awaiting a connection.\n" ); - if ( mSocket.acceptConnection( mStreamSocket ) == osl_Socket_Error ) { - // Socket closed or other problem - return; + StreamSocket aSocket; + if ( mSocket.acceptConnection( aSocket ) == osl_Socket_Error ) { + MutexGuard aGuard( mDataMutex ); + // FIXME: read one line in, parse the data. + mAvailableClients.push_back( new ClientInfoInternal( "A name", + "An address", aSocket, "0000" ) ); } - fprintf( stderr, "Accepted a connection!\n" ); - listenThread(); } } -void RemoteServer::informListenerDestroyed() +RemoteServer *sd::RemoteServer::spServer = NULL; + +void RemoteServer::setup() { - mListener.clear(); + if (spServer) + return; + + spServer = new RemoteServer(); + spServer->launch(); } + void RemoteServer::presentationStarted( const css::uno::Reference< - css::presentation::XSlideShowController > &rController ) + css::presentation::XSlideShowController > &rController ) { - if ( pTransmitter ) + if ( !spServer ) + return; + MutexGuard aGuard( spServer->mDataMutex ); + for ( vector<Communicator*>::const_iterator aIt = spServer->mCommunicators.begin(); + aIt < spServer->mCommunicators.end(); aIt++ ) { - mListener = rtl::Reference<Listener>( new Listener( spServer, pTransmitter ) ); - mListener->init( rController ); + (*aIt)->presentationStarted( rController ); } } - void RemoteServer::presentationStopped() { - if ( mListener.is() ) + if ( !spServer ) + return; + MutexGuard aGuard( spServer->mDataMutex ); + for ( vector<Communicator*>::const_iterator aIt = spServer->mCommunicators.begin(); + aIt < spServer->mCommunicators.end(); aIt++ ) { - mListener->disposing(); - mListener = NULL; + (*aIt)->disposeListener(); } } -RemoteServer *sd::RemoteServer::spServer = NULL; -Transmitter *sd::RemoteServer::pTransmitter = NULL; -rtl::Reference<Listener> sd::RemoteServer::mListener = NULL; - -void RemoteServer::setup() +void RemoteServer::removeCommunicator( Communicator* mCommunicator ) { - if (spServer) - return; - - spServer = new RemoteServer(); - spServer->launch(); + if ( !spServer ) + return; + MutexGuard aGuard( spServer->mDataMutex ); + for ( vector<Communicator*>::iterator aIt = spServer->mCommunicators.begin(); + aIt < spServer->mCommunicators.end(); aIt++ ) + { + if ( mCommunicator == *aIt ) + { + spServer->mCommunicators.erase( aIt ); + break; + } + } } -std::vector<ClientInfo> RemoteServer::getClients() +std::vector<ClientInfo*> RemoteServer::getClients() { - std::vector<ClientInfo> aV; - aV.push_back( ClientInfo( "A phone", "akaakaskj" ) ); - aV.push_back( ClientInfo( "B phone", "iiiiiii" ) ); - return aV; + if ( !spServer ) + std::vector<ClientInfo*>(); + MutexGuard aGuard( spServer->mDataMutex ); + std::vector<ClientInfo*> aClients; + aClients.assign( spServer->mAvailableClients.begin(), + spServer->mAvailableClients.end() ); + return aClients; } void RemoteServer::connectClient( ClientInfo aClient, rtl::OString aPin ) |