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