00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "precompiled_extensions.hxx"
00038 #include <cstdarg>
00039 #include <math.h>
00040 #include <osl/file.h>
00041 #include <tools/stream.hxx>
00042 #include <sane.hxx>
00043 #include <dlfcn.h>
00044 #include <stdio.h>
00045 #include <unistd.h>
00046 #include <sys/time.h>
00047 #include <sys/types.h>
00048 #include <sal/config.h>
00049
00050 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
00051 #include <stdarg.h>
00052 #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
00053 #else
00054 #define dump_state( a, b, c, d ) ;
00055 #endif
00056 inline void dbg_msg( const char* pString, ... )
00057 {
00058 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
00059 va_list ap;
00060 va_start( ap, pString );
00061 vfprintf( stderr, pString, ap );
00062 va_end( ap );
00063 #else
00064 (void)pString;
00065 #endif
00066 }
00067
00068 #define FAIL_SHUTDOWN_STATE( x, y, z ) \
00069 if( x != SANE_STATUS_GOOD ) \
00070 { \
00071 dump_state( "%s returned error %d (%s)\n", \
00072 y, x, p_strstatus( x ) ); \
00073 DeInit(); \
00074 return z; \
00075 }
00076
00077 #define FAIL_STATE( x, y, z ) \
00078 if( x != SANE_STATUS_GOOD ) \
00079 { \
00080 dump_state( "%s returned error %d (%s)\n", \
00081 y, x, p_strstatus( x ) ); \
00082 return z; \
00083 }
00084
00085 #define DUMP_STATE( x, y ) \
00086 if( x != SANE_STATUS_GOOD ) \
00087 { \
00088 dump_state( "%s returned error %d (%s)\n", \
00089 y, x, p_strstatus( x ) ); \
00090 }
00091
00092 #define CHECK_STATE( x, y ) \
00093 if( x != SANE_STATUS_GOOD ) \
00094 { \
00095 dump_state( "%s returned error %d (%s)\n", \
00096 y, x, p_strstatus( x ) ); \
00097 } \
00098 else
00099
00100 int Sane::nRefCount = 0;
00101 oslModule Sane::pSaneLib = 0;
00102 SANE_Int Sane::nVersion = 0;
00103 SANE_Device** Sane::ppDevices = 0;
00104 int Sane::nDevices = 0;
00105
00106 SANE_Status (*Sane::p_init)( SANE_Int*,
00107 SANE_Auth_Callback ) = 0;
00108 void (*Sane::p_exit)() = 0;
00109 SANE_Status (*Sane::p_get_devices)( const SANE_Device***,
00110 SANE_Bool ) = 0;
00111 SANE_Status (*Sane::p_open)( SANE_String_Const, SANE_Handle ) = 0;
00112 void (*Sane::p_close)( SANE_Handle ) = 0;
00113 const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
00114 SANE_Handle, SANE_Int ) = 0;
00115 SANE_Status (*Sane::p_control_option)( SANE_Handle, SANE_Int,
00116 SANE_Action, void*,
00117 SANE_Int* ) = 0;
00118 SANE_Status (*Sane::p_get_parameters)( SANE_Handle,
00119 SANE_Parameters* ) = 0;
00120 SANE_Status (*Sane::p_start)( SANE_Handle ) = 0;
00121 SANE_Status (*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
00122 SANE_Int* ) = 0;
00123 void (*Sane::p_cancel)( SANE_Handle ) = 0;
00124 SANE_Status (*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = 0;
00125 SANE_Status (*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = 0;
00126 const SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = 0;
00127
00128 static BOOL bSaneSymbolLoadFailed = FALSE;
00129
00130 inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname )
00131 {
00132 oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname );
00133 if( ! pFunction )
00134 {
00135 fprintf( stderr, "Could not load symbol %s\n",
00136 pSymbolname );
00137 bSaneSymbolLoadFailed = TRUE;
00138 }
00139 return pFunction;
00140 }
00141
00142 SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction,
00143 void* pData )
00144 {
00145 SANE_Status nStatus = SANE_STATUS_GOOD;
00146 SANE_Int nInfo = 0;
00147
00148 nStatus = p_control_option( maHandle, (SANE_Int)nOption,
00149 nAction, pData, &nInfo );
00150 DUMP_STATE( nStatus, "sane_control_option" );
00151 #if OSL_DEBUG_LEVEL > 1
00152 if( nStatus != SANE_STATUS_GOOD )
00153 {
00154 char* pAction = "Unknown";
00155 switch( nAction )
00156 {
00157 case SANE_ACTION_GET_VALUE:
00158 pAction = "SANE_ACTION_GET_VALUE";break;
00159 case SANE_ACTION_SET_VALUE:
00160 pAction = "SANE_ACTION_SET_VALUE";break;
00161 case SANE_ACTION_SET_AUTO:
00162 pAction = "SANE_ACTION_SET_AUTO";break;
00163 }
00164 dbg_msg( "Option: \"%s\" action: %s\n",
00165 ByteString( GetOptionName( nOption ), gsl_getSystemTextEncoding() ).GetBuffer(),
00166 pAction );
00167 }
00168 #endif
00169
00170 if( nInfo & SANE_INFO_RELOAD_OPTIONS )
00171 ReloadOptions();
00172 return nStatus;
00173 }
00174
00175 Sane::Sane() :
00176 mppOptions( 0 ),
00177 mnOptions( 0 ),
00178 mnDevice( -1 ),
00179 maHandle( 0 )
00180 {
00181 if( ! nRefCount || ! pSaneLib )
00182 Init();
00183 nRefCount++;
00184 };
00185
00186 Sane::~Sane()
00187 {
00188 if( IsOpen() )
00189 Close();
00190 nRefCount--;
00191 if( ! nRefCount && pSaneLib )
00192 DeInit();
00193 }
00194
00195 void Sane::Init()
00196 {
00197 ::rtl::OUString sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ) );
00198 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
00199 if( ! pSaneLib )
00200 {
00201 sSaneLibName = ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ".1" );
00202 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
00203 }
00204
00205 if( ! pSaneLib )
00206 {
00207 ::rtl::OUString sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION ) );
00208 osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
00209 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
00210 }
00211
00212 if( pSaneLib )
00213 {
00214 bSaneSymbolLoadFailed = FALSE;
00215 p_init = (SANE_Status(*)(SANE_Int*, SANE_Auth_Callback ))
00216 LoadSymbol( "sane_init" );
00217 p_exit = (void(*)())
00218 LoadSymbol( "sane_exit" );
00219 p_get_devices = (SANE_Status(*)(const SANE_Device***,
00220 SANE_Bool ))
00221 LoadSymbol( "sane_get_devices" );
00222 p_open = (SANE_Status(*)(SANE_String_Const, SANE_Handle ))
00223 LoadSymbol( "sane_open" );
00224 p_close = (void(*)(SANE_Handle))
00225 LoadSymbol( "sane_close" );
00226 p_get_option_descriptor = (const SANE_Option_Descriptor*(*)(SANE_Handle,
00227 SANE_Int))
00228 LoadSymbol( "sane_get_option_descriptor" );
00229 p_control_option = (SANE_Status(*)(SANE_Handle, SANE_Int,
00230 SANE_Action, void*, SANE_Int*))
00231 LoadSymbol( "sane_control_option" );
00232 p_get_parameters = (SANE_Status(*)(SANE_Handle,SANE_Parameters*))
00233 LoadSymbol( "sane_get_parameters" );
00234 p_start = (SANE_Status(*)(SANE_Handle))
00235 LoadSymbol( "sane_start" );
00236 p_read = (SANE_Status(*)(SANE_Handle, SANE_Byte*,
00237 SANE_Int, SANE_Int* ))
00238 LoadSymbol( "sane_read" );
00239 p_cancel = (void(*)(SANE_Handle))
00240 LoadSymbol( "sane_cancel" );
00241 p_set_io_mode = (SANE_Status(*)(SANE_Handle, SANE_Bool))
00242 LoadSymbol( "sane_set_io_mode" );
00243 p_get_select_fd = (SANE_Status(*)(SANE_Handle, SANE_Int*))
00244 LoadSymbol( "sane_get_select_fd" );
00245 p_strstatus = (const SANE_String_Const(*)(SANE_Status))
00246 LoadSymbol( "sane_strstatus" );
00247 if( bSaneSymbolLoadFailed )
00248 DeInit();
00249 else
00250 {
00251 SANE_Status nStatus = p_init( &nVersion, 0 );
00252 FAIL_SHUTDOWN_STATE( nStatus, "sane_init", );
00253 nStatus = p_get_devices( (const SANE_Device***)&ppDevices,
00254 SANE_FALSE );
00255 FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", );
00256 for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ );
00257 }
00258 }
00259 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
00260 else
00261 fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION,
00262 dlerror() );
00263 #endif
00264 }
00265
00266 void Sane::DeInit()
00267 {
00268 if( pSaneLib )
00269 {
00270 p_exit();
00271 osl_unloadModule( pSaneLib );
00272 pSaneLib = 0;
00273 }
00274 }
00275
00276 void Sane::ReloadDevices()
00277 {
00278 if( IsOpen() )
00279 Close();
00280 DeInit();
00281 Init();
00282 }
00283
00284 void Sane::ReloadOptions()
00285 {
00286 if( ! IsOpen() )
00287 return;
00288
00289 SANE_Option_Descriptor* pZero = (SANE_Option_Descriptor*)
00290 p_get_option_descriptor( maHandle, 0 );
00291 SANE_Word pOptions[2];
00292 SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE,
00293 (void*)pOptions, NULL );
00294 if( nStatus != SANE_STATUS_GOOD )
00295 fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) );
00296
00297 mnOptions = pOptions[ 0 ];
00298 if( (size_t)pZero->size > sizeof( SANE_Word ) )
00299 fprintf( stderr, "driver returned numer of options with larger size tha SANE_Word !!!\n" );
00300 if( mppOptions )
00301 delete [] mppOptions;
00302 mppOptions = (const SANE_Option_Descriptor**)new SANE_Option_Descriptor*[ mnOptions ];
00303 mppOptions[ 0 ] = (SANE_Option_Descriptor*)pZero;
00304 for( int i = 1; i < mnOptions; i++ )
00305 mppOptions[ i ] = (SANE_Option_Descriptor*)
00306 p_get_option_descriptor( maHandle, i );
00307
00308 CheckConsistency( NULL, TRUE );
00309
00310 maReloadOptionsLink.Call( this );
00311 }
00312
00313 BOOL Sane::Open( const char* name )
00314 {
00315 int i;
00316
00317 SANE_Status nStatus = p_open( (SANE_String_Const)name, &maHandle );
00318 FAIL_STATE( nStatus, "sane_open", FALSE );
00319
00320 ReloadOptions();
00321
00322 if( mnDevice == -1 )
00323 {
00324 ByteString aDevice( name );
00325 for( i = 0; i < nDevices; i++ )
00326 {
00327 if( aDevice.Equals( ppDevices[i]->name ) )
00328 {
00329 mnDevice = i;
00330 break;
00331 }
00332 }
00333 }
00334
00335 return TRUE;
00336 }
00337
00338 BOOL Sane::Open( int n )
00339 {
00340 if( n >= 0 && n < nDevices )
00341 {
00342 mnDevice = n;
00343 return Open( (char*)ppDevices[n]->name );
00344 }
00345 return FALSE;
00346 }
00347
00348 void Sane::Close()
00349 {
00350 if( maHandle )
00351 {
00352 p_close( maHandle );
00353 delete [] mppOptions;
00354 mppOptions = 0;
00355 maHandle = 0;
00356 mnDevice = -1;
00357 }
00358 }
00359
00360 void Sane::Stop()
00361 {
00362 if( maHandle )
00363 {
00364 int nDevice = mnDevice;
00365 Close();
00366 Open( nDevice );
00367 }
00368 }
00369
00370 int Sane::GetOptionByName( const char* rName )
00371 {
00372 int i;
00373 ByteString aOption( rName );
00374 for( i = 0; i < mnOptions; i++ )
00375 {
00376 if( mppOptions[i]->name && aOption.Equals( mppOptions[i]->name ) )
00377 return i;
00378 }
00379 return -1;
00380 }
00381
00382 BOOL Sane::GetOptionValue( int n, BOOL& rRet )
00383 {
00384 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
00385 return FALSE;
00386 SANE_Word nRet;
00387 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet );
00388 if( nStatus != SANE_STATUS_GOOD )
00389 return FALSE;
00390
00391 rRet = nRet;
00392 return TRUE;
00393 }
00394
00395 BOOL Sane::GetOptionValue( int n, ByteString& rRet )
00396 {
00397 BOOL bSuccess = FALSE;
00398 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
00399 return FALSE;
00400 char* pRet = new char[mppOptions[n]->size+1];
00401 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
00402 if( nStatus == SANE_STATUS_GOOD )
00403 {
00404 bSuccess = TRUE;
00405 rRet = pRet;
00406 }
00407 delete [] pRet;
00408 return bSuccess;
00409 }
00410
00411 BOOL Sane::GetOptionValue( int n, double& rRet, int nElement )
00412 {
00413 BOOL bSuccess = FALSE;
00414
00415 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
00416 mppOptions[n]->type != SANE_TYPE_FIXED ) )
00417 return FALSE;
00418
00419 SANE_Word* pRet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
00420 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
00421 if( nStatus == SANE_STATUS_GOOD )
00422 {
00423 bSuccess = TRUE;
00424 if( mppOptions[n]->type == SANE_TYPE_INT )
00425 rRet = (double)pRet[ nElement ];
00426 else
00427 rRet = SANE_UNFIX( pRet[nElement] );
00428 }
00429 delete [] pRet;
00430 return bSuccess;
00431 }
00432
00433 BOOL Sane::GetOptionValue( int n, double* pSet )
00434 {
00435 if( ! maHandle || ! ( mppOptions[n]->type == SANE_TYPE_FIXED ||
00436 mppOptions[n]->type == SANE_TYPE_INT ) )
00437 return FALSE;
00438
00439 SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
00440 SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet );
00441 if( nStatus != SANE_STATUS_GOOD )
00442 {
00443 delete [] pFixedSet;
00444 return FALSE;
00445 }
00446 for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ )
00447 {
00448 if( mppOptions[n]->type == SANE_TYPE_FIXED )
00449 pSet[i] = SANE_UNFIX( pFixedSet[i] );
00450 else
00451 pSet[i] = (double) pFixedSet[i];
00452 }
00453 delete [] pFixedSet;
00454 return TRUE;
00455 }
00456
00457 BOOL Sane::SetOptionValue( int n, BOOL bSet )
00458 {
00459 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_BOOL )
00460 return FALSE;
00461 SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
00462 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nRet );
00463 if( nStatus != SANE_STATUS_GOOD )
00464 return FALSE;
00465 return TRUE;
00466 }
00467
00468 BOOL Sane::SetOptionValue( int n, const String& rSet )
00469 {
00470 if( ! maHandle || mppOptions[n]->type != SANE_TYPE_STRING )
00471 return FALSE;
00472 ByteString aSet( rSet, gsl_getSystemTextEncoding() );
00473 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, (void*)aSet.GetBuffer() );
00474 if( nStatus != SANE_STATUS_GOOD )
00475 return FALSE;
00476 return TRUE;
00477 }
00478
00479 BOOL Sane::SetOptionValue( int n, double fSet, int nElement )
00480 {
00481 BOOL bSuccess = FALSE;
00482
00483 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
00484 mppOptions[n]->type != SANE_TYPE_FIXED ) )
00485 return FALSE;
00486
00487 SANE_Status nStatus;
00488 if( mppOptions[n]->size/sizeof(SANE_Word) > 1 )
00489 {
00490 SANE_Word* pSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
00491 nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet );
00492 if( nStatus == SANE_STATUS_GOOD )
00493 {
00494 pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ?
00495 (SANE_Word)fSet : SANE_FIX( fSet );
00496 nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pSet );
00497 }
00498 delete [] pSet;
00499 }
00500 else
00501 {
00502 SANE_Word nSetTo =
00503 mppOptions[n]->type == SANE_TYPE_INT ?
00504 (SANE_Word)fSet : SANE_FIX( fSet );
00505
00506 nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo );
00507 if( nStatus == SANE_STATUS_GOOD )
00508 bSuccess = TRUE;
00509 }
00510 return bSuccess;
00511 }
00512
00513 BOOL Sane::SetOptionValue( int n, double* pSet )
00514 {
00515 if( ! maHandle || ( mppOptions[n]->type != SANE_TYPE_INT &&
00516 mppOptions[n]->type != SANE_TYPE_FIXED ) )
00517 return FALSE;
00518 SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
00519 for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ )
00520 {
00521 if( mppOptions[n]->type == SANE_TYPE_FIXED )
00522 pFixedSet[i] = SANE_FIX( pSet[i] );
00523 else
00524 pFixedSet[i] = (SANE_Word)pSet[i];
00525 }
00526 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet );
00527 delete [] pFixedSet;
00528 if( nStatus != SANE_STATUS_GOOD )
00529 return FALSE;
00530 return TRUE;
00531 }
00532
00533 enum FrameStyleType {
00534 FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
00535 };
00536
00537 #define BYTE_BUFFER_SIZE 32768
00538
00539 static inline UINT8 _ReadValue( FILE* fp, int depth )
00540 {
00541 if( depth == 16 )
00542 {
00543 UINT16 nWord;
00544
00545
00546
00547
00548
00549 fread( &nWord, 1, 2, fp );
00550 return (UINT8)( nWord / 256 );
00551 }
00552 UINT8 nByte;
00553 fread( &nByte, 1, 1, fp );
00554 return nByte;
00555 }
00556
00557 BOOL Sane::CheckConsistency( const char* pMes, BOOL bInit )
00558 {
00559 static SANE_Option_Descriptor** pDescArray = NULL;
00560 static SANE_Option_Descriptor* pZero = NULL;
00561
00562 if( bInit )
00563 {
00564 pDescArray = (SANE_Option_Descriptor**)mppOptions;
00565 if( mppOptions )
00566 pZero = (SANE_Option_Descriptor*)mppOptions[0];
00567 return TRUE;
00568 }
00569
00570 BOOL bConsistent = TRUE;
00571
00572 if( pDescArray != mppOptions )
00573 bConsistent = FALSE;
00574 if( pZero != mppOptions[0] )
00575 bConsistent = FALSE;
00576
00577 if( ! bConsistent )
00578 dbg_msg( "Sane is not consistent. (%s)\n", pMes );
00579
00580 return bConsistent;
00581 }
00582
00583 BOOL Sane::Start( BitmapTransporter& rBitmap )
00584 {
00585 int nStream = 0, nLine = 0, i = 0;
00586 SANE_Parameters aParams;
00587 FrameStyleType eType = FrameStyle_Gray;
00588 BOOL bSuccess = TRUE;
00589 BOOL bWidthSet = FALSE;
00590
00591 if( ! maHandle )
00592 return FALSE;
00593
00594 int nWidthMM = 0;
00595 int nHeightMM = 0;
00596 double fTLx, fTLy, fBRx, fBRy, fResl = 0.0;
00597 int nOption;
00598 if( ( nOption = GetOptionByName( "tl-x" ) ) != -1 &&
00599 GetOptionValue( nOption, fTLx, 0 ) &&
00600 GetOptionUnit( nOption ) == SANE_UNIT_MM )
00601 {
00602 if( ( nOption = GetOptionByName( "br-x" ) ) != -1 &&
00603 GetOptionValue( nOption, fBRx, 0 ) &&
00604 GetOptionUnit( nOption ) == SANE_UNIT_MM )
00605 {
00606 nWidthMM = (int)fabs(fBRx - fTLx);
00607 }
00608 }
00609 if( ( nOption = GetOptionByName( "tl-y" ) ) != -1 &&
00610 GetOptionValue( nOption, fTLy, 0 ) &&
00611 GetOptionUnit( nOption ) == SANE_UNIT_MM )
00612 {
00613 if( ( nOption = GetOptionByName( "br-y" ) ) != -1 &&
00614 GetOptionValue( nOption, fBRy, 0 ) &&
00615 GetOptionUnit( nOption ) == SANE_UNIT_MM )
00616 {
00617 nHeightMM = (int)fabs(fBRy - fTLy);
00618 }
00619 }
00620 if( ( nOption = GetOptionByName( "resolution" ) ) != -1 )
00621 GetOptionValue( nOption, fResl );
00622
00623 BYTE* pBuffer = NULL;
00624
00625 SANE_Status nStatus = SANE_STATUS_GOOD;
00626
00627 rBitmap.lock();
00628 SvMemoryStream& aConverter = rBitmap.getStream();
00629 aConverter.Seek( 0 );
00630 aConverter.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
00631
00632
00633 aConverter << 'B' << 'M';
00634 aConverter << (sal_uInt32) 0;
00635 aConverter << (sal_uInt32) 0;
00636 aConverter << (sal_uInt32) 60;
00637
00638
00639 aConverter << (UINT32)40;
00640 aConverter << (UINT32)0;
00641 aConverter << (UINT32)0;
00642 aConverter << (UINT16)1;
00643
00644
00645 aConverter << (UINT16)24;
00646 aConverter << (UINT32)0;
00647 aConverter << (UINT32)0;
00648 aConverter << (UINT32)0;
00649 aConverter << (UINT32)0;
00650 aConverter << (UINT32)0;
00651 aConverter << (UINT32)0;
00652
00653 for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
00654 {
00655 nStatus = p_start( maHandle );
00656 DUMP_STATE( nStatus, "sane_start" );
00657 CheckConsistency( "sane_start" );
00658 if( nStatus == SANE_STATUS_GOOD )
00659 {
00660 nStatus = p_get_parameters( maHandle, &aParams );
00661 DUMP_STATE( nStatus, "sane_get_parameters" );
00662 CheckConsistency( "sane_get_parameters" );
00663 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
00664 const char* ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
00665 "SANE_FRAME_RED", "SANE_FRAME_GREEN",
00666 "SANE_FRAME_BLUE", "Unknown !!!" };
00667 fprintf( stderr, "Parameters for frame %d:\n", nStream );
00668 if( aParams.format < 0 || aParams.format > 4 )
00669 aParams.format = (SANE_Frame)5;
00670 fprintf( stderr, "format: %s\n", ppFormats[ (int)aParams.format ] );
00671 fprintf( stderr, "last_frame: %s\n", aParams.last_frame ? "TRUE" : "FALSE" );
00672 fprintf( stderr, "depth: %d\n", (int)aParams.depth );
00673 fprintf( stderr, "pixels_per_line: %d\n", (int)aParams.pixels_per_line );
00674 fprintf( stderr, "bytes_per_line: %d\n", (int)aParams.bytes_per_line );
00675 #endif
00676 if( ! pBuffer )
00677 {
00678 pBuffer = new BYTE[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ];
00679 }
00680
00681 if( aParams.last_frame )
00682 nStream=3;
00683
00684 switch( aParams.format )
00685 {
00686 case SANE_FRAME_GRAY:
00687 eType = FrameStyle_Gray;
00688 if( aParams.depth == 1 )
00689 eType = FrameStyle_BW;
00690 break;
00691 case SANE_FRAME_RGB:
00692 eType = FrameStyle_RGB;
00693 break;
00694 case SANE_FRAME_RED:
00695 case SANE_FRAME_GREEN:
00696 case SANE_FRAME_BLUE:
00697 eType = FrameStyle_Separated;
00698 break;
00699 default:
00700 fprintf( stderr, "Warning: unknown frame style !!!\n" );
00701 }
00702
00703 BOOL bSynchronousRead = TRUE;
00704
00705
00706 nStatus = p_set_io_mode( maHandle, SANE_FALSE );
00707 CheckConsistency( "sane_set_io_mode" );
00708 if( nStatus != SANE_STATUS_GOOD )
00709 {
00710 bSynchronousRead = FALSE;
00711 nStatus = p_set_io_mode( maHandle, SANE_TRUE );
00712 CheckConsistency( "sane_set_io_mode" );
00713 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
00714 if( nStatus != SANE_STATUS_GOOD )
00715
00716 fprintf( stderr, "Sane::Start: driver is confused\n" );
00717 #endif
00718 }
00719
00720 SANE_Int nLen=0;
00721 SANE_Int fd = 0;
00722
00723 if( ! bSynchronousRead )
00724 {
00725 nStatus = p_get_select_fd( maHandle, &fd );
00726 DUMP_STATE( nStatus, "sane_get_select_fd" );
00727 CheckConsistency( "sane_get_select_fd" );
00728 if( nStatus != SANE_STATUS_GOOD )
00729 bSynchronousRead = TRUE;
00730 }
00731 FILE* pFrame = tmpfile();
00732 if( ! pFrame )
00733 {
00734 bSuccess = FALSE;
00735 break;
00736 }
00737 do {
00738 if( ! bSynchronousRead )
00739 {
00740 fd_set fdset;
00741 struct timeval tv;
00742
00743 FD_ZERO( &fdset );
00744 FD_SET( (int)fd, &fdset );
00745 tv.tv_sec = 5;
00746 tv.tv_usec = 0;
00747 if( select( fd+1, &fdset, NULL, NULL, &tv ) == 0 )
00748 fprintf( stderr, "Timout on sane_read descriptor\n" );
00749 }
00750 nLen = 0;
00751 nStatus = p_read( maHandle, pBuffer, BYTE_BUFFER_SIZE, &nLen );
00752 CheckConsistency( "sane_read" );
00753 if( nLen && ( nStatus == SANE_STATUS_GOOD ||
00754 nStatus == SANE_STATUS_EOF ) )
00755 {
00756 fwrite( pBuffer, 1, nLen, pFrame );
00757 }
00758 else
00759 DUMP_STATE( nStatus, "sane_read" );
00760 } while( nStatus == SANE_STATUS_GOOD );
00761 if( nStatus != SANE_STATUS_EOF )
00762 {
00763 fclose( pFrame );
00764 bSuccess = FALSE;
00765 break;
00766 }
00767
00768 int nFrameLength = ftell( pFrame );
00769 fseek( pFrame, 0, SEEK_SET );
00770 UINT32 nWidth = (UINT32) aParams.pixels_per_line;
00771 UINT32 nHeight = (UINT32) (nFrameLength / aParams.bytes_per_line);
00772 if( ! bWidthSet )
00773 {
00774 if( ! fResl )
00775 fResl = 300;
00776 if( ! nWidthMM )
00777 nWidthMM = (int)(((double)nWidth / fResl) * 25.4);
00778 if( ! nHeightMM )
00779 nHeightMM = (int)(((double)nHeight / fResl) * 25.4);
00780 #if OSL_DEBUG_LEVEL > 1
00781 fprintf( stderr, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", nWidth, nHeight, nWidthMM, nHeightMM, fResl );
00782 #endif
00783
00784 aConverter.Seek( 18 );
00785 aConverter << (UINT32)nWidth;
00786 aConverter << (UINT32)nHeight;
00787 aConverter.Seek( 38 );
00788 aConverter << (UINT32)(1000*nWidth/nWidthMM);
00789 aConverter << (UINT32)(1000*nHeight/nHeightMM);
00790 bWidthSet = TRUE;
00791 }
00792 aConverter.Seek(60);
00793
00794 if( eType == FrameStyle_BW )
00795 {
00796 aConverter.Seek( 10 );
00797 aConverter << (sal_uInt32)64;
00798 aConverter.Seek( 28 );
00799 aConverter << (UINT16) 1;
00800 aConverter.Seek( 54 );
00801
00802 aConverter << (UINT16)0xffff;
00803 aConverter << (UINT8)0xff;
00804 aConverter << (UINT8)0;
00805 aConverter << (UINT32)0;
00806 aConverter.Seek( 64 );
00807 }
00808 else if( eType == FrameStyle_Gray )
00809 {
00810 aConverter.Seek( 10 );
00811 aConverter << (sal_uInt32)1084;
00812 aConverter.Seek( 28 );
00813 aConverter << (UINT16) 8;
00814 aConverter.Seek( 54 );
00815
00816 for( nLine = 0; nLine < 256; nLine++ )
00817 {
00818 aConverter << (UINT8)nLine;
00819 aConverter << (UINT8)nLine;
00820 aConverter << (UINT8)nLine;
00821 aConverter << (UINT8)0;
00822 }
00823 aConverter.Seek( 1084 );
00824 }
00825
00826 for( nLine = nHeight-1;
00827 nLine >= 0; nLine-- )
00828 {
00829 fseek( pFrame, nLine * aParams.bytes_per_line, SEEK_SET );
00830 if( eType == FrameStyle_BW ||
00831 ( eType == FrameStyle_Gray && aParams.depth == 8 )
00832 )
00833 {
00834 fread( pBuffer, 1, aParams.bytes_per_line, pFrame );
00835 aConverter.Write( pBuffer, aParams.bytes_per_line );
00836 }
00837 else if( eType == FrameStyle_Gray )
00838 {
00839 for( i = 0; i < (aParams.pixels_per_line); i++ )
00840 {
00841 UINT8 nGray = _ReadValue( pFrame, aParams.depth );
00842 aConverter << nGray;
00843 }
00844 }
00845 else if( eType == FrameStyle_RGB )
00846 {
00847 for( i = 0; i < (aParams.pixels_per_line); i++ )
00848 {
00849 UINT8 nRed, nGreen, nBlue;
00850 nRed = _ReadValue( pFrame, aParams.depth );
00851 nGreen = _ReadValue( pFrame, aParams.depth );
00852 nBlue = _ReadValue( pFrame, aParams.depth );
00853 aConverter << nBlue;
00854 aConverter << nGreen;
00855 aConverter << nRed;
00856 }
00857 }
00858 else if( eType == FrameStyle_Separated )
00859 {
00860 for( i = 0; i < (aParams.pixels_per_line); i++ )
00861 {
00862 UINT8 nValue = _ReadValue( pFrame, aParams.depth );
00863 switch( aParams.format )
00864 {
00865 case SANE_FRAME_RED:
00866 aConverter.SeekRel( 2 );
00867 aConverter << nValue;
00868 break;
00869 case SANE_FRAME_GREEN:
00870 aConverter.SeekRel( 1 );
00871 aConverter << nValue;
00872 aConverter.SeekRel( 1 );
00873 break;
00874 case SANE_FRAME_BLUE:
00875 aConverter << nValue;
00876 aConverter.SeekRel( 2 );
00877 break;
00878 case SANE_FRAME_GRAY:
00879 case SANE_FRAME_RGB:
00880 break;
00881 }
00882 }
00883 }
00884 int nGap = aConverter.Tell() & 3;
00885 if( nGap )
00886 aConverter.SeekRel( 4-nGap );
00887 }
00888 fclose( pFrame );
00889 if( eType != FrameStyle_Separated )
00890 break;
00891 }
00892 else
00893 bSuccess = FALSE;
00894 }
00895
00896 aConverter.Seek( STREAM_SEEK_TO_END );
00897 int nPos = aConverter.Tell();
00898
00899 aConverter.Seek( 2 );
00900 aConverter << (sal_uInt32) nPos+1;
00901 aConverter.Seek( 0 );
00902
00903 rBitmap.unlock();
00904
00905 if( bSuccess )
00906 {
00907
00908
00909 p_cancel( maHandle );
00910 CheckConsistency( "sane_cancel" );
00911 }
00912 if( pBuffer )
00913 delete [] pBuffer;
00914
00915 ReloadOptions();
00916
00917
00918 dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" );
00919
00920 return bSuccess;
00921 }
00922
00923 int Sane::GetRange( int n, double*& rpDouble )
00924 {
00925 if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE &&
00926 mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
00927 {
00928 return -1;
00929 }
00930
00931 rpDouble = 0;
00932 int nItems, i;
00933 BOOL bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED ? TRUE : FALSE;
00934
00935 dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name );
00936 if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE )
00937 {
00938 double fMin, fMax, fQuant;
00939 if( bIsFixed )
00940 {
00941 fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min );
00942 fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max );
00943 fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant );
00944 }
00945 else
00946 {
00947 fMin = (double)mppOptions[n]->constraint.range->min;
00948 fMax = (double)mppOptions[n]->constraint.range->max;
00949 fQuant = (double)mppOptions[n]->constraint.range->quant;
00950 }
00951 if( fQuant != 0.0 )
00952 {
00953 dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
00954 fMin, fQuant, fMax );
00955 nItems = (int)((fMax - fMin)/fQuant)+1;
00956 rpDouble = new double[ nItems ];
00957 double fValue = fMin;
00958 for( i = 0; i < nItems; i++, fValue += fQuant )
00959 rpDouble[i] = fValue;
00960 rpDouble[ nItems-1 ] = fMax;
00961 return nItems;
00962 }
00963 else
00964 {
00965 dbg_msg( "normal range [ %lg %lg ]\n",
00966 fMin, fMax );
00967 rpDouble = new double[2];
00968 rpDouble[0] = fMin;
00969 rpDouble[1] = fMax;
00970 return 0;
00971 }
00972 }
00973 else
00974 {
00975 nItems = mppOptions[n]->constraint.word_list[0];
00976 rpDouble = new double[nItems];
00977 for( i=0; i<nItems; i++ )
00978 {
00979 rpDouble[i] = bIsFixed ?
00980 SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) :
00981 (double)mppOptions[n]->constraint.word_list[i+1];
00982 }
00983 dbg_msg( "wordlist [ %lg ... %lg ]\n",
00984 rpDouble[ 0 ], rpDouble[ nItems-1 ] );
00985 return nItems;
00986 }
00987 }
00988
00989 static const char *ppUnits[] = {
00990 "",
00991 "[Pixel]",
00992 "[Bit]",
00993 "[mm]",
00994 "[DPI]",
00995 "[%]",
00996 "[usec]"
00997 };
00998
00999 String Sane::GetOptionUnitName( int n )
01000 {
01001 String aText;
01002 SANE_Unit nUnit = mppOptions[n]->unit;
01003 size_t nUnitAsSize = (size_t)nUnit;
01004 if( nUnitAsSize > sizeof( ppUnits )/sizeof( ppUnits[0] ) )
01005 aText = String::CreateFromAscii( "[unknown units]" );
01006 else
01007 aText = String( ppUnits[ nUnit ], gsl_getSystemTextEncoding() );
01008 return aText;
01009 }
01010
01011 BOOL Sane::ActivateButtonOption( int n )
01012 {
01013 SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, NULL );
01014 if( nStatus != SANE_STATUS_GOOD )
01015 return FALSE;
01016 return TRUE;
01017 }