bump product version to 4.1.6.2
[LibreOffice.git] / extensions / source / scanner / scanunx.cxx
blobd6d7615d93cc040bd582a8561d07af8f8dc8279e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scanner.hxx>
21 #include <sanedlg.hxx>
22 #include <osl/thread.hxx>
23 #include <boost/shared_ptr.hpp>
25 #if OSL_DEBUG_LEVEL > 1
26 #include <stdio.h>
27 #endif
29 BitmapTransporter::BitmapTransporter()
31 #if OSL_DEBUG_LEVEL > 1
32 fprintf( stderr, "BitmapTransporter\n" );
33 #endif
36 BitmapTransporter::~BitmapTransporter()
38 #if OSL_DEBUG_LEVEL > 1
39 fprintf( stderr, "~BitmapTransporter\n" );
40 #endif
43 // -----------------------------------------------------------------------------
45 Any SAL_CALL BitmapTransporter::queryInterface( const Type& rType ) throw( RuntimeException )
47 const Any aRet( cppu::queryInterface( rType, static_cast< css::awt::XBitmap* >( this ) ) );
49 return( aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ) );
52 // -----------------------------------------------------------------------------
54 css::awt::Size BitmapTransporter::getSize() throw()
56 osl::MutexGuard aGuard( m_aProtector );
57 int nPreviousPos = m_aStream.Tell();
58 css::awt::Size aRet;
60 // ensure that there is at least a header
61 m_aStream.Seek( STREAM_SEEK_TO_END );
62 int nLen = m_aStream.Tell();
63 if( nLen > 15 )
65 m_aStream.Seek( 4 );
66 m_aStream >> aRet.Width >> aRet.Height;
68 else
69 aRet.Width = aRet.Height = 0;
71 m_aStream.Seek( nPreviousPos );
73 return aRet;
76 // -----------------------------------------------------------------------------
78 Sequence< sal_Int8 > BitmapTransporter::getDIB() throw()
80 osl::MutexGuard aGuard( m_aProtector );
81 int nPreviousPos = m_aStream.Tell();
83 // create return value
84 m_aStream.Seek( STREAM_SEEK_TO_END );
85 int nBytes = m_aStream.Tell();
86 m_aStream.Seek( 0 );
88 Sequence< sal_Int8 > aValue( nBytes );
89 m_aStream.Read( aValue.getArray(), nBytes );
90 m_aStream.Seek( nPreviousPos );
92 return aValue;
95 // --------------
96 // - SaneHolder -
97 // --------------
99 struct SaneHolder
101 Sane m_aSane;
102 Reference< css::awt::XBitmap > m_xBitmap;
103 osl::Mutex m_aProtector;
104 ScanError m_nError;
105 bool m_bBusy;
107 SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {}
110 namespace
112 typedef std::vector< boost::shared_ptr<SaneHolder> > sanevec;
113 class allSanes
115 private:
116 int mnRefCount;
117 public:
118 sanevec m_aSanes;
119 allSanes() : mnRefCount(0) {}
120 void acquire();
121 void release();
124 void allSanes::acquire()
126 ++mnRefCount;
129 void allSanes::release()
131 // was unused, now because of i99835: "Scanning interface not SANE API
132 // compliant" destroy all SaneHolder to get Sane Dtor called
133 --mnRefCount;
134 if (!mnRefCount)
135 m_aSanes.clear();
138 struct theSaneProtector : public rtl::Static<osl::Mutex, theSaneProtector> {};
139 struct theSanes : public rtl::Static<allSanes, theSanes> {};
142 // -----------------
143 // - ScannerThread -
144 // -----------------
146 class ScannerThread : public osl::Thread
148 boost::shared_ptr<SaneHolder> m_pHolder;
149 Reference< com::sun::star::lang::XEventListener > m_xListener;
150 ScannerManager* m_pManager; // just for the disposing call
152 public:
153 virtual void run();
154 virtual void onTerminated() { delete this; }
155 public:
156 ScannerThread( boost::shared_ptr<SaneHolder> pHolder,
157 const Reference< com::sun::star::lang::XEventListener >& listener,
158 ScannerManager* pManager );
159 virtual ~ScannerThread();
162 // -----------------------------------------------------------------------------
164 ScannerThread::ScannerThread(
165 boost::shared_ptr<SaneHolder> pHolder,
166 const Reference< com::sun::star::lang::XEventListener >& listener,
167 ScannerManager* pManager )
168 : m_pHolder( pHolder ), m_xListener( listener ), m_pManager( pManager )
170 #if OSL_DEBUG_LEVEL > 1
171 fprintf( stderr, "ScannerThread\n" );
172 #endif
175 ScannerThread::~ScannerThread()
177 #if OSL_DEBUG_LEVEL > 1
178 fprintf( stderr, "~ScannerThread\n" );
179 #endif
182 void ScannerThread::run()
184 osl::MutexGuard aGuard( m_pHolder->m_aProtector );
185 BitmapTransporter* pTransporter = new BitmapTransporter;
186 Reference< XInterface > aIf( static_cast< OWeakObject* >( pTransporter ) );
188 m_pHolder->m_xBitmap = Reference< css::awt::XBitmap >( aIf, UNO_QUERY );
190 m_pHolder->m_bBusy = true;
191 if( m_pHolder->m_aSane.IsOpen() )
193 int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" );
194 if( nOption != -1 )
195 m_pHolder->m_aSane.SetOptionValue( nOption, (sal_Bool)sal_False );
197 m_pHolder->m_nError =
198 m_pHolder->m_aSane.Start( *pTransporter ) ?
199 ScanError_ScanErrorNone : ScanError_ScanCanceled;
201 else
202 m_pHolder->m_nError = ScanError_ScannerNotAvailable;
205 Reference< XInterface > xXInterface( static_cast< OWeakObject* >( m_pManager ) );
206 m_xListener->disposing( com::sun::star::lang::EventObject(xXInterface) );
207 m_pHolder->m_bBusy = false;
210 // ------------------
211 // - ScannerManager -
212 // ------------------
214 void ScannerManager::AcquireData()
216 osl::MutexGuard aGuard( theSaneProtector::get() );
217 theSanes::get().acquire();
220 void ScannerManager::ReleaseData()
222 osl::MutexGuard aGuard( theSaneProtector::get() );
223 theSanes::get().release();
226 // -----------------------------------------------------------------------------
228 css::awt::Size ScannerManager::getSize() throw()
230 css::awt::Size aRet;
231 aRet.Width = aRet.Height = 0;
232 return aRet;
235 // -----------------------------------------------------------------------------
237 Sequence< sal_Int8 > ScannerManager::getDIB() throw()
239 return Sequence< sal_Int8 >();
242 // -----------------------------------------------------------------------------
244 Sequence< ScannerContext > ScannerManager::getAvailableScanners() throw()
246 osl::MutexGuard aGuard( theSaneProtector::get() );
247 sanevec &rSanes = theSanes::get().m_aSanes;
249 if( rSanes.empty() )
251 boost::shared_ptr<SaneHolder> pSaneHolder(new SaneHolder);
252 if( Sane::IsSane() )
253 rSanes.push_back( pSaneHolder );
256 if( Sane::IsSane() )
258 Sequence< ScannerContext > aRet(1);
259 aRet.getArray()[0].ScannerName = OUString("SANE");
260 aRet.getArray()[0].InternalData = 0;
261 return aRet;
264 return Sequence< ScannerContext >();
267 // -----------------------------------------------------------------------------
269 sal_Bool ScannerManager::configureScannerAndScan( ScannerContext& scanner_context,
270 const Reference< com::sun::star::lang::XEventListener >& listener ) throw( ScannerException )
272 bool bRet;
273 bool bScan;
275 osl::MutexGuard aGuard( theSaneProtector::get() );
276 sanevec &rSanes = theSanes::get().m_aSanes;
278 #if OSL_DEBUG_LEVEL > 1
279 fprintf( stderr, "ScannerManager::configureScanner\n" );
280 #endif
282 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
283 throw ScannerException(
284 OUString("Scanner does not exist"),
285 Reference< XScannerManager >( this ),
286 ScanError_InvalidContext
289 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
290 if( pHolder->m_bBusy )
291 throw ScannerException(
292 OUString("Scanner is busy"),
293 Reference< XScannerManager >( this ),
294 ScanError_ScanInProgress
297 pHolder->m_bBusy = true;
298 SaneDlg aDlg( NULL, pHolder->m_aSane, listener.is() );
299 bRet = aDlg.Execute();
300 bScan = aDlg.getDoScan();
301 pHolder->m_bBusy = false;
303 if ( bScan )
304 startScan( scanner_context, listener );
306 return bRet;
309 // -----------------------------------------------------------------------------
311 void ScannerManager::startScan( const ScannerContext& scanner_context,
312 const Reference< com::sun::star::lang::XEventListener >& listener ) throw( ScannerException )
314 osl::MutexGuard aGuard( theSaneProtector::get() );
315 sanevec &rSanes = theSanes::get().m_aSanes;
317 #if OSL_DEBUG_LEVEL > 1
318 fprintf( stderr, "ScannerManager::startScan\n" );
319 #endif
321 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
322 throw ScannerException(
323 OUString("Scanner does not exist"),
324 Reference< XScannerManager >( this ),
325 ScanError_InvalidContext
327 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
328 if( pHolder->m_bBusy )
329 throw ScannerException(
330 OUString("Scanner is busy"),
331 Reference< XScannerManager >( this ),
332 ScanError_ScanInProgress
334 pHolder->m_bBusy = true;
336 ScannerThread* pThread = new ScannerThread( pHolder, listener, this );
337 pThread->create();
340 // -----------------------------------------------------------------------------
342 ScanError ScannerManager::getError( const ScannerContext& scanner_context ) throw( ScannerException )
344 osl::MutexGuard aGuard( theSaneProtector::get() );
345 sanevec &rSanes = theSanes::get().m_aSanes;
347 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
348 throw ScannerException(
349 OUString("Scanner does not exist"),
350 Reference< XScannerManager >( this ),
351 ScanError_InvalidContext
354 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
356 return pHolder->m_nError;
359 // -----------------------------------------------------------------------------
361 Reference< css::awt::XBitmap > ScannerManager::getBitmap( const ScannerContext& scanner_context ) throw( ScannerException )
363 osl::MutexGuard aGuard( theSaneProtector::get() );
364 sanevec &rSanes = theSanes::get().m_aSanes;
366 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() )
367 throw ScannerException(
368 OUString("Scanner does not exist"),
369 Reference< XScannerManager >( this ),
370 ScanError_InvalidContext
372 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
374 osl::MutexGuard aProtGuard( pHolder->m_aProtector );
376 Reference< css::awt::XBitmap > xRet( pHolder->m_xBitmap );
377 pHolder->m_xBitmap = Reference< css::awt::XBitmap >();
379 return xRet;
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */