From f9685dc555cc79fe3a52caf9da39df37da750cd4 Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Thu, 14 Feb 2013 17:07:01 +0200 Subject: More work on the Impress Remote Control Bluetooth code for OS X Mostly the work of Thorsten, from December, adapted to compile against the current remote control code, and with one or two crucial things added. Plus lots of SAL_INFO calls added; once it works well many of them can be dropped. Does not work properly yet, do not cherry-pick just this to 4.0. Change-Id: I53361b49a2b6938c768be1ea0fc17eb5e46b6aa4 --- sd/Library_sd.mk | 1 + sd/source/ui/remotecontrol/BluetoothServer.cxx | 160 ++++++++++++++++++++- sd/source/ui/remotecontrol/BluetoothServer.hxx | 2 + .../ui/remotecontrol/BufferedStreamSocket.hxx | 10 +- sd/source/ui/remotecontrol/Communicator.cxx | 2 +- sd/source/ui/remotecontrol/Communicator.hxx | 10 +- sd/source/ui/remotecontrol/IBluetoothSocket.hxx | 41 ++++++ sd/source/ui/remotecontrol/OSXBluetooth.h | 33 +++++ sd/source/ui/remotecontrol/OSXBluetooth.mm | 48 +++++++ sd/source/ui/remotecontrol/OSXBluetoothWrapper.hxx | 40 ++++++ sd/source/ui/remotecontrol/Server.cxx | 1 + sd/source/ui/remotecontrol/Transmitter.cxx | 2 +- sd/source/ui/remotecontrol/Transmitter.hxx | 8 +- 13 files changed, 338 insertions(+), 20 deletions(-) create mode 100644 sd/source/ui/remotecontrol/IBluetoothSocket.hxx create mode 100644 sd/source/ui/remotecontrol/OSXBluetooth.h create mode 100644 sd/source/ui/remotecontrol/OSXBluetooth.mm create mode 100644 sd/source/ui/remotecontrol/OSXBluetoothWrapper.hxx (limited to 'sd') diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk index 679c83670fda..49678453b132 100644 --- a/sd/Library_sd.mk +++ b/sd/Library_sd.mk @@ -543,6 +543,7 @@ else $(eval $(call gb_Library_add_objcxxobjects,sd,\ sd/source/ui/remotecontrol/BluetoothServer \ + sd/source/ui/remotecontrol/OSXBluetooth \ )) $(eval $(call gb_Library_add_libs,sd,\ diff --git a/sd/source/ui/remotecontrol/BluetoothServer.cxx b/sd/source/ui/remotecontrol/BluetoothServer.cxx index e877cca22756..1830a3b159d9 100644 --- a/sd/source/ui/remotecontrol/BluetoothServer.cxx +++ b/sd/source/ui/remotecontrol/BluetoothServer.cxx @@ -9,7 +9,8 @@ #include "BluetoothServer.hxx" -#include +#include +#include #include @@ -40,6 +41,7 @@ #endif #ifdef MACOSX + #include // Include this early to avoid error as check() gets defined by some SDK header to empty #include #if MACOSX_SDK_VERSION >= 1070 #import @@ -50,6 +52,8 @@ #import #endif #include + #import "OSXBluetooth.h" + #include "OSXBluetoothWrapper.hxx" #endif #ifdef __MINGW32__ @@ -104,6 +108,141 @@ DBusGProxy* bluezGetDefaultAdapter( DBusGConnection* aConnection, } #endif // defined(LINUX) && defined(ENABLE_DBUS) +#if defined(MACOSX) + +OSXBluetoothWrapper::OSXBluetoothWrapper( IOBluetoothRFCOMMChannel* channel ) : + mpChannel(channel), + mnMTU(0), + mHaveBytes(), + mMutex(), + mBuffer() +{ + // silly enough, can't write more than mnMTU bytes at once + mnMTU = [channel getMTU]; + + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::OSXBluetoothWrapper(): mnMTU=" << mnMTU ); +} + +sal_Int32 OSXBluetoothWrapper::readLine( rtl::OString& aLine ) +{ + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::readLine()" ); + + while( true ) + { + { + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::readLine: entering mutex" ); + ::osl::MutexGuard aQueueGuard( mMutex ); + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::readLine: entered mutex" ); + +#ifdef SAL_LOG_INFO + // We should have in the sal logging some standard way to + // output char buffers with non-printables escaped. + std::ostringstream s; + for (unsigned char *p = (unsigned char *) mBuffer.data(); p != (unsigned char *) mBuffer.data() + mBuffer.size(); p++) + { + if (*p == '\n') + s << "\\n"; + else if (*p < ' ' || (*p >= 0x7F && *p <= 0xFF)) + s << "\\0x" << std::hex << std::setw(2) << std::setfill('0') << (int) *p << std::setfill(' ') << std::setw(1) << std::dec; + else + s << *p; + } + SAL_INFO( "sdremote.bluetooth", " mBuffer: \"" << s.str() << "\"" ); +#endif + + // got enough bytes to return a line? + std::vector::iterator aIt; + if ( (aIt = find( mBuffer.begin(), mBuffer.end(), '\n' )) + != mBuffer.end() ) + { + sal_uInt64 aLocation = aIt - mBuffer.begin(); + + aLine = OString( &(*mBuffer.begin()), aLocation ); + + mBuffer.erase( mBuffer.begin(), aIt + 1 ); // Also delete the empty line + + // yeps + SAL_INFO( "sdremote.bluetooth", " returning, got \"" << OStringToOUString( aLine, RTL_TEXTENCODING_UTF8 ) << "\"" ); + return aLine.getLength() + 1; + } + + // nope - wait some more (after releasing the mutex) + SAL_INFO( "sdremote.bluetooth", " resetting mHaveBytes" ); + mHaveBytes.reset(); + SAL_INFO( "sdremote.bluetooth", " leaving mutex" ); + } + + SAL_INFO( "sdremote.bluetooth", " waiting for mHaveBytes" ); + mHaveBytes.wait(); + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::readLine: got mHaveBytes" ); + } +} + +sal_Int32 OSXBluetoothWrapper::write( const void* pBuffer, sal_uInt32 n ) +{ + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::write(" << pBuffer << ", " << n << ") mpChannel=" << mpChannel ); + + char* ptr = (char*)pBuffer; + sal_uInt32 nBytesWritten = 0; + while( nBytesWritten < n ) + { + int toWrite = n - nBytesWritten; + toWrite = toWrite <= mnMTU ? toWrite : mnMTU; + if ( [mpChannel writeSync:ptr length:toWrite] != kIOReturnSuccess ) + { + SAL_INFO( "sdremote.bluetooth", " [mpChannel writeSync:" << (void *) ptr << " length:" << toWrite << "] returned error, total written " << nBytesWritten ); + return nBytesWritten; + } + ptr += toWrite; + nBytesWritten += toWrite; + } + SAL_INFO( "sdremote.bluetooth", " total written " << nBytesWritten ); + return nBytesWritten; +} + +void OSXBluetoothWrapper::appendData(void* pBuffer, size_t len) +{ + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::appendData(" << pBuffer << ", " << len << ")" ); + + if( len ) + { + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::appendData: entering mutex" ); + ::osl::MutexGuard aQueueGuard( mMutex ); + SAL_INFO( "sdremote.bluetooth", "OSXBluetoothWrapper::appendData: entered mutex" ); + mBuffer.insert(mBuffer.begin()+mBuffer.size(), + (char*)pBuffer, (char *)pBuffer+len); + SAL_INFO( "sdremote.bluetooth", " setting mHaveBytes" ); + mHaveBytes.set(); + SAL_INFO( "sdremote.bluetooth", " leaving mutex" ); + } +} + +void incomingCallback( void *userRefCon, + IOBluetoothUserNotificationRef inRef, + IOBluetoothObjectRef objectRef ) +{ + (void) inRef; + + SAL_INFO( "sdremote.bluetooth", "incomingCallback()" ); + + BluetoothServer* pServer = (BluetoothServer*)userRefCon; + + IOBluetoothRFCOMMChannel* channel = [IOBluetoothRFCOMMChannel withRFCOMMChannelRef:(IOBluetoothRFCOMMChannelRef)objectRef]; + + OSXBluetoothWrapper* socket = new OSXBluetoothWrapper( channel); + Communicator* pCommunicator = new Communicator( socket ); + pServer->addCommunicator( pCommunicator ); + + ChannelDelegate* delegate = [[ChannelDelegate alloc] initWithCommunicatorAndSocket: pCommunicator socket: socket]; + [channel setDelegate: delegate]; + [delegate retain]; + + pCommunicator->launch(); +} + +#endif // MACOSX + + BluetoothServer::BluetoothServer( std::vector* pCommunicators ) : mpCommunicators( pCommunicators ) { @@ -260,6 +399,11 @@ void BluetoothServer::setDiscoverable( bool aDiscoverable ) #endif } +void BluetoothServer::addCommunicator( Communicator* pCommunicator ) +{ + mpCommunicators->push_back( pCommunicator ); +} + void SAL_CALL BluetoothServer::run() { SAL_INFO( "sdremote.bluetooth", "BluetoothServer::run called" ); @@ -526,7 +670,7 @@ void SAL_CALL BluetoothServer::run() IOBluetoothSDPServiceRecordRef serviceRecordRef; IOReturn rc = IOBluetoothAddServiceDict((CFDictionaryRef) dict, &serviceRecordRef); - SAL_INFO("sd.bluetooth", "IOBluetoothAddServiceDict returned " << rc); + SAL_INFO("sdremote.bluetooth", "IOBluetoothAddServiceDict returned " << rc); if (rc == kIOReturnSuccess) { @@ -539,9 +683,17 @@ void SAL_CALL BluetoothServer::run() BluetoothSDPServiceRecordHandle serviceRecordHandle; [serviceRecord getServiceRecordHandle: &serviceRecordHandle]; - // Do more... + // Register callback for incoming connections + IOBluetoothUserNotificationRef callbackRef = + IOBluetoothRegisterForFilteredRFCOMMChannelOpenNotifications( + incomingCallback, + this, + channelID, + kIOBluetoothUserNotificationChannelDirectionIncoming); + + (void) callbackRef; - (void) serviceRecord; + [serviceRecord release]; } (void) mpCommunicators; #else diff --git a/sd/source/ui/remotecontrol/BluetoothServer.hxx b/sd/source/ui/remotecontrol/BluetoothServer.hxx index 51be45f7d9bc..d8c9879ab59b 100644 --- a/sd/source/ui/remotecontrol/BluetoothServer.hxx +++ b/sd/source/ui/remotecontrol/BluetoothServer.hxx @@ -24,6 +24,8 @@ namespace sd static bool isDiscoverable(); static void setDiscoverable( bool aDiscoverable ); + void addCommunicator( Communicator* pCommunicator ); + private: BluetoothServer( std::vector* pCommunicators ); ~BluetoothServer(); diff --git a/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx b/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx index bf9a58aad7c0..eafaa6bfc525 100644 --- a/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx +++ b/sd/source/ui/remotecontrol/BufferedStreamSocket.hxx @@ -9,7 +9,7 @@ #ifndef _SD_IMPRESSREMOTE_BUFFEREDSTREAMSOCKET_HXX #define _SD_IMPRESSREMOTE_BUFFEREDSTREAMSOCKET_HXX -#include +#include "IBluetoothSocket.hxx" #include #include @@ -28,8 +28,8 @@ namespace sd * integrated into osl Sockets. */ class BufferedStreamSocket : - private ::osl::StreamSocket, - private ::boost::noncopyable + public IBluetoothSocket, + private ::osl::StreamSocket { public: /** @@ -47,9 +47,9 @@ namespace sd * Returns whatever the last call of recv returned, i.e. 0 or less * if there was a problem in communications. */ - sal_Int32 readLine(OString& aLine); + virtual sal_Int32 readLine( OString& aLine ); - sal_Int32 write( const void* pBuffer, sal_uInt32 n ); + virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ); void getPeerAddr(osl::SocketAddr&); private: diff --git a/sd/source/ui/remotecontrol/Communicator.cxx b/sd/source/ui/remotecontrol/Communicator.cxx index 84467da26eb4..908f732d0a07 100644 --- a/sd/source/ui/remotecontrol/Communicator.cxx +++ b/sd/source/ui/remotecontrol/Communicator.cxx @@ -22,7 +22,7 @@ using namespace std; using namespace com::sun::star; using namespace osl; -Communicator::Communicator( BufferedStreamSocket *pSocket ): +Communicator::Communicator( IBluetoothSocket *pSocket ): Thread( "CommunicatorThread" ), mpSocket( pSocket ), pTransmitter( 0 ), diff --git a/sd/source/ui/remotecontrol/Communicator.hxx b/sd/source/ui/remotecontrol/Communicator.hxx index 10078bf63387..a783bacb7672 100644 --- a/sd/source/ui/remotecontrol/Communicator.hxx +++ b/sd/source/ui/remotecontrol/Communicator.hxx @@ -9,20 +9,17 @@ #ifndef _SD_IMPRESSREMOTE_COMMUNICATOR_HXX #define _SD_IMPRESSREMOTE_COMMUNICATOR_HXX -// SERVER -#include #include #include #include #include -#include #include #include #include -#include "BufferedStreamSocket.hxx" +#include "IBluetoothSocket.hxx" #define CHARSET RTL_TEXTENCODING_UTF8 namespace sd @@ -39,7 +36,7 @@ namespace sd class Communicator : public salhelper::Thread { public: - Communicator( BufferedStreamSocket *pSocket ); + Communicator( IBluetoothSocket *pSocket ); ~Communicator(); void presentationStarted( const css::uno::Reference< @@ -49,7 +46,7 @@ namespace sd private: void execute(); - BufferedStreamSocket *mpSocket; + IBluetoothSocket *mpSocket; Transmitter *pTransmitter; rtl::Reference mListener; @@ -57,4 +54,5 @@ namespace sd } #endif // _SD_IMPRESSREMOTE_COMMUNICATOR_HXX + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/IBluetoothSocket.hxx b/sd/source/ui/remotecontrol/IBluetoothSocket.hxx new file mode 100644 index 000000000000..194936730058 --- /dev/null +++ b/sd/source/ui/remotecontrol/IBluetoothSocket.hxx @@ -0,0 +1,41 @@ +/* -*- 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_IBLUETOOTHSOCKET_HXX +#define _SD_IMPRESSREMOTE_IBLUETOOTHSOCKET_HXX + +#include +#include + +namespace sd +{ + /** Interface for bluetooth data io + */ + struct IBluetoothSocket : private boost::noncopyable + { + virtual ~IBluetoothSocket() {} + + /** Blocks until a line is read. + + @return whatever the last call of recv returned, i.e. 0 or less + if there was a problem in communications. + */ + virtual sal_Int32 readLine(rtl::OString& aLine) = 0; + + /** Write a number of bytes + + @return number of bytes actually written + */ + virtual sal_Int32 write( const void* pBuffer, sal_uInt32 n ) = 0; + }; +} + +#endif // _SD_IMPRESSREMOTE_IBLUETOOTHSOCKET_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/OSXBluetooth.h b/sd/source/ui/remotecontrol/OSXBluetooth.h new file mode 100644 index 000000000000..4c1900adb65d --- /dev/null +++ b/sd/source/ui/remotecontrol/OSXBluetooth.h @@ -0,0 +1,33 @@ +/* -*- Mode: ObjC; 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 INCLUDED_OSXBLUETOOTH_H +#define INCLUDED_OSXBLUETOOTH_H + +#import + +#include "IBluetoothSocket.hxx" +#include "Communicator.hxx" +#include "OSXBluetoothWrapper.hxx" + +@interface ChannelDelegate : NSObject +{ + sd::Communicator* pCommunicator; + sd::OSXBluetoothWrapper* pSocket; +} + +- (id) initWithCommunicatorAndSocket:(sd::Communicator*)communicator socket:(sd::OSXBluetoothWrapper*)socket; +- (void) rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength; +- (void) rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel; + +@end + +#endif /* INCLUDED_OSXBLUETOOTH_H */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/OSXBluetooth.mm b/sd/source/ui/remotecontrol/OSXBluetooth.mm new file mode 100644 index 000000000000..2c21e698b15e --- /dev/null +++ b/sd/source/ui/remotecontrol/OSXBluetooth.mm @@ -0,0 +1,48 @@ +/* -*- Mode: ObjC; 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 // Include this early to avoid error as check() gets defined by some SDK header to empty + +#include +#import +#include + +#include "OSXBluetooth.h" + +@implementation ChannelDelegate + +- (id) initWithCommunicatorAndSocket:(sd::Communicator*)communicator socket:(sd::OSXBluetoothWrapper*)socket +{ + pCommunicator = communicator; + pSocket = socket; + return self; +} + +- (void) rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength +{ + (void) rfcommChannel; + + if ( pSocket ) + { + pSocket->appendData(dataPointer, dataLength); + } +} + +- (void) rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel +{ + (void) rfcommChannel; + + // TODO: broadcast premature closing of data channel + pCommunicator = NULL; + pSocket = NULL; +} + +@end + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/OSXBluetoothWrapper.hxx b/sd/source/ui/remotecontrol/OSXBluetoothWrapper.hxx new file mode 100644 index 000000000000..6a61a24bc97b --- /dev/null +++ b/sd/source/ui/remotecontrol/OSXBluetoothWrapper.hxx @@ -0,0 +1,40 @@ +/* -*- 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_OSXBLUETOOTHWRAPPER_HXX +#define _SD_IMPRESSREMOTE_OSXBLUETOOTHWRAPPER_HXX + +#include +#include +#include +#include + +#include "IBluetoothSocket.hxx" + +namespace sd +{ + class OSXBluetoothWrapper : public IBluetoothSocket + { + IOBluetoothRFCOMMChannel* mpChannel; + int mnMTU; + osl::Condition mHaveBytes; + osl::Mutex mMutex; + std::vector mBuffer; + + public: + OSXBluetoothWrapper( IOBluetoothRFCOMMChannel* channel ); + virtual sal_Int32 readLine( rtl::OString& aLine ); + virtual sal_Int32 write( const void* pBuffer, sal_uInt32 len ); + void appendData(void* pBuffer, size_t len ); + }; +} + +#endif // _SD_IMPRESSREMOTE_OSXBLUETOOTHWRAPPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/ui/remotecontrol/Server.cxx b/sd/source/ui/remotecontrol/Server.cxx index 76b4dd7c1562..9989ed05bb57 100644 --- a/sd/source/ui/remotecontrol/Server.cxx +++ b/sd/source/ui/remotecontrol/Server.cxx @@ -29,6 +29,7 @@ #include "RemoteServer.hxx" #include "BluetoothServer.hxx" #include "Communicator.hxx" +#include "BufferedStreamSocket.hxx" using namespace std; using namespace sd; diff --git a/sd/source/ui/remotecontrol/Transmitter.cxx b/sd/source/ui/remotecontrol/Transmitter.cxx index e8e3388d7e88..a7c211b20ad1 100644 --- a/sd/source/ui/remotecontrol/Transmitter.cxx +++ b/sd/source/ui/remotecontrol/Transmitter.cxx @@ -13,7 +13,7 @@ using namespace std; using namespace osl; // Sockets etc. using namespace sd; -Transmitter::Transmitter( BufferedStreamSocket* aSocket ) +Transmitter::Transmitter( IBluetoothSocket* aSocket ) : pStreamSocket( aSocket ), mQueuesNotEmpty(), mFinishRequested(), diff --git a/sd/source/ui/remotecontrol/Transmitter.hxx b/sd/source/ui/remotecontrol/Transmitter.hxx index 80e09b1793df..783e1d5dbc3c 100644 --- a/sd/source/ui/remotecontrol/Transmitter.hxx +++ b/sd/source/ui/remotecontrol/Transmitter.hxx @@ -6,12 +6,13 @@ * 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_TRANSMITTER_HXX #define _SD_IMPRESSREMOTE_TRANSMITTER_HXX #include #include -#include "BufferedStreamSocket.hxx" +#include "IBluetoothSocket.hxx" #include #include @@ -25,7 +26,7 @@ class Transmitter { public: enum Priority { PRIORITY_LOW = 1, PRIORITY_HIGH }; - Transmitter( ::sd::BufferedStreamSocket* aSocket ); + Transmitter( ::sd::IBluetoothSocket* aSocket ); ~Transmitter(); void addMessage( const rtl::OString& aMessage, const Priority aPriority ); void notifyFinished(); @@ -33,7 +34,7 @@ public: private: virtual void SAL_CALL run(); - ::sd::BufferedStreamSocket* pStreamSocket; + ::sd::IBluetoothSocket* pStreamSocket; ::osl::Condition mQueuesNotEmpty; ::osl::Condition mFinishRequested; @@ -46,4 +47,5 @@ private: } #endif // _SD_IMPRESSREMOTE_TRANSMITTER_HXX + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit '>feature/print_revamp LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
AgeCommit message (Expand)Author