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