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