bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / scanner / scanunx.cxx
blob3225cab44b065f0faf70426b34afc71a61fdbbd9
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 <sal/log.hxx>
24 #include <cppuhelper/queryinterface.hxx>
25 #include <memory>
28 BitmapTransporter::BitmapTransporter()
30 SAL_INFO("extensions.scanner", "BitmapTransporter");
34 BitmapTransporter::~BitmapTransporter()
36 SAL_INFO("extensions.scanner", "~BitmapTransporter");
40 css::awt::Size BitmapTransporter::getSize()
42 osl::MutexGuard aGuard( m_aProtector );
43 css::awt::Size aRet;
45 // ensure that there is at least a header
46 int nLen = m_aStream.TellEnd();
47 if( nLen > 15 )
49 int nPreviousPos = m_aStream.Tell();
50 m_aStream.Seek( 4 );
51 m_aStream.ReadInt32( aRet.Width ).ReadInt32( aRet.Height );
52 m_aStream.Seek( nPreviousPos );
54 else
55 aRet.Width = aRet.Height = 0;
58 return aRet;
62 Sequence< sal_Int8 > BitmapTransporter::getDIB()
64 osl::MutexGuard aGuard( m_aProtector );
65 int nPreviousPos = m_aStream.Tell();
67 // create return value
68 int nBytes = m_aStream.TellEnd();
69 m_aStream.Seek( 0 );
71 Sequence< sal_Int8 > aValue( nBytes );
72 m_aStream.ReadBytes( aValue.getArray(), nBytes );
73 m_aStream.Seek( nPreviousPos );
75 return aValue;
79 struct SaneHolder
81 Sane m_aSane;
82 Reference< css::awt::XBitmap > m_xBitmap;
83 osl::Mutex m_aProtector;
84 ScanError m_nError;
85 bool m_bBusy;
87 SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {}
91 namespace
93 typedef std::vector< std::shared_ptr<SaneHolder> > sanevec;
94 class allSanes
96 private:
97 int mnRefCount;
98 public:
99 sanevec m_aSanes;
100 allSanes() : mnRefCount(0) {}
101 void acquire();
102 void release();
105 void allSanes::acquire()
107 ++mnRefCount;
110 void allSanes::release()
112 // was unused, now because of i99835: "Scanning interface not SANE API
113 // compliant" destroy all SaneHolder to get Sane Dtor called
114 --mnRefCount;
115 if (!mnRefCount)
116 m_aSanes.clear();
119 struct theSaneProtector : public rtl::Static<osl::Mutex, theSaneProtector> {};
120 struct theSanes : public rtl::Static<allSanes, theSanes> {};
124 class ScannerThread : public osl::Thread
126 std::shared_ptr<SaneHolder> m_pHolder;
127 Reference< css::lang::XEventListener > m_xListener;
128 ScannerManager* m_pManager; // just for the disposing call
130 public:
131 virtual void SAL_CALL run() override;
132 virtual void SAL_CALL onTerminated() override { delete this; }
133 public:
134 ScannerThread( const std::shared_ptr<SaneHolder>& pHolder,
135 const Reference< css::lang::XEventListener >& listener,
136 ScannerManager* pManager );
137 virtual ~ScannerThread() override;
141 ScannerThread::ScannerThread(const std::shared_ptr<SaneHolder>& pHolder,
142 const Reference< css::lang::XEventListener >& listener,
143 ScannerManager* pManager)
144 : m_pHolder( pHolder ), m_xListener( listener ), m_pManager( pManager )
146 SAL_INFO("extensions.scanner", "ScannerThread");
150 ScannerThread::~ScannerThread()
152 SAL_INFO("extensions.scanner", "~ScannerThread");
156 void ScannerThread::run()
158 osl_setThreadName("ScannerThread");
160 osl::MutexGuard aGuard( m_pHolder->m_aProtector );
161 BitmapTransporter* pTransporter = new BitmapTransporter;
162 Reference< XInterface > aIf( static_cast< OWeakObject* >( pTransporter ) );
164 m_pHolder->m_xBitmap.set( aIf, UNO_QUERY );
166 m_pHolder->m_bBusy = true;
167 if( m_pHolder->m_aSane.IsOpen() )
169 int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" );
170 if( nOption != -1 )
171 m_pHolder->m_aSane.SetOptionValue( nOption, false );
173 m_pHolder->m_nError =
174 m_pHolder->m_aSane.Start( *pTransporter ) ?
175 ScanError_ScanErrorNone : ScanError_ScanCanceled;
177 else
178 m_pHolder->m_nError = ScanError_ScannerNotAvailable;
181 Reference< XInterface > xXInterface( static_cast< OWeakObject* >( m_pManager ) );
182 m_xListener->disposing( css::lang::EventObject(xXInterface) );
183 m_pHolder->m_bBusy = false;
187 void ScannerManager::AcquireData()
189 osl::MutexGuard aGuard( theSaneProtector::get() );
190 theSanes::get().acquire();
194 void ScannerManager::ReleaseData()
196 osl::MutexGuard aGuard( theSaneProtector::get() );
197 theSanes::get().release();
201 css::awt::Size ScannerManager::getSize()
203 css::awt::Size aRet;
204 aRet.Width = aRet.Height = 0;
205 return aRet;
209 Sequence< sal_Int8 > ScannerManager::getDIB()
211 return Sequence< sal_Int8 >();
215 Sequence< ScannerContext > ScannerManager::getAvailableScanners()
217 osl::MutexGuard aGuard( theSaneProtector::get() );
218 sanevec &rSanes = theSanes::get().m_aSanes;
220 if( rSanes.empty() )
222 std::shared_ptr<SaneHolder> pSaneHolder(new SaneHolder);
223 if( Sane::IsSane() )
224 rSanes.push_back( pSaneHolder );
227 if( Sane::IsSane() )
229 Sequence< ScannerContext > aRet(1);
230 aRet[0].ScannerName = "SANE";
231 aRet[0].InternalData = 0;
232 return aRet;
235 return Sequence< ScannerContext >();
239 sal_Bool ScannerManager::configureScannerAndScan( ScannerContext& scanner_context,
240 const Reference< css::lang::XEventListener >& listener )
242 bool bRet;
243 bool bScan;
245 osl::MutexGuard aGuard( theSaneProtector::get() );
246 sanevec &rSanes = theSanes::get().m_aSanes;
248 SAL_INFO("extensions.scanner", "ScannerManager::configureScanner");
250 if( scanner_context.InternalData < 0 || static_cast<sal_uLong>(scanner_context.InternalData) >= rSanes.size() )
251 throw ScannerException(
252 "Scanner does not exist",
253 Reference< XScannerManager >( this ),
254 ScanError_InvalidContext
257 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
258 if( pHolder->m_bBusy )
259 throw ScannerException(
260 "Scanner is busy",
261 Reference< XScannerManager >( this ),
262 ScanError_ScanInProgress
265 pHolder->m_bBusy = true;
266 ScopedVclPtrInstance< SaneDlg > aDlg(nullptr, pHolder->m_aSane, listener.is());
267 bRet = aDlg->Execute();
268 bScan = aDlg->getDoScan();
269 pHolder->m_bBusy = false;
271 if ( bScan )
272 startScan( scanner_context, listener );
274 return bRet;
278 void ScannerManager::startScan( const ScannerContext& scanner_context,
279 const Reference< css::lang::XEventListener >& listener )
281 osl::MutexGuard aGuard( theSaneProtector::get() );
282 sanevec &rSanes = theSanes::get().m_aSanes;
284 SAL_INFO("extensions.scanner", "ScannerManager::startScan");
286 if( scanner_context.InternalData < 0 || static_cast<sal_uLong>(scanner_context.InternalData) >= rSanes.size() )
287 throw ScannerException(
288 "Scanner does not exist",
289 Reference< XScannerManager >( this ),
290 ScanError_InvalidContext
292 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
293 if( pHolder->m_bBusy )
294 throw ScannerException(
295 "Scanner is busy",
296 Reference< XScannerManager >( this ),
297 ScanError_ScanInProgress
299 pHolder->m_bBusy = true;
301 ScannerThread* pThread = new ScannerThread( pHolder, listener, this );
302 pThread->create();
306 ScanError ScannerManager::getError( const ScannerContext& scanner_context )
308 osl::MutexGuard aGuard( theSaneProtector::get() );
309 sanevec &rSanes = theSanes::get().m_aSanes;
311 if( scanner_context.InternalData < 0 || static_cast<sal_uLong>(scanner_context.InternalData) >= rSanes.size() )
312 throw ScannerException(
313 "Scanner does not exist",
314 Reference< XScannerManager >( this ),
315 ScanError_InvalidContext
318 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
320 return pHolder->m_nError;
324 Reference< css::awt::XBitmap > ScannerManager::getBitmap( const ScannerContext& scanner_context )
326 osl::MutexGuard aGuard( theSaneProtector::get() );
327 sanevec &rSanes = theSanes::get().m_aSanes;
329 if( scanner_context.InternalData < 0 || static_cast<sal_uLong>(scanner_context.InternalData) >= rSanes.size() )
330 throw ScannerException(
331 "Scanner does not exist",
332 Reference< XScannerManager >( this ),
333 ScanError_InvalidContext
335 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
337 osl::MutexGuard aProtGuard( pHolder->m_aProtector );
339 Reference< css::awt::XBitmap > xRet( pHolder->m_xBitmap );
340 pHolder->m_xBitmap.clear();
342 return xRet;
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */