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