1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "svpelement.hxx" 29 30 #include <basebmp/scanlineformats.hxx> 31 #include <tools/debug.hxx> 32 33 #if defined WITH_SVP_LISTENING 34 #include <osl/thread.h> 35 #include <vcl/svapp.hxx> 36 #include <rtl/strbuf.hxx> 37 #include <vcl/bitmap.hxx> 38 #include <tools/stream.hxx> 39 40 #include "svpvd.hxx" 41 #include "svpbmp.hxx" 42 #include "svpframe.hxx" 43 44 #include <list> 45 #include <hash_map> 46 47 #include <sys/types.h> 48 #include <sys/socket.h> 49 #include <netinet/ip.h> 50 #include <stdio.h> 51 #include <errno.h> 52 53 using namespace basegfx; 54 55 class SvpElementContainer 56 { 57 std::list< SvpElement* > m_aElements; 58 int m_nSocket; 59 oslThread m_aThread; 60 61 SvpElementContainer(); 62 ~SvpElementContainer(); 63 public: 64 void registerElement( SvpElement* pElement ) { m_aElements.push_back(pElement); } 65 void deregisterElement( SvpElement* pElement ) { m_aElements.remove(pElement); } 66 67 void run(); 68 DECL_LINK(processRequest,void*); 69 70 static SvpElementContainer& get(); 71 }; 72 73 extern "C" void SAL_CALL SvpContainerThread( void* ); 74 75 SvpElementContainer& SvpElementContainer::get() 76 { 77 static SvpElementContainer* pInstance = new SvpElementContainer(); 78 return *pInstance; 79 } 80 81 SvpElementContainer::SvpElementContainer() 82 { 83 static const char* pEnv = getenv("SVP_LISTENER_PORT"); 84 int nPort = (pEnv && *pEnv) ? atoi(pEnv) : 8000; 85 m_nSocket = socket( PF_INET, SOCK_STREAM, 0 ); 86 if( m_nSocket >= 0) 87 { 88 int nOn = 1; 89 if( setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR, 90 (char*)&nOn, sizeof(nOn)) ) 91 { 92 perror( "SvpElementContainer: changing socket options failed" ); 93 close( m_nSocket ); 94 } 95 else 96 { 97 struct sockaddr_in addr; 98 memset(&addr, 0, sizeof(struct sockaddr_in)); 99 addr.sin_family = AF_INET; 100 addr.sin_port = htons(nPort); 101 addr.sin_addr.s_addr = INADDR_ANY; 102 if( bind(m_nSocket,(struct sockaddr*)&addr,sizeof(addr)) ) 103 { 104 perror( "SvpElementContainer: bind() failed" ); 105 close( m_nSocket ); 106 } 107 else 108 { 109 if( listen( m_nSocket, 0 ) ) 110 { 111 perror( "SvpElementContainer: listen() failed" ); 112 close(m_nSocket); 113 } 114 else 115 { 116 m_aThread = osl_createThread( SvpContainerThread, this ); 117 } 118 } 119 } 120 } 121 else 122 perror( "SvpElementContainer: socket() failed\n" ); 123 } 124 125 SvpElementContainer::~SvpElementContainer() 126 { 127 } 128 129 void SAL_CALL SvpContainerThread(void* pSvpContainer) 130 { 131 ((SvpElementContainer*)pSvpContainer)->run(); 132 } 133 134 void SvpElementContainer::run() 135 { 136 bool bRun = m_nSocket != 0; 137 while( bRun ) 138 { 139 int nLocalSocket = accept( m_nSocket, NULL, NULL ); 140 if( nLocalSocket < 0 ) 141 { 142 bRun = false; 143 perror( "accept() failed" ); 144 } 145 else 146 { 147 Application::PostUserEvent( LINK( this, SvpElementContainer, processRequest ), (void*)nLocalSocket ); 148 } 149 } 150 if( m_nSocket ) 151 close( m_nSocket ); 152 } 153 154 static const char* matchType( SvpElement* pEle ) 155 { 156 if( dynamic_cast<SvpSalBitmap*>(pEle) ) 157 return "Bitmap"; 158 else if( dynamic_cast<SvpSalFrame*>(pEle) ) 159 return "Frame"; 160 else if( dynamic_cast<SvpSalVirtualDevice*>(pEle) ) 161 return "VirtualDevice"; 162 return typeid(*pEle).name(); 163 } 164 165 IMPL_LINK( SvpElementContainer, processRequest, void*, pSocket ) 166 { 167 int nFile = (int)pSocket; 168 169 rtl::OStringBuffer aBuf( 256 ), aAnswer( 256 ); 170 char c; 171 while( read( nFile, &c, 1 ) && c != '\n' ) 172 aBuf.append( sal_Char(c) ); 173 rtl::OString aCommand( aBuf.makeStringAndClear() ); 174 if( aCommand.compareTo( "list", 4 ) == 0 ) 175 { 176 std::hash_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash > aMap; 177 for( std::list< SvpElement* >::const_iterator it = m_aElements.begin(); 178 it != m_aElements.end(); ++it ) 179 { 180 std::list<SvpElement*>& rList = aMap[matchType(*it)]; 181 rList.push_back( *it ); 182 } 183 for( std::hash_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash>::const_iterator hash_it = aMap.begin(); 184 hash_it != aMap.end(); ++hash_it ) 185 { 186 aAnswer.append( "ElementType: " ); 187 aAnswer.append( hash_it->first ); 188 aAnswer.append( '\n' ); 189 for( std::list<SvpElement*>::const_iterator it = hash_it->second.begin(); 190 it != hash_it->second.end(); ++it ) 191 { 192 aAnswer.append( sal_Int64(reinterpret_cast<sal_uInt32>(*it)), 16 ); 193 aAnswer.append( '\n' ); 194 } 195 } 196 } 197 else if( aCommand.compareTo( "get", 3 ) == 0 ) 198 { 199 sal_IntPtr aId = aCommand.copy( 3 ).toInt64( 16 ); 200 SvpElement* pElement = reinterpret_cast<SvpElement*>(aId); 201 for( std::list< SvpElement* >::const_iterator it = m_aElements.begin(); 202 it != m_aElements.end(); ++it ) 203 { 204 if( *it == pElement ) 205 { 206 const basebmp::BitmapDeviceSharedPtr& rDevice = pElement->getDevice(); 207 if( rDevice.get() ) 208 { 209 SvpSalBitmap* pSalBitmap = new SvpSalBitmap(); 210 pSalBitmap->setBitmap( rDevice ); 211 Bitmap aBitmap( pSalBitmap ); 212 SvMemoryStream aStream( 256, 256 ); 213 aStream << aBitmap; 214 aStream.Seek( STREAM_SEEK_TO_END ); 215 int nBytes = aStream.Tell(); 216 aStream.Seek( STREAM_SEEK_TO_BEGIN ); 217 aAnswer.append( (const sal_Char*)aStream.GetData(), nBytes ); 218 } 219 break; 220 } 221 } 222 } 223 else if( aCommand.compareTo( "quit", 4 ) == 0 ) 224 { 225 Application::Quit(); 226 close( m_nSocket ); 227 m_nSocket = 0; 228 } 229 write( nFile, aAnswer.getStr(), aAnswer.getLength() ); 230 close( nFile ); 231 232 return 0; 233 } 234 235 #endif 236 237 using namespace basebmp; 238 239 SvpElement::SvpElement() 240 { 241 #if defined WITH_SVP_LISTENING 242 SvpElementContainer::get().registerElement( this ); 243 #endif 244 } 245 246 SvpElement::~SvpElement() 247 { 248 #if defined WITH_SVP_LISTENING 249 SvpElementContainer::get().deregisterElement( this ); 250 #endif 251 } 252 253 sal_uInt32 SvpElement::getBitCountFromScanlineFormat( sal_Int32 nFormat ) 254 { 255 sal_uInt32 nBitCount = 1; 256 switch( nFormat ) 257 { 258 case Format::ONE_BIT_MSB_GREY: 259 case Format::ONE_BIT_LSB_GREY: 260 case Format::ONE_BIT_MSB_PAL: 261 case Format::ONE_BIT_LSB_PAL: 262 nBitCount = 1; 263 break; 264 case Format::FOUR_BIT_MSB_GREY: 265 case Format::FOUR_BIT_LSB_GREY: 266 case Format::FOUR_BIT_MSB_PAL: 267 case Format::FOUR_BIT_LSB_PAL: 268 nBitCount = 4; 269 break; 270 case Format::EIGHT_BIT_PAL: 271 case Format::EIGHT_BIT_GREY: 272 nBitCount = 8; 273 break; 274 case Format::SIXTEEN_BIT_LSB_TC_MASK: 275 case Format::SIXTEEN_BIT_MSB_TC_MASK: 276 nBitCount = 16; 277 break; 278 case Format::TWENTYFOUR_BIT_TC_MASK: 279 nBitCount = 24; 280 break; 281 case Format::THIRTYTWO_BIT_TC_MASK: 282 nBitCount = 32; 283 break; 284 default: 285 DBG_ERROR( "unsupported basebmp format" ); 286 break; 287 } 288 return nBitCount; 289 } 290 291 292