/Users/ericb/Desktop/NATIVEPRINTDLG01/extensions/source/scanner/sane.cxx

Go to the documentation of this file.
00001 /*************************************************************************
00002  *
00003  *  OpenOffice.org - a multi-platform office productivity suite
00004  *
00005  *  $RCSfile: sane.cxx,v $
00006  *
00007  *  $Revision: 1.14 $
00008  *
00009  *  last change: $Author: ihi $ $Date: 2008/01/14 15:03:00 $
00010  *
00011  *  The Contents of this file are made available subject to
00012  *  the terms of GNU Lesser General Public License Version 2.1.
00013  *
00014  *
00015  *    GNU Lesser General Public License Version 2.1
00016  *    =============================================
00017  *    Copyright 2005 by Sun Microsystems, Inc.
00018  *    901 San Antonio Road, Palo Alto, CA 94303, USA
00019  *
00020  *    This library is free software; you can redistribute it and/or
00021  *    modify it under the terms of the GNU Lesser General Public
00022  *    License version 2.1, as published by the Free Software Foundation.
00023  *
00024  *    This library is distributed in the hope that it will be useful,
00025  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027  *    Lesser General Public License for more details.
00028  *
00029  *    You should have received a copy of the GNU Lesser General Public
00030  *    License along with this library; if not, write to the Free Software
00031  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00032  *    MA  02111-1307  USA
00033  *
00034  ************************************************************************/
00035 
00036 // MARKER(update_precomp.py): autogen include statement, do not remove
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 //      if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
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     // try reasonable places that might not be in the library search path
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                 // data always come in native byte order !
00545                 // 16 bits is not really supported by backends as of now
00546                 // e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
00547                 // against SANE documentation (xscanimage gets the same result
00548                 // as we do
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         // write bitmap stream header
00633         aConverter << 'B' << 'M';
00634         aConverter << (sal_uInt32) 0;
00635         aConverter << (sal_uInt32) 0;
00636         aConverter << (sal_uInt32) 60;
00637 
00638         // write BITMAPINFOHEADER
00639         aConverter << (UINT32)40;
00640         aConverter << (UINT32)0; // fill in width later
00641         aConverter << (UINT32)0; // fill in height later
00642         aConverter << (UINT16)1;
00643         // create header for 24 bits
00644         // correct later if necessary
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                         // should be fail safe, but ... ??
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                                         // what ?!?
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; // if all else fails that's a good guess
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                                 // write color table
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                                 // write color table
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 ); // deletes tmpfile
00889                         if( eType != FrameStyle_Separated )
00890                                 break;
00891                 }
00892                 else
00893                         bSuccess = FALSE;
00894         }
00895         // get stream length
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                 // only cancel a successful operation
00908                 // sane disrupts memory else
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 }

Generated on Thu Feb 28 17:53:26 2008 for AquaScanner by  doxygen 1.5.1