1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
29 BitmapTransporter::BitmapTransporter()
31 #if OSL_DEBUG_LEVEL > 1
32 fprintf( stderr
, "BitmapTransporter\n" );
36 BitmapTransporter::~BitmapTransporter()
38 #if OSL_DEBUG_LEVEL > 1
39 fprintf( stderr
, "~BitmapTransporter\n" );
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();
60 // ensure that there is at least a header
61 m_aStream
.Seek( STREAM_SEEK_TO_END
);
62 int nLen
= m_aStream
.Tell();
66 m_aStream
>> aRet
.Width
>> aRet
.Height
;
69 aRet
.Width
= aRet
.Height
= 0;
71 m_aStream
.Seek( nPreviousPos
);
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();
88 Sequence
< sal_Int8
> aValue( nBytes
);
89 m_aStream
.Read( aValue
.getArray(), nBytes
);
90 m_aStream
.Seek( nPreviousPos
);
102 Reference
< css::awt::XBitmap
> m_xBitmap
;
103 osl::Mutex m_aProtector
;
107 SaneHolder() : m_nError(ScanError_ScanErrorNone
), m_bBusy(false) {}
112 typedef std::vector
< boost::shared_ptr
<SaneHolder
> > sanevec
;
119 allSanes() : mnRefCount(0) {}
124 void allSanes::acquire()
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
138 struct theSaneProtector
: public rtl::Static
<osl::Mutex
, theSaneProtector
> {};
139 struct theSanes
: public rtl::Static
<allSanes
, theSanes
> {};
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
154 virtual void onTerminated() { delete this; }
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" );
175 ScannerThread::~ScannerThread()
177 #if OSL_DEBUG_LEVEL > 1
178 fprintf( stderr
, "~ScannerThread\n" );
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" );
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
;
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()
231 aRet
.Width
= aRet
.Height
= 0;
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
;
251 boost::shared_ptr
<SaneHolder
> pSaneHolder(new SaneHolder
);
253 rSanes
.push_back( pSaneHolder
);
258 Sequence
< ScannerContext
> aRet(1);
259 aRet
.getArray()[0].ScannerName
= OUString("SANE");
260 aRet
.getArray()[0].InternalData
= 0;
264 return Sequence
< ScannerContext
>();
267 // -----------------------------------------------------------------------------
269 sal_Bool
ScannerManager::configureScannerAndScan( ScannerContext
& scanner_context
,
270 const Reference
< com::sun::star::lang::XEventListener
>& listener
) throw( ScannerException
)
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" );
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;
304 startScan( scanner_context
, listener
);
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" );
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 );
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
>();
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */