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 <scanner.hxx>
21 : #include <sanedlg.hxx>
22 : #include <osl/thread.hxx>
23 : #include <boost/shared_ptr.hpp>
24 : #include <boost/shared_ptr.hpp>
25 :
26 : #if OSL_DEBUG_LEVEL > 1
27 : #include <stdio.h>
28 : #endif
29 :
30 0 : BitmapTransporter::BitmapTransporter()
31 : {
32 : #if OSL_DEBUG_LEVEL > 1
33 : fprintf( stderr, "BitmapTransporter\n" );
34 : #endif
35 0 : }
36 :
37 0 : BitmapTransporter::~BitmapTransporter()
38 : {
39 : #if OSL_DEBUG_LEVEL > 1
40 : fprintf( stderr, "~BitmapTransporter\n" );
41 : #endif
42 0 : }
43 :
44 : // -----------------------------------------------------------------------------
45 :
46 0 : ANY SAL_CALL BitmapTransporter::queryInterface( const Type& rType ) throw( RuntimeException )
47 : {
48 0 : const ANY aRet( cppu::queryInterface( rType, static_cast< AWT::XBitmap* >( this ) ) );
49 :
50 0 : return( aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ) );
51 : }
52 :
53 : // -----------------------------------------------------------------------------
54 :
55 0 : AWT::Size BitmapTransporter::getSize() throw()
56 : {
57 0 : osl::MutexGuard aGuard( m_aProtector );
58 0 : int nPreviousPos = m_aStream.Tell();
59 0 : AWT::Size aRet;
60 :
61 : // ensure that there is at least a header
62 0 : m_aStream.Seek( STREAM_SEEK_TO_END );
63 0 : int nLen = m_aStream.Tell();
64 0 : if( nLen > 15 )
65 : {
66 0 : m_aStream.Seek( 4 );
67 0 : m_aStream >> aRet.Width >> aRet.Height;
68 : }
69 : else
70 0 : aRet.Width = aRet.Height = 0;
71 :
72 0 : m_aStream.Seek( nPreviousPos );
73 :
74 0 : return aRet;
75 : }
76 :
77 : // -----------------------------------------------------------------------------
78 :
79 0 : SEQ( sal_Int8 ) BitmapTransporter::getDIB() throw()
80 : {
81 0 : osl::MutexGuard aGuard( m_aProtector );
82 0 : int nPreviousPos = m_aStream.Tell();
83 :
84 : // create return value
85 0 : m_aStream.Seek( STREAM_SEEK_TO_END );
86 0 : int nBytes = m_aStream.Tell();
87 0 : m_aStream.Seek( 0 );
88 :
89 0 : SEQ( sal_Int8 ) aValue( nBytes );
90 0 : m_aStream.Read( aValue.getArray(), nBytes );
91 0 : m_aStream.Seek( nPreviousPos );
92 :
93 0 : return aValue;
94 : }
95 :
96 : // --------------
97 : // - SaneHolder -
98 : // --------------
99 :
100 0 : struct SaneHolder
101 : {
102 : Sane m_aSane;
103 : REF( AWT::XBitmap ) m_xBitmap;
104 : osl::Mutex m_aProtector;
105 : ScanError m_nError;
106 : bool m_bBusy;
107 :
108 0 : SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {}
109 : };
110 :
111 : namespace
112 : {
113 : typedef std::vector< boost::shared_ptr<SaneHolder> > sanevec;
114 0 : class allSanes
115 : {
116 : private:
117 : int mnRefCount;
118 : public:
119 : sanevec m_aSanes;
120 0 : allSanes() : mnRefCount(0) {}
121 : void acquire();
122 : void release();
123 : };
124 :
125 0 : void allSanes::acquire()
126 : {
127 0 : ++mnRefCount;
128 0 : }
129 :
130 0 : void allSanes::release()
131 : {
132 : // was unused, now because of i99835: "Scanning interface not SANE API
133 : // compliant" destroy all SaneHolder to get Sane Dtor called
134 0 : --mnRefCount;
135 0 : if (!mnRefCount)
136 0 : m_aSanes.clear();
137 0 : }
138 :
139 : struct theSaneProtector : public rtl::Static<osl::Mutex, theSaneProtector> {};
140 : struct theSanes : public rtl::Static<allSanes, theSanes> {};
141 : }
142 :
143 : // -----------------
144 : // - ScannerThread -
145 : // -----------------
146 :
147 : class ScannerThread : public osl::Thread
148 : {
149 : boost::shared_ptr<SaneHolder> m_pHolder;
150 : REF( com::sun::star::lang::XEventListener ) m_xListener;
151 : ScannerManager* m_pManager; // just for the disposing call
152 :
153 : public:
154 : virtual void run();
155 0 : virtual void onTerminated() { delete this; }
156 : public:
157 : ScannerThread( boost::shared_ptr<SaneHolder> pHolder,
158 : const REF( com::sun::star::lang::XEventListener )& listener,
159 : ScannerManager* pManager );
160 : virtual ~ScannerThread();
161 : };
162 :
163 : // -----------------------------------------------------------------------------
164 :
165 0 : ScannerThread::ScannerThread(
166 : boost::shared_ptr<SaneHolder> pHolder,
167 : const REF( com::sun::star::lang::XEventListener )& listener,
168 : ScannerManager* pManager )
169 0 : : m_pHolder( pHolder ), m_xListener( listener ), m_pManager( pManager )
170 : {
171 : #if OSL_DEBUG_LEVEL > 1
172 : fprintf( stderr, "ScannerThread\n" );
173 : #endif
174 0 : }
175 :
176 0 : ScannerThread::~ScannerThread()
177 : {
178 : #if OSL_DEBUG_LEVEL > 1
179 : fprintf( stderr, "~ScannerThread\n" );
180 : #endif
181 0 : }
182 :
183 0 : void ScannerThread::run()
184 : {
185 0 : osl::MutexGuard aGuard( m_pHolder->m_aProtector );
186 0 : BitmapTransporter* pTransporter = new BitmapTransporter;
187 0 : REF( XInterface ) aIf( static_cast< OWeakObject* >( pTransporter ) );
188 :
189 0 : m_pHolder->m_xBitmap = REF( AWT::XBitmap )( aIf, UNO_QUERY );
190 :
191 0 : m_pHolder->m_bBusy = true;
192 0 : if( m_pHolder->m_aSane.IsOpen() )
193 : {
194 0 : int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" );
195 0 : if( nOption != -1 )
196 0 : m_pHolder->m_aSane.SetOptionValue( nOption, (sal_Bool)sal_False );
197 :
198 0 : m_pHolder->m_nError =
199 0 : m_pHolder->m_aSane.Start( *pTransporter ) ?
200 0 : ScanError_ScanErrorNone : ScanError_ScanCanceled;
201 : }
202 : else
203 0 : m_pHolder->m_nError = ScanError_ScannerNotAvailable;
204 :
205 :
206 0 : REF( XInterface ) xXInterface( static_cast< OWeakObject* >( m_pManager ) );
207 0 : m_xListener->disposing( com::sun::star::lang::EventObject(xXInterface) );
208 0 : m_pHolder->m_bBusy = false;
209 0 : }
210 :
211 : // ------------------
212 : // - ScannerManager -
213 : // ------------------
214 :
215 0 : void ScannerManager::AcquireData()
216 : {
217 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
218 0 : theSanes::get().acquire();
219 0 : }
220 :
221 0 : void ScannerManager::ReleaseData()
222 : {
223 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
224 0 : theSanes::get().release();
225 0 : }
226 :
227 : // -----------------------------------------------------------------------------
228 :
229 0 : AWT::Size ScannerManager::getSize() throw()
230 : {
231 0 : AWT::Size aRet;
232 0 : aRet.Width = aRet.Height = 0;
233 0 : return aRet;
234 : }
235 :
236 : // -----------------------------------------------------------------------------
237 :
238 0 : SEQ( sal_Int8 ) ScannerManager::getDIB() throw()
239 : {
240 0 : return SEQ( sal_Int8 )();
241 : }
242 :
243 : // -----------------------------------------------------------------------------
244 :
245 0 : SEQ( ScannerContext ) ScannerManager::getAvailableScanners() throw()
246 : {
247 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
248 0 : sanevec &rSanes = theSanes::get().m_aSanes;
249 :
250 0 : if( rSanes.empty() )
251 : {
252 0 : boost::shared_ptr<SaneHolder> pSaneHolder(new SaneHolder);
253 0 : if( Sane::IsSane() )
254 0 : rSanes.push_back( pSaneHolder );
255 : }
256 :
257 0 : if( Sane::IsSane() )
258 : {
259 0 : SEQ( ScannerContext ) aRet(1);
260 0 : aRet.getArray()[0].ScannerName = ::rtl::OUString("SANE");
261 0 : aRet.getArray()[0].InternalData = 0;
262 0 : return aRet;
263 : }
264 :
265 0 : return SEQ( ScannerContext )();
266 : }
267 :
268 : // -----------------------------------------------------------------------------
269 :
270 0 : sal_Bool ScannerManager::configureScannerAndScan( ScannerContext& scanner_context,
271 : const REF( com::sun::star::lang::XEventListener )& listener ) throw( ScannerException )
272 : {
273 : bool bRet;
274 : bool bScan;
275 : {
276 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
277 0 : sanevec &rSanes = theSanes::get().m_aSanes;
278 :
279 : #if OSL_DEBUG_LEVEL > 1
280 : fprintf( stderr, "ScannerManager::configureScanner\n" );
281 : #endif
282 :
283 0 : if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
284 : throw ScannerException(
285 : ::rtl::OUString("Scanner does not exist"),
286 : REF( XScannerManager )( this ),
287 : ScanError_InvalidContext
288 0 : );
289 :
290 0 : boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
291 0 : if( pHolder->m_bBusy )
292 : throw ScannerException(
293 : ::rtl::OUString("Scanner is busy"),
294 : REF( XScannerManager )( this ),
295 : ScanError_ScanInProgress
296 0 : );
297 :
298 0 : pHolder->m_bBusy = true;
299 0 : SaneDlg aDlg( NULL, pHolder->m_aSane, listener.is() );
300 0 : bRet = aDlg.Execute();
301 0 : bScan = aDlg.getDoScan();
302 0 : pHolder->m_bBusy = false;
303 : }
304 0 : if ( bScan )
305 0 : startScan( scanner_context, listener );
306 :
307 0 : return bRet;
308 : }
309 :
310 : // -----------------------------------------------------------------------------
311 :
312 0 : void ScannerManager::startScan( const ScannerContext& scanner_context,
313 : const REF( com::sun::star::lang::XEventListener )& listener ) throw( ScannerException )
314 : {
315 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
316 0 : sanevec &rSanes = theSanes::get().m_aSanes;
317 :
318 : #if OSL_DEBUG_LEVEL > 1
319 : fprintf( stderr, "ScannerManager::startScan\n" );
320 : #endif
321 :
322 0 : if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
323 : throw ScannerException(
324 : ::rtl::OUString("Scanner does not exist"),
325 : REF( XScannerManager )( this ),
326 : ScanError_InvalidContext
327 0 : );
328 0 : boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
329 0 : if( pHolder->m_bBusy )
330 : throw ScannerException(
331 : ::rtl::OUString("Scanner is busy"),
332 : REF( XScannerManager )( this ),
333 : ScanError_ScanInProgress
334 0 : );
335 0 : pHolder->m_bBusy = true;
336 :
337 0 : ScannerThread* pThread = new ScannerThread( pHolder, listener, this );
338 0 : pThread->create();
339 0 : }
340 :
341 : // -----------------------------------------------------------------------------
342 :
343 0 : ScanError ScannerManager::getError( const ScannerContext& scanner_context ) throw( ScannerException )
344 : {
345 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
346 0 : sanevec &rSanes = theSanes::get().m_aSanes;
347 :
348 0 : if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
349 : throw ScannerException(
350 : ::rtl::OUString("Scanner does not exist"),
351 : REF( XScannerManager )( this ),
352 : ScanError_InvalidContext
353 0 : );
354 :
355 0 : boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
356 :
357 0 : return pHolder->m_nError;
358 : }
359 :
360 : // -----------------------------------------------------------------------------
361 :
362 0 : REF( AWT::XBitmap ) ScannerManager::getBitmap( const ScannerContext& scanner_context ) throw( ScannerException )
363 : {
364 0 : osl::MutexGuard aGuard( theSaneProtector::get() );
365 0 : sanevec &rSanes = theSanes::get().m_aSanes;
366 :
367 0 : if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
368 : throw ScannerException(
369 : ::rtl::OUString("Scanner does not exist"),
370 : REF( XScannerManager )( this ),
371 : ScanError_InvalidContext
372 0 : );
373 0 : boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
374 :
375 0 : osl::MutexGuard aProtGuard( pHolder->m_aProtector );
376 :
377 0 : REF( AWT::XBitmap ) xRet( pHolder->m_xBitmap );
378 0 : pHolder->m_xBitmap = REF( AWT::XBitmap )();
379 :
380 0 : return xRet;
381 : }
382 :
383 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|