1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_extensions.hxx" 26 #include <scanner.hxx> 27 #include <sanedlg.hxx> 28 #include <vos/thread.hxx> 29 #include <tools/list.hxx> 30 #include <boost/shared_ptr.hpp> 31 32 #if OSL_DEBUG_LEVEL > 1 33 #include <stdio.h> 34 #endif 35 36 BitmapTransporter::BitmapTransporter() 37 { 38 #if OSL_DEBUG_LEVEL > 1 39 fprintf( stderr, "BitmapTransporter\n" ); 40 #endif 41 } 42 43 BitmapTransporter::~BitmapTransporter() 44 { 45 #if OSL_DEBUG_LEVEL > 1 46 fprintf( stderr, "~BitmapTransporter\n" ); 47 #endif 48 } 49 50 // ----------------------------------------------------------------------------- 51 52 ANY SAL_CALL BitmapTransporter::queryInterface( const Type& rType ) throw( RuntimeException ) 53 { 54 const ANY aRet( cppu::queryInterface( rType, static_cast< AWT::XBitmap* >( this ) ) ); 55 56 return( aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ) ); 57 } 58 59 // ----------------------------------------------------------------------------- 60 61 AWT::Size BitmapTransporter::getSize() throw() 62 { 63 vos::OGuard aGuard( m_aProtector ); 64 int nPreviousPos = m_aStream.Tell(); 65 AWT::Size aRet; 66 67 // ensure that there is at least a header 68 m_aStream.Seek( STREAM_SEEK_TO_END ); 69 int nLen = m_aStream.Tell(); 70 if( nLen > 15 ) 71 { 72 m_aStream.Seek( 4 ); 73 m_aStream >> aRet.Width >> aRet.Height; 74 } 75 else 76 aRet.Width = aRet.Height = 0; 77 78 m_aStream.Seek( nPreviousPos ); 79 80 return aRet; 81 } 82 83 // ----------------------------------------------------------------------------- 84 85 SEQ( sal_Int8 ) BitmapTransporter::getDIB() throw() 86 { 87 vos::OGuard aGuard( m_aProtector ); 88 int nPreviousPos = m_aStream.Tell(); 89 90 // create return value 91 m_aStream.Seek( STREAM_SEEK_TO_END ); 92 int nBytes = m_aStream.Tell(); 93 m_aStream.Seek( 0 ); 94 95 SEQ( sal_Int8 ) aValue( nBytes ); 96 m_aStream.Read( aValue.getArray(), nBytes ); 97 m_aStream.Seek( nPreviousPos ); 98 99 return aValue; 100 } 101 102 // -------------- 103 // - SaneHolder - 104 // -------------- 105 106 struct SaneHolder 107 { 108 Sane m_aSane; 109 REF( AWT::XBitmap ) m_xBitmap; 110 vos::OMutex m_aProtector; 111 ScanError m_nError; 112 bool m_bBusy; 113 114 SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {} 115 }; 116 117 namespace 118 { 119 typedef std::vector< boost::shared_ptr<SaneHolder> > sanevec; 120 class allSanes 121 { 122 private: 123 int mnRefCount; 124 public: 125 sanevec m_aSanes; 126 allSanes() : mnRefCount(0) {} 127 void acquire(); 128 void release(); 129 }; 130 131 void allSanes::acquire() 132 { 133 ++mnRefCount; 134 } 135 136 void allSanes::release() 137 { 138 // was unused, now because of i99835: "Scanning interface not SANE API 139 // compliant" destroy all SaneHolder to get Sane Dtor called 140 --mnRefCount; 141 if (!mnRefCount) 142 m_aSanes.clear(); 143 } 144 145 struct theSaneProtector : public rtl::Static<vos::OMutex, theSaneProtector> {}; 146 struct theSanes : public rtl::Static<allSanes, theSanes> {}; 147 } 148 149 // ----------------- 150 // - ScannerThread - 151 // ----------------- 152 153 class ScannerThread : public vos::OThread 154 { 155 boost::shared_ptr<SaneHolder> m_pHolder; 156 REF( com::sun::star::lang::XEventListener ) m_xListener; 157 ScannerManager* m_pManager; // just for the disposing call 158 159 public: 160 virtual void run(); 161 virtual void onTerminated() { delete this; } 162 public: 163 ScannerThread( boost::shared_ptr<SaneHolder> pHolder, 164 const REF( com::sun::star::lang::XEventListener )& listener, 165 ScannerManager* pManager ); 166 virtual ~ScannerThread(); 167 }; 168 169 // ----------------------------------------------------------------------------- 170 171 ScannerThread::ScannerThread( 172 boost::shared_ptr<SaneHolder> pHolder, 173 const REF( com::sun::star::lang::XEventListener )& listener, 174 ScannerManager* pManager ) 175 : m_pHolder( pHolder ), m_xListener( listener ), m_pManager( pManager ) 176 { 177 #if OSL_DEBUG_LEVEL > 1 178 fprintf( stderr, "ScannerThread\n" ); 179 #endif 180 } 181 182 ScannerThread::~ScannerThread() 183 { 184 #if OSL_DEBUG_LEVEL > 1 185 fprintf( stderr, "~ScannerThread\n" ); 186 #endif 187 } 188 189 void ScannerThread::run() 190 { 191 vos::OGuard aGuard( m_pHolder->m_aProtector ); 192 BitmapTransporter* pTransporter = new BitmapTransporter; 193 REF( XInterface ) aIf( static_cast< OWeakObject* >( pTransporter ) ); 194 195 m_pHolder->m_xBitmap = REF( AWT::XBitmap )( aIf, UNO_QUERY ); 196 197 m_pHolder->m_bBusy = true; 198 if( m_pHolder->m_aSane.IsOpen() ) 199 { 200 int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" ); 201 if( nOption != -1 ) 202 m_pHolder->m_aSane.SetOptionValue( nOption, (sal_Bool)sal_False ); 203 204 m_pHolder->m_nError = 205 m_pHolder->m_aSane.Start( *pTransporter ) ? 206 ScanError_ScanErrorNone : ScanError_ScanCanceled; 207 } 208 else 209 m_pHolder->m_nError = ScanError_ScannerNotAvailable; 210 211 212 REF( XInterface ) xXInterface( static_cast< OWeakObject* >( m_pManager ) ); 213 m_xListener->disposing( com::sun::star::lang::EventObject(xXInterface) ); 214 m_pHolder->m_bBusy = false; 215 } 216 217 // ------------------ 218 // - ScannerManager - 219 // ------------------ 220 221 void ScannerManager::AcquireData() 222 { 223 vos::OGuard aGuard( theSaneProtector::get() ); 224 theSanes::get().acquire(); 225 } 226 227 void ScannerManager::ReleaseData() 228 { 229 vos::OGuard aGuard( theSaneProtector::get() ); 230 theSanes::get().release(); 231 } 232 233 // ----------------------------------------------------------------------------- 234 235 AWT::Size ScannerManager::getSize() throw() 236 { 237 AWT::Size aRet; 238 aRet.Width = aRet.Height = 0; 239 return aRet; 240 } 241 242 // ----------------------------------------------------------------------------- 243 244 SEQ( sal_Int8 ) ScannerManager::getDIB() throw() 245 { 246 return SEQ( sal_Int8 )(); 247 } 248 249 // ----------------------------------------------------------------------------- 250 251 SEQ( ScannerContext ) ScannerManager::getAvailableScanners() throw() 252 { 253 vos::OGuard aGuard( theSaneProtector::get() ); 254 sanevec &rSanes = theSanes::get().m_aSanes; 255 256 if( rSanes.empty() ) 257 { 258 boost::shared_ptr<SaneHolder> pSaneHolder(new SaneHolder); 259 if( Sane::IsSane() ) 260 rSanes.push_back( pSaneHolder ); 261 } 262 263 if( Sane::IsSane() ) 264 { 265 SEQ( ScannerContext ) aRet(1); 266 aRet.getArray()[0].ScannerName = ::rtl::OUString::createFromAscii( "SANE" ); 267 aRet.getArray()[0].InternalData = 0; 268 return aRet; 269 } 270 271 return SEQ( ScannerContext )(); 272 } 273 274 // ----------------------------------------------------------------------------- 275 276 sal_Bool ScannerManager::configureScanner( ScannerContext& scanner_context ) throw( ScannerException ) 277 { 278 vos::OGuard aGuard( theSaneProtector::get() ); 279 sanevec &rSanes = theSanes::get().m_aSanes; 280 281 #if OSL_DEBUG_LEVEL > 1 282 fprintf( stderr, "ScannerManager::configureScanner\n" ); 283 #endif 284 285 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) 286 throw ScannerException( 287 ::rtl::OUString::createFromAscii( "Scanner does not exist" ), 288 REF( XScannerManager )( this ), 289 ScanError_InvalidContext 290 ); 291 292 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; 293 if( pHolder->m_bBusy ) 294 throw ScannerException( 295 ::rtl::OUString::createFromAscii( "Scanner is busy" ), 296 REF( XScannerManager )( this ), 297 ScanError_ScanInProgress 298 ); 299 300 pHolder->m_bBusy = true; 301 SaneDlg aDlg( NULL, pHolder->m_aSane ); 302 sal_Bool bRet = (sal_Bool)aDlg.Execute(); 303 pHolder->m_bBusy = false; 304 305 return bRet; 306 } 307 308 // ----------------------------------------------------------------------------- 309 310 void ScannerManager::startScan( const ScannerContext& scanner_context, 311 const REF( com::sun::star::lang::XEventListener )& listener ) throw( ScannerException ) 312 { 313 vos::OGuard aGuard( theSaneProtector::get() ); 314 sanevec &rSanes = theSanes::get().m_aSanes; 315 316 #if OSL_DEBUG_LEVEL > 1 317 fprintf( stderr, "ScannerManager::startScan\n" ); 318 #endif 319 320 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) 321 throw ScannerException( 322 ::rtl::OUString::createFromAscii( "Scanner does not exist" ), 323 REF( XScannerManager )( this ), 324 ScanError_InvalidContext 325 ); 326 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; 327 if( pHolder->m_bBusy ) 328 throw ScannerException( 329 ::rtl::OUString::createFromAscii( "Scanner is busy" ), 330 REF( XScannerManager )( this ), 331 ScanError_ScanInProgress 332 ); 333 pHolder->m_bBusy = true; 334 335 ScannerThread* pThread = new ScannerThread( pHolder, listener, this ); 336 pThread->create(); 337 } 338 339 // ----------------------------------------------------------------------------- 340 341 ScanError ScannerManager::getError( const ScannerContext& scanner_context ) throw( ScannerException ) 342 { 343 vos::OGuard aGuard( theSaneProtector::get() ); 344 sanevec &rSanes = theSanes::get().m_aSanes; 345 346 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) 347 throw ScannerException( 348 ::rtl::OUString::createFromAscii( "Scanner does not exist" ), 349 REF( XScannerManager )( this ), 350 ScanError_InvalidContext 351 ); 352 353 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; 354 355 return pHolder->m_nError; 356 } 357 358 // ----------------------------------------------------------------------------- 359 360 REF( AWT::XBitmap ) ScannerManager::getBitmap( const ScannerContext& scanner_context ) throw( ScannerException ) 361 { 362 vos::OGuard aGuard( theSaneProtector::get() ); 363 sanevec &rSanes = theSanes::get().m_aSanes; 364 365 if( scanner_context.InternalData < 0 || (sal_uLong)scanner_context.InternalData >= rSanes.size() ) 366 throw ScannerException( 367 ::rtl::OUString::createFromAscii( "Scanner does not exist" ), 368 REF( XScannerManager )( this ), 369 ScanError_InvalidContext 370 ); 371 boost::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData]; 372 373 vos::OGuard aProtGuard( pHolder->m_aProtector ); 374 375 REF( AWT::XBitmap ) xRet( pHolder->m_xBitmap ); 376 pHolder->m_xBitmap = REF( AWT::XBitmap )(); 377 378 return xRet; 379 } 380