xref: /trunk/main/extensions/source/scanner/scanunx.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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