|  | /************************************************************** | 
|  | * | 
|  | * Licensed to the Apache Software Foundation (ASF) under one | 
|  | * or more contributor license agreements.  See the NOTICE file | 
|  | * distributed with this work for additional information | 
|  | * regarding copyright ownership.  The ASF licenses this file | 
|  | * to you under the Apache License, Version 2.0 (the | 
|  | * "License"); you may not use this file except in compliance | 
|  | * with the License.  You may obtain a copy of the License at | 
|  | * | 
|  | *   http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, | 
|  | * software distributed under the License is distributed on an | 
|  | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
|  | * KIND, either express or implied.  See the License for the | 
|  | * specific language governing permissions and limitations | 
|  | * under the License. | 
|  | * | 
|  | *************************************************************/ | 
|  |  | 
|  |  | 
|  |  | 
|  | // MARKER(update_precomp.py): autogen include statement, do not remove | 
|  | #include "precompiled_extensions.hxx" | 
|  | #include <scanner.hxx> | 
|  | #include <sanedlg.hxx> | 
|  | #include <vos/thread.hxx> | 
|  | #include <tools/list.hxx> | 
|  | #include <boost/shared_ptr.hpp> | 
|  |  | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | #include <stdio.h> | 
|  | #endif | 
|  |  | 
|  | BitmapTransporter::BitmapTransporter() | 
|  | { | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "BitmapTransporter\n" ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | BitmapTransporter::~BitmapTransporter() | 
|  | { | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "~BitmapTransporter\n" ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | ANY SAL_CALL BitmapTransporter::queryInterface( const Type& rType ) throw( RuntimeException ) | 
|  | { | 
|  | const ANY aRet( cppu::queryInterface( rType, static_cast< AWT::XBitmap* >( this ) ) ); | 
|  |  | 
|  | return( aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ) ); | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | AWT::Size BitmapTransporter::getSize() throw() | 
|  | { | 
|  | vos::OGuard	aGuard( m_aProtector ); | 
|  | int			nPreviousPos = m_aStream.Tell(); | 
|  | AWT::Size	aRet; | 
|  |  | 
|  | // ensure that there is at least a header | 
|  | m_aStream.Seek( STREAM_SEEK_TO_END ); | 
|  | int nLen = m_aStream.Tell(); | 
|  | if( nLen > 15 ) | 
|  | { | 
|  | m_aStream.Seek( 4 ); | 
|  | m_aStream >> aRet.Width >> aRet.Height; | 
|  | } | 
|  | else | 
|  | aRet.Width = aRet.Height = 0; | 
|  |  | 
|  | m_aStream.Seek( nPreviousPos ); | 
|  |  | 
|  | return aRet; | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | SEQ( sal_Int8 ) BitmapTransporter::getDIB() throw() | 
|  | { | 
|  | vos::OGuard aGuard( m_aProtector ); | 
|  | int			nPreviousPos = m_aStream.Tell(); | 
|  |  | 
|  | // create return value | 
|  | m_aStream.Seek( STREAM_SEEK_TO_END ); | 
|  | int nBytes = m_aStream.Tell(); | 
|  | m_aStream.Seek( 0 ); | 
|  |  | 
|  | SEQ( sal_Int8 ) aValue( nBytes ); | 
|  | m_aStream.Read( aValue.getArray(), nBytes ); | 
|  | m_aStream.Seek( nPreviousPos ); | 
|  |  | 
|  | return aValue; | 
|  | } | 
|  |  | 
|  | // -------------- | 
|  | // - SaneHolder - | 
|  | // -------------- | 
|  |  | 
|  | struct SaneHolder | 
|  | { | 
|  | Sane				m_aSane; | 
|  | REF( AWT::XBitmap )	m_xBitmap; | 
|  | vos::OMutex			m_aProtector; | 
|  | ScanError			m_nError; | 
|  | bool				m_bBusy; | 
|  |  | 
|  | SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {} | 
|  | }; | 
|  |  | 
|  | namespace | 
|  | { | 
|  | typedef std::vector< boost::shared_ptr<SaneHolder> > sanevec; | 
|  | class allSanes | 
|  | { | 
|  | private: | 
|  | int mnRefCount; | 
|  | public: | 
|  | sanevec m_aSanes; | 
|  | allSanes() : mnRefCount(0) {} | 
|  | void acquire(); | 
|  | void release(); | 
|  | }; | 
|  |  | 
|  | void allSanes::acquire() | 
|  | { | 
|  | ++mnRefCount; | 
|  | } | 
|  |  | 
|  | void allSanes::release() | 
|  | { | 
|  | // was unused, now because of i99835: "Scanning interface not SANE API | 
|  | // compliant" destroy all SaneHolder to get Sane Dtor called | 
|  | --mnRefCount; | 
|  | if (!mnRefCount) | 
|  | m_aSanes.clear(); | 
|  | } | 
|  |  | 
|  | struct theSaneProtector : public rtl::Static<vos::OMutex, theSaneProtector> {}; | 
|  | struct theSanes : public rtl::Static<allSanes, theSanes> {}; | 
|  | } | 
|  |  | 
|  | // ----------------- | 
|  | // - ScannerThread - | 
|  | // ----------------- | 
|  |  | 
|  | class ScannerThread : public vos::OThread | 
|  | { | 
|  | boost::shared_ptr<SaneHolder>				m_pHolder; | 
|  | REF( com::sun::star::lang::XEventListener )	m_xListener; | 
|  | ScannerManager*								m_pManager; // just for the disposing call | 
|  |  | 
|  | public: | 
|  | virtual void run(); | 
|  | virtual void onTerminated() { delete this; } | 
|  | public: | 
|  | ScannerThread( boost::shared_ptr<SaneHolder> pHolder, | 
|  | const REF( com::sun::star::lang::XEventListener )& listener, | 
|  | ScannerManager* pManager ); | 
|  | virtual ~ScannerThread(); | 
|  | }; | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | ScannerThread::ScannerThread( | 
|  | boost::shared_ptr<SaneHolder> pHolder, | 
|  | const REF( com::sun::star::lang::XEventListener )& listener, | 
|  | ScannerManager* pManager ) | 
|  | : m_pHolder( pHolder ), m_xListener( listener ), m_pManager( pManager ) | 
|  | { | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "ScannerThread\n" ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | ScannerThread::~ScannerThread() | 
|  | { | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "~ScannerThread\n" ); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void ScannerThread::run() | 
|  | { | 
|  | vos::OGuard			aGuard( m_pHolder->m_aProtector ); | 
|  | BitmapTransporter*	pTransporter = new BitmapTransporter; | 
|  | REF( XInterface )	aIf( static_cast< OWeakObject* >( pTransporter ) ); | 
|  |  | 
|  | m_pHolder->m_xBitmap = REF( AWT::XBitmap )( aIf, UNO_QUERY ); | 
|  |  | 
|  | m_pHolder->m_bBusy = true; | 
|  | if( m_pHolder->m_aSane.IsOpen() ) | 
|  | { | 
|  | int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" ); | 
|  | if( nOption != -1 ) | 
|  | m_pHolder->m_aSane.SetOptionValue( nOption, (sal_Bool)sal_False ); | 
|  |  | 
|  | m_pHolder->m_nError = | 
|  | m_pHolder->m_aSane.Start( *pTransporter ) ? | 
|  | ScanError_ScanErrorNone : ScanError_ScanCanceled; | 
|  | } | 
|  | else | 
|  | m_pHolder->m_nError = ScanError_ScannerNotAvailable; | 
|  |  | 
|  |  | 
|  | REF( XInterface ) xXInterface( static_cast< OWeakObject* >( m_pManager ) ); | 
|  | m_xListener->disposing( com::sun::star::lang::EventObject(xXInterface) ); | 
|  | m_pHolder->m_bBusy = false; | 
|  | } | 
|  |  | 
|  | // ------------------ | 
|  | // - ScannerManager - | 
|  | // ------------------ | 
|  |  | 
|  | void ScannerManager::AcquireData() | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | theSanes::get().acquire(); | 
|  | } | 
|  |  | 
|  | void ScannerManager::ReleaseData() | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | theSanes::get().release(); | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | AWT::Size ScannerManager::getSize() throw() | 
|  | { | 
|  | AWT::Size aRet; | 
|  | aRet.Width = aRet.Height = 0; | 
|  | return aRet; | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | SEQ( sal_Int8 ) ScannerManager::getDIB() throw() | 
|  | { | 
|  | return SEQ( sal_Int8 )(); | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | SEQ( ScannerContext ) ScannerManager::getAvailableScanners() throw() | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | sanevec &rSanes = theSanes::get().m_aSanes; | 
|  |  | 
|  | if( rSanes.empty() ) | 
|  | { | 
|  | boost::shared_ptr<SaneHolder> pSaneHolder(new SaneHolder); | 
|  | if( Sane::IsSane() ) | 
|  | rSanes.push_back( pSaneHolder ); | 
|  | } | 
|  |  | 
|  | if( Sane::IsSane() ) | 
|  | { | 
|  | SEQ( ScannerContext ) aRet(1); | 
|  | aRet.getArray()[0].ScannerName		= ::rtl::OUString::createFromAscii( "SANE" ); | 
|  | aRet.getArray()[0].InternalData		= 0; | 
|  | return aRet; | 
|  | } | 
|  |  | 
|  | return SEQ( ScannerContext )(); | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | sal_Bool ScannerManager::configureScanner( ScannerContext& scanner_context ) throw( ScannerException ) | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | sanevec &rSanes = theSanes::get().m_aSanes; | 
|  |  | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "ScannerManager::configureScanner\n" ); | 
|  | #endif | 
|  |  | 
|  | if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner does not exist" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_InvalidContext | 
|  | ); | 
|  |  | 
|  | boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; | 
|  | if( pHolder->m_bBusy ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner is busy" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_ScanInProgress | 
|  | ); | 
|  |  | 
|  | pHolder->m_bBusy = true; | 
|  | SaneDlg aDlg( NULL, pHolder->m_aSane ); | 
|  | sal_Bool bRet = (sal_Bool)aDlg.Execute(); | 
|  | pHolder->m_bBusy = false; | 
|  |  | 
|  | return bRet; | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | void ScannerManager::startScan( const ScannerContext& scanner_context, | 
|  | const REF( com::sun::star::lang::XEventListener )& listener ) throw( ScannerException ) | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | sanevec &rSanes = theSanes::get().m_aSanes; | 
|  |  | 
|  | #if OSL_DEBUG_LEVEL > 1 | 
|  | fprintf( stderr, "ScannerManager::startScan\n" ); | 
|  | #endif | 
|  |  | 
|  | if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner does not exist" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_InvalidContext | 
|  | ); | 
|  | boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; | 
|  | if( pHolder->m_bBusy ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner is busy" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_ScanInProgress | 
|  | ); | 
|  | pHolder->m_bBusy = true; | 
|  |  | 
|  | ScannerThread* pThread = new ScannerThread( pHolder, listener, this ); | 
|  | pThread->create(); | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | ScanError ScannerManager::getError( const ScannerContext& scanner_context ) throw( ScannerException ) | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | sanevec &rSanes = theSanes::get().m_aSanes; | 
|  |  | 
|  | if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner does not exist" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_InvalidContext | 
|  | ); | 
|  |  | 
|  | boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; | 
|  |  | 
|  | return pHolder->m_nError; | 
|  | } | 
|  |  | 
|  | // ----------------------------------------------------------------------------- | 
|  |  | 
|  | REF( AWT::XBitmap ) ScannerManager::getBitmap( const ScannerContext& scanner_context ) throw( ScannerException ) | 
|  | { | 
|  | vos::OGuard aGuard( theSaneProtector::get() ); | 
|  | sanevec &rSanes = theSanes::get().m_aSanes; | 
|  |  | 
|  | if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) | 
|  | throw ScannerException( | 
|  | ::rtl::OUString::createFromAscii( "Scanner does not exist" ), | 
|  | REF( XScannerManager )( this ), | 
|  | ScanError_InvalidContext | 
|  | ); | 
|  | boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; | 
|  |  | 
|  | vos::OGuard aProtGuard( pHolder->m_aProtector ); | 
|  |  | 
|  | REF( AWT::XBitmap ) xRet( pHolder->m_xBitmap ); | 
|  | pHolder->m_xBitmap = REF( AWT::XBitmap )(); | 
|  |  | 
|  | return xRet; | 
|  | } |