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