Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "headless/svpelement.hxx"
21 :
22 : #include <basebmp/scanlineformats.hxx>
23 : #include <osl/diagnose.h>
24 :
25 : #if defined WITH_SVP_LISTENING
26 : #include <osl/thread.h>
27 : #include <vcl/svapp.hxx>
28 : #include <rtl/strbuf.hxx>
29 : #include <vcl/bitmap.hxx>
30 : #include <tools/stream.hxx>
31 :
32 : #include "headless/svpvd.hxx"
33 : #include "headless/svpbmp.hxx"
34 : #include "headless/svpframe.hxx"
35 :
36 : #include <list>
37 : #include <boost/unordered_map.hpp>
38 :
39 : #include <sys/types.h>
40 : #include <sys/socket.h>
41 : #include <netinet/ip.h>
42 : #include <stdio.h>
43 : #include <errno.h>
44 :
45 : using namespace basegfx;
46 :
47 : class SvpElementContainer
48 : {
49 : std::list< SvpElement* > m_aElements;
50 : int m_nSocket;
51 : oslThread m_aThread;
52 :
53 : SvpElementContainer();
54 : ~SvpElementContainer();
55 : public:
56 : void registerElement( SvpElement* pElement ) { m_aElements.push_back(pElement); }
57 : void deregisterElement( SvpElement* pElement ) { m_aElements.remove(pElement); }
58 :
59 : void run();
60 : DECL_LINK(processRequest,void*);
61 :
62 : static SvpElementContainer& get();
63 : };
64 :
65 : extern "C" void SAL_CALL SvpContainerThread( void* );
66 :
67 : SvpElementContainer& SvpElementContainer::get()
68 : {
69 : static SvpElementContainer* pInstance = new SvpElementContainer();
70 : return *pInstance;
71 : }
72 :
73 : SvpElementContainer::SvpElementContainer()
74 : {
75 : static const char* pEnv = getenv("SVP_LISTENER_PORT");
76 : int nPort = (pEnv && *pEnv) ? atoi(pEnv) : 8000;
77 : m_nSocket = socket( PF_INET, SOCK_STREAM, 0 );
78 : if( m_nSocket >= 0)
79 : {
80 : int nOn = 1;
81 : if( setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR,
82 : (char*)&nOn, sizeof(nOn)) )
83 : {
84 : perror( "SvpElementContainer: changing socket options failed" );
85 : close( m_nSocket );
86 : }
87 : else
88 : {
89 : struct sockaddr_in addr;
90 : memset(&addr, 0, sizeof(struct sockaddr_in));
91 : addr.sin_family = AF_INET;
92 : addr.sin_port = htons(nPort);
93 : addr.sin_addr.s_addr = INADDR_ANY;
94 : if( bind(m_nSocket,(struct sockaddr*)&addr,sizeof(addr)) )
95 : {
96 : perror( "SvpElementContainer: bind() failed" );
97 : close( m_nSocket );
98 : }
99 : else
100 : {
101 : if( listen( m_nSocket, 0 ) )
102 : {
103 : perror( "SvpElementContainer: listen() failed" );
104 : close(m_nSocket);
105 : }
106 : else
107 : {
108 : m_aThread = osl_createThread( SvpContainerThread, this );
109 : }
110 : }
111 : }
112 : }
113 : else
114 : perror( "SvpElementContainer: socket() failed\n" );
115 : }
116 :
117 : SvpElementContainer::~SvpElementContainer()
118 : {
119 : }
120 :
121 : void SAL_CALL SvpContainerThread(void* pSvpContainer)
122 : {
123 : ((SvpElementContainer*)pSvpContainer)->run();
124 : }
125 :
126 : void SvpElementContainer::run()
127 : {
128 : bool bRun = m_nSocket != 0;
129 : while( bRun )
130 : {
131 : int nLocalSocket = accept( m_nSocket, NULL, NULL );
132 : if( nLocalSocket < 0 )
133 : {
134 : bRun = false;
135 : perror( "accept() failed" );
136 : }
137 : else
138 : {
139 : Application::PostUserEvent( LINK( this, SvpElementContainer, processRequest ), (void*)nLocalSocket );
140 : }
141 : }
142 : if( m_nSocket )
143 : close( m_nSocket );
144 : }
145 :
146 : static const char* matchType( SvpElement* pEle )
147 : {
148 : if( dynamic_cast<SvpSalBitmap*>(pEle) )
149 : return "Bitmap";
150 : else if( dynamic_cast<SvpSalFrame*>(pEle) )
151 : return "Frame";
152 : else if( dynamic_cast<SvpSalVirtualDevice*>(pEle) )
153 : return "VirtualDevice";
154 : return typeid(*pEle).name();
155 : }
156 :
157 : IMPL_LINK( SvpElementContainer, processRequest, void*, pSocket )
158 : {
159 : int nFile = (int)pSocket;
160 :
161 : rtl::OStringBuffer aBuf( 256 ), aAnswer( 256 );
162 : char c;
163 : while( read( nFile, &c, 1 ) && c != '\n' )
164 : aBuf.append( sal_Char(c) );
165 : rtl::OString aCommand( aBuf.makeStringAndClear() );
166 : if( aCommand.compareTo( "list", 4 ) == 0 )
167 : {
168 : boost::unordered_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash > aMap;
169 : for( std::list< SvpElement* >::const_iterator it = m_aElements.begin();
170 : it != m_aElements.end(); ++it )
171 : {
172 : std::list<SvpElement*>& rList = aMap[matchType(*it)];
173 : rList.push_back( *it );
174 : }
175 : for( boost::unordered_map< rtl::OString, std::list<SvpElement*>, rtl::OStringHash>::const_iterator hash_it = aMap.begin();
176 : hash_it != aMap.end(); ++hash_it )
177 : {
178 : aAnswer.append( "ElementType: " );
179 : aAnswer.append( hash_it->first );
180 : aAnswer.append( '\n' );
181 : for( std::list<SvpElement*>::const_iterator it = hash_it->second.begin();
182 : it != hash_it->second.end(); ++it )
183 : {
184 : aAnswer.append( sal_Int64(reinterpret_cast<sal_uInt32>(*it)), 16 );
185 : aAnswer.append( '\n' );
186 : }
187 : }
188 : }
189 : else if( aCommand.compareTo( "get", 3 ) == 0 )
190 : {
191 : sal_IntPtr aId = aCommand.copy( 3 ).toInt64( 16 );
192 : SvpElement* pElement = reinterpret_cast<SvpElement*>(aId);
193 : for( std::list< SvpElement* >::const_iterator it = m_aElements.begin();
194 : it != m_aElements.end(); ++it )
195 : {
196 : if( *it == pElement )
197 : {
198 : const basebmp::BitmapDeviceSharedPtr& rDevice = pElement->getDevice();
199 : if( rDevice.get() )
200 : {
201 : SvpSalBitmap* pSalBitmap = new SvpSalBitmap();
202 : pSalBitmap->setBitmap( rDevice );
203 : Bitmap aBitmap( pSalBitmap );
204 : SvMemoryStream aStream( 256, 256 );
205 : aStream << aBitmap;
206 : aStream.Seek( STREAM_SEEK_TO_END );
207 : int nBytes = aStream.Tell();
208 : aStream.Seek( STREAM_SEEK_TO_BEGIN );
209 : aAnswer.append( (const sal_Char*)aStream.GetData(), nBytes );
210 : }
211 : break;
212 : }
213 : }
214 : }
215 : else if( aCommand.compareTo( "quit", 4 ) == 0 )
216 : {
217 : Application::Quit();
218 : close( m_nSocket );
219 : m_nSocket = 0;
220 : }
221 : write( nFile, aAnswer.getStr(), aAnswer.getLength() );
222 : close( nFile );
223 :
224 : return 0;
225 : }
226 :
227 : #endif
228 :
229 : using namespace basebmp;
230 :
231 7541 : SvpElement::SvpElement()
232 : {
233 : #if defined WITH_SVP_LISTENING
234 : SvpElementContainer::get().registerElement( this );
235 : #endif
236 7541 : }
237 :
238 6205 : SvpElement::~SvpElement()
239 : {
240 : #if defined WITH_SVP_LISTENING
241 : SvpElementContainer::get().deregisterElement( this );
242 : #endif
243 6205 : }
244 :
245 9526 : sal_uInt32 SvpElement::getBitCountFromScanlineFormat( sal_Int32 nFormat )
246 : {
247 9526 : sal_uInt32 nBitCount = 1;
248 9526 : switch( nFormat )
249 : {
250 : case Format::ONE_BIT_MSB_GREY:
251 : case Format::ONE_BIT_LSB_GREY:
252 : case Format::ONE_BIT_MSB_PAL:
253 : case Format::ONE_BIT_LSB_PAL:
254 112 : nBitCount = 1;
255 112 : break;
256 : case Format::FOUR_BIT_MSB_GREY:
257 : case Format::FOUR_BIT_LSB_GREY:
258 : case Format::FOUR_BIT_MSB_PAL:
259 : case Format::FOUR_BIT_LSB_PAL:
260 5 : nBitCount = 4;
261 5 : break;
262 : case Format::EIGHT_BIT_PAL:
263 : case Format::EIGHT_BIT_GREY:
264 77 : nBitCount = 8;
265 77 : break;
266 : case Format::SIXTEEN_BIT_LSB_TC_MASK:
267 : case Format::SIXTEEN_BIT_MSB_TC_MASK:
268 0 : nBitCount = 16;
269 0 : break;
270 : case Format::TWENTYFOUR_BIT_TC_MASK:
271 9332 : nBitCount = 24;
272 9332 : break;
273 : case Format::THIRTYTWO_BIT_TC_MASK_BGRA:
274 : case Format::THIRTYTWO_BIT_TC_MASK_ARGB:
275 : case Format::THIRTYTWO_BIT_TC_MASK_ABGR:
276 : case Format::THIRTYTWO_BIT_TC_MASK_RGBA:
277 0 : nBitCount = 32;
278 0 : break;
279 : default:
280 : OSL_FAIL( "unsupported basebmp format" );
281 0 : break;
282 : }
283 9526 : return nBitCount;
284 : }
285 :
286 :
287 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|