xref: /aoo41x/main/vcl/unx/headless/svpelement.cxx (revision cdf0e10c)
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