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