1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: sane.cxx,v $
10 * $Revision: 1.16.60.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
36 #include <tools/stream.hxx>
42 #include <sys/types.h>
43 #include <sal/config.h>
45 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
47 #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
49 #define dump_state( a, b, c, d ) ;
51 inline void dbg_msg( const char* pString
, ... )
53 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
55 va_start( ap
, pString
);
56 vfprintf( stderr
, pString
, ap
);
63 #define FAIL_SHUTDOWN_STATE( x, y, z ) \
64 if( x != SANE_STATUS_GOOD ) \
66 dump_state( "%s returned error %d (%s)\n", \
67 y, x, p_strstatus( x ) ); \
72 #define FAIL_STATE( x, y, z ) \
73 if( x != SANE_STATUS_GOOD ) \
75 dump_state( "%s returned error %d (%s)\n", \
76 y, x, p_strstatus( x ) ); \
80 #define DUMP_STATE( x, y ) \
81 if( x != SANE_STATUS_GOOD ) \
83 dump_state( "%s returned error %d (%s)\n", \
84 y, x, p_strstatus( x ) ); \
87 #define CHECK_STATE( x, y ) \
88 if( x != SANE_STATUS_GOOD ) \
90 dump_state( "%s returned error %d (%s)\n", \
91 y, x, p_strstatus( x ) ); \
95 int Sane::nRefCount
= 0;
96 oslModule
Sane::pSaneLib
= 0;
97 SANE_Int
Sane::nVersion
= 0;
98 SANE_Device
** Sane::ppDevices
= 0;
99 int Sane::nDevices
= 0;
101 SANE_Status (*Sane::p_init
)( SANE_Int
*,
102 SANE_Auth_Callback
) = 0;
103 void (*Sane::p_exit
)() = 0;
104 SANE_Status (*Sane::p_get_devices
)( const SANE_Device
***,
106 SANE_Status (*Sane::p_open
)( SANE_String_Const
, SANE_Handle
) = 0;
107 void (*Sane::p_close
)( SANE_Handle
) = 0;
108 const SANE_Option_Descriptor
* (*Sane::p_get_option_descriptor
)(
109 SANE_Handle
, SANE_Int
) = 0;
110 SANE_Status (*Sane::p_control_option
)( SANE_Handle
, SANE_Int
,
113 SANE_Status (*Sane::p_get_parameters
)( SANE_Handle
,
114 SANE_Parameters
* ) = 0;
115 SANE_Status (*Sane::p_start
)( SANE_Handle
) = 0;
116 SANE_Status (*Sane::p_read
)( SANE_Handle
, SANE_Byte
*, SANE_Int
,
118 void (*Sane::p_cancel
)( SANE_Handle
) = 0;
119 SANE_Status (*Sane::p_set_io_mode
)( SANE_Handle
, SANE_Bool
) = 0;
120 SANE_Status (*Sane::p_get_select_fd
)( SANE_Handle
, SANE_Int
* ) = 0;
121 SANE_String_Const (*Sane::p_strstatus
)( SANE_Status
) = 0;
123 static BOOL bSaneSymbolLoadFailed
= FALSE
;
125 inline oslGenericFunction
Sane::LoadSymbol( const char* pSymbolname
)
127 oslGenericFunction pFunction
= osl_getAsciiFunctionSymbol( pSaneLib
, pSymbolname
);
130 fprintf( stderr
, "Could not load symbol %s\n",
132 bSaneSymbolLoadFailed
= TRUE
;
137 SANE_Status
Sane::ControlOption( int nOption
, SANE_Action nAction
,
140 SANE_Status nStatus
= SANE_STATUS_GOOD
;
143 nStatus
= p_control_option( maHandle
, (SANE_Int
)nOption
,
144 nAction
, pData
, &nInfo
);
145 DUMP_STATE( nStatus
, "sane_control_option" );
146 #if OSL_DEBUG_LEVEL > 1
147 if( nStatus
!= SANE_STATUS_GOOD
)
149 const char* pAction
= "Unknown";
152 case SANE_ACTION_GET_VALUE
:
153 pAction
= "SANE_ACTION_GET_VALUE";break;
154 case SANE_ACTION_SET_VALUE
:
155 pAction
= "SANE_ACTION_SET_VALUE";break;
156 case SANE_ACTION_SET_AUTO
:
157 pAction
= "SANE_ACTION_SET_AUTO";break;
159 dbg_msg( "Option: \"%s\" action: %s\n",
160 ByteString( GetOptionName( nOption
), gsl_getSystemTextEncoding() ).GetBuffer(),
164 // if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
165 if( nInfo
& SANE_INFO_RELOAD_OPTIONS
)
176 if( ! nRefCount
|| ! pSaneLib
)
186 if( ! nRefCount
&& pSaneLib
)
192 ::rtl::OUString
sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION
) );
193 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
196 sSaneLibName
= ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION
".1" );
197 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
199 // try reasonable places that might not be in the library search path
202 ::rtl::OUString
sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION
) );
203 osl_getFileURLFromSystemPath( sSaneLibSystemPath
.pData
, &sSaneLibName
.pData
);
204 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
209 bSaneSymbolLoadFailed
= FALSE
;
210 p_init
= (SANE_Status(*)(SANE_Int
*, SANE_Auth_Callback
))
211 LoadSymbol( "sane_init" );
213 LoadSymbol( "sane_exit" );
214 p_get_devices
= (SANE_Status(*)(const SANE_Device
***,
216 LoadSymbol( "sane_get_devices" );
217 p_open
= (SANE_Status(*)(SANE_String_Const
, SANE_Handle
))
218 LoadSymbol( "sane_open" );
219 p_close
= (void(*)(SANE_Handle
))
220 LoadSymbol( "sane_close" );
221 p_get_option_descriptor
= (const SANE_Option_Descriptor
*(*)(SANE_Handle
,
223 LoadSymbol( "sane_get_option_descriptor" );
224 p_control_option
= (SANE_Status(*)(SANE_Handle
, SANE_Int
,
225 SANE_Action
, void*, SANE_Int
*))
226 LoadSymbol( "sane_control_option" );
227 p_get_parameters
= (SANE_Status(*)(SANE_Handle
,SANE_Parameters
*))
228 LoadSymbol( "sane_get_parameters" );
229 p_start
= (SANE_Status(*)(SANE_Handle
))
230 LoadSymbol( "sane_start" );
231 p_read
= (SANE_Status(*)(SANE_Handle
, SANE_Byte
*,
232 SANE_Int
, SANE_Int
* ))
233 LoadSymbol( "sane_read" );
234 p_cancel
= (void(*)(SANE_Handle
))
235 LoadSymbol( "sane_cancel" );
236 p_set_io_mode
= (SANE_Status(*)(SANE_Handle
, SANE_Bool
))
237 LoadSymbol( "sane_set_io_mode" );
238 p_get_select_fd
= (SANE_Status(*)(SANE_Handle
, SANE_Int
*))
239 LoadSymbol( "sane_get_select_fd" );
240 p_strstatus
= (SANE_String_Const(*)(SANE_Status
))
241 LoadSymbol( "sane_strstatus" );
242 if( bSaneSymbolLoadFailed
)
246 SANE_Status nStatus
= p_init( &nVersion
, 0 );
247 FAIL_SHUTDOWN_STATE( nStatus
, "sane_init", );
248 nStatus
= p_get_devices( (const SANE_Device
***)&ppDevices
,
250 FAIL_SHUTDOWN_STATE( nStatus
, "sane_get_devices", );
251 for( nDevices
= 0 ; ppDevices
[ nDevices
]; nDevices
++ ) ;
254 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
256 fprintf( stderr
, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION
,
266 osl_unloadModule( pSaneLib
);
271 void Sane::ReloadDevices()
279 void Sane::ReloadOptions()
284 SANE_Option_Descriptor
* pZero
= (SANE_Option_Descriptor
*)
285 p_get_option_descriptor( maHandle
, 0 );
286 SANE_Word pOptions
[2];
287 SANE_Status nStatus
= p_control_option( maHandle
, 0, SANE_ACTION_GET_VALUE
,
288 (void*)pOptions
, NULL
);
289 if( nStatus
!= SANE_STATUS_GOOD
)
290 fprintf( stderr
, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus
) );
292 mnOptions
= pOptions
[ 0 ];
293 if( (size_t)pZero
->size
> sizeof( SANE_Word
) )
294 fprintf( stderr
, "driver returned numer of options with larger size tha SANE_Word !!!\n" );
296 delete [] mppOptions
;
297 mppOptions
= (const SANE_Option_Descriptor
**)new SANE_Option_Descriptor
*[ mnOptions
];
298 mppOptions
[ 0 ] = (SANE_Option_Descriptor
*)pZero
;
299 for( int i
= 1; i
< mnOptions
; i
++ )
300 mppOptions
[ i
] = (SANE_Option_Descriptor
*)
301 p_get_option_descriptor( maHandle
, i
);
303 CheckConsistency( NULL
, TRUE
);
305 maReloadOptionsLink
.Call( this );
308 BOOL
Sane::Open( const char* name
)
312 SANE_Status nStatus
= p_open( (SANE_String_Const
)name
, &maHandle
);
313 FAIL_STATE( nStatus
, "sane_open", FALSE
);
319 ByteString
aDevice( name
);
320 for( i
= 0; i
< nDevices
; i
++ )
322 if( aDevice
.Equals( ppDevices
[i
]->name
) )
333 BOOL
Sane::Open( int n
)
335 if( n
>= 0 && n
< nDevices
)
338 return Open( (char*)ppDevices
[n
]->name
);
348 delete [] mppOptions
;
355 int Sane::GetOptionByName( const char* rName
)
358 ByteString
aOption( rName
);
359 for( i
= 0; i
< mnOptions
; i
++ )
361 if( mppOptions
[i
]->name
&& aOption
.Equals( mppOptions
[i
]->name
) )
367 BOOL
Sane::GetOptionValue( int n
, BOOL
& rRet
)
369 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_BOOL
)
372 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, &nRet
);
373 if( nStatus
!= SANE_STATUS_GOOD
)
380 BOOL
Sane::GetOptionValue( int n
, ByteString
& rRet
)
382 BOOL bSuccess
= FALSE
;
383 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_STRING
)
385 char* pRet
= new char[mppOptions
[n
]->size
+1];
386 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pRet
);
387 if( nStatus
== SANE_STATUS_GOOD
)
396 BOOL
Sane::GetOptionValue( int n
, double& rRet
, int nElement
)
398 BOOL bSuccess
= FALSE
;
400 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
401 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
404 SANE_Word
* pRet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
405 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pRet
);
406 if( nStatus
== SANE_STATUS_GOOD
)
409 if( mppOptions
[n
]->type
== SANE_TYPE_INT
)
410 rRet
= (double)pRet
[ nElement
];
412 rRet
= SANE_UNFIX( pRet
[nElement
] );
418 BOOL
Sane::GetOptionValue( int n
, double* pSet
)
420 if( ! maHandle
|| ! ( mppOptions
[n
]->type
== SANE_TYPE_FIXED
||
421 mppOptions
[n
]->type
== SANE_TYPE_INT
) )
424 SANE_Word
* pFixedSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
425 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pFixedSet
);
426 if( nStatus
!= SANE_STATUS_GOOD
)
431 for( size_t i
= 0; i
<mppOptions
[n
]->size
/sizeof(SANE_Word
); i
++ )
433 if( mppOptions
[n
]->type
== SANE_TYPE_FIXED
)
434 pSet
[i
] = SANE_UNFIX( pFixedSet
[i
] );
436 pSet
[i
] = (double) pFixedSet
[i
];
442 BOOL
Sane::SetOptionValue( int n
, BOOL bSet
)
444 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_BOOL
)
446 SANE_Word nRet
= bSet
? SANE_TRUE
: SANE_FALSE
;
447 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, &nRet
);
448 if( nStatus
!= SANE_STATUS_GOOD
)
453 BOOL
Sane::SetOptionValue( int n
, const String
& rSet
)
455 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_STRING
)
457 ByteString
aSet( rSet
, gsl_getSystemTextEncoding() );
458 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, (void*)aSet
.GetBuffer() );
459 if( nStatus
!= SANE_STATUS_GOOD
)
464 BOOL
Sane::SetOptionValue( int n
, double fSet
, int nElement
)
466 BOOL bSuccess
= FALSE
;
468 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
469 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
473 if( mppOptions
[n
]->size
/sizeof(SANE_Word
) > 1 )
475 SANE_Word
* pSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
476 nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pSet
);
477 if( nStatus
== SANE_STATUS_GOOD
)
479 pSet
[nElement
] = mppOptions
[n
]->type
== SANE_TYPE_INT
?
480 (SANE_Word
)fSet
: SANE_FIX( fSet
);
481 nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, pSet
);
488 mppOptions
[n
]->type
== SANE_TYPE_INT
?
489 (SANE_Word
)fSet
: SANE_FIX( fSet
);
491 nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, &nSetTo
);
492 if( nStatus
== SANE_STATUS_GOOD
)
498 BOOL
Sane::SetOptionValue( int n
, double* pSet
)
500 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
501 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
503 SANE_Word
* pFixedSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
504 for( size_t i
= 0; i
< mppOptions
[n
]->size
/sizeof(SANE_Word
); i
++ )
506 if( mppOptions
[n
]->type
== SANE_TYPE_FIXED
)
507 pFixedSet
[i
] = SANE_FIX( pSet
[i
] );
509 pFixedSet
[i
] = (SANE_Word
)pSet
[i
];
511 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, pFixedSet
);
513 if( nStatus
!= SANE_STATUS_GOOD
)
518 enum FrameStyleType
{
519 FrameStyle_BW
, FrameStyle_Gray
, FrameStyle_RGB
, FrameStyle_Separated
522 #define BYTE_BUFFER_SIZE 32768
524 static inline UINT8
_ReadValue( FILE* fp
, int depth
)
529 // data always come in native byte order !
530 // 16 bits is not really supported by backends as of now
531 // e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
532 // against SANE documentation (xscanimage gets the same result
534 fread( &nWord
, 1, 2, fp
);
535 return (UINT8
)( nWord
/ 256 );
538 fread( &nByte
, 1, 1, fp
);
542 BOOL
Sane::CheckConsistency( const char* pMes
, BOOL bInit
)
544 static SANE_Option_Descriptor
** pDescArray
= NULL
;
545 static SANE_Option_Descriptor
* pZero
= NULL
;
549 pDescArray
= (SANE_Option_Descriptor
**)mppOptions
;
551 pZero
= (SANE_Option_Descriptor
*)mppOptions
[0];
555 BOOL bConsistent
= TRUE
;
557 if( pDescArray
!= mppOptions
)
559 if( pZero
!= mppOptions
[0] )
563 dbg_msg( "Sane is not consistent. (%s)\n", pMes
);
568 BOOL
Sane::Start( BitmapTransporter
& rBitmap
)
570 int nStream
= 0, nLine
= 0, i
= 0;
571 SANE_Parameters aParams
;
572 FrameStyleType eType
= FrameStyle_Gray
;
573 BOOL bSuccess
= TRUE
;
574 BOOL bWidthSet
= FALSE
;
581 double fTLx
, fTLy
, fBRx
, fBRy
, fResl
= 0.0;
583 if( ( nOption
= GetOptionByName( "tl-x" ) ) != -1 &&
584 GetOptionValue( nOption
, fTLx
, 0 ) &&
585 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
587 if( ( nOption
= GetOptionByName( "br-x" ) ) != -1 &&
588 GetOptionValue( nOption
, fBRx
, 0 ) &&
589 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
591 nWidthMM
= (int)fabs(fBRx
- fTLx
);
594 if( ( nOption
= GetOptionByName( "tl-y" ) ) != -1 &&
595 GetOptionValue( nOption
, fTLy
, 0 ) &&
596 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
598 if( ( nOption
= GetOptionByName( "br-y" ) ) != -1 &&
599 GetOptionValue( nOption
, fBRy
, 0 ) &&
600 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
602 nHeightMM
= (int)fabs(fBRy
- fTLy
);
605 if( ( nOption
= GetOptionByName( "resolution" ) ) != -1 )
606 GetOptionValue( nOption
, fResl
);
608 BYTE
* pBuffer
= NULL
;
610 SANE_Status nStatus
= SANE_STATUS_GOOD
;
613 SvMemoryStream
& aConverter
= rBitmap
.getStream();
614 aConverter
.Seek( 0 );
615 aConverter
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
617 // write bitmap stream header
618 aConverter
<< 'B' << 'M';
619 aConverter
<< (sal_uInt32
) 0;
620 aConverter
<< (sal_uInt32
) 0;
621 aConverter
<< (sal_uInt32
) 60;
623 // write BITMAPINFOHEADER
624 aConverter
<< (UINT32
)40;
625 aConverter
<< (UINT32
)0; // fill in width later
626 aConverter
<< (UINT32
)0; // fill in height later
627 aConverter
<< (UINT16
)1;
628 // create header for 24 bits
629 // correct later if necessary
630 aConverter
<< (UINT16
)24;
631 aConverter
<< (UINT32
)0;
632 aConverter
<< (UINT32
)0;
633 aConverter
<< (UINT32
)0;
634 aConverter
<< (UINT32
)0;
635 aConverter
<< (UINT32
)0;
636 aConverter
<< (UINT32
)0;
638 for( nStream
=0; nStream
< 3 && bSuccess
; nStream
++ )
640 nStatus
= p_start( maHandle
);
641 DUMP_STATE( nStatus
, "sane_start" );
642 CheckConsistency( "sane_start" );
643 if( nStatus
== SANE_STATUS_GOOD
)
645 nStatus
= p_get_parameters( maHandle
, &aParams
);
646 DUMP_STATE( nStatus
, "sane_get_parameters" );
647 CheckConsistency( "sane_get_parameters" );
648 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
649 const char* ppFormats
[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
650 "SANE_FRAME_RED", "SANE_FRAME_GREEN",
651 "SANE_FRAME_BLUE", "Unknown !!!" };
652 fprintf( stderr
, "Parameters for frame %d:\n", nStream
);
653 if( aParams
.format
< 0 || aParams
.format
> 4 )
654 aParams
.format
= (SANE_Frame
)5;
655 fprintf( stderr
, "format: %s\n", ppFormats
[ (int)aParams
.format
] );
656 fprintf( stderr
, "last_frame: %s\n", aParams
.last_frame
? "TRUE" : "FALSE" );
657 fprintf( stderr
, "depth: %d\n", (int)aParams
.depth
);
658 fprintf( stderr
, "pixels_per_line: %d\n", (int)aParams
.pixels_per_line
);
659 fprintf( stderr
, "bytes_per_line: %d\n", (int)aParams
.bytes_per_line
);
663 pBuffer
= new BYTE
[ BYTE_BUFFER_SIZE
< 4*aParams
.bytes_per_line
? 4*aParams
.bytes_per_line
: BYTE_BUFFER_SIZE
];
666 if( aParams
.last_frame
)
669 switch( aParams
.format
)
671 case SANE_FRAME_GRAY
:
672 eType
= FrameStyle_Gray
;
673 if( aParams
.depth
== 1 )
674 eType
= FrameStyle_BW
;
677 eType
= FrameStyle_RGB
;
680 case SANE_FRAME_GREEN
:
681 case SANE_FRAME_BLUE
:
682 eType
= FrameStyle_Separated
;
685 fprintf( stderr
, "Warning: unknown frame style !!!\n" );
688 BOOL bSynchronousRead
= TRUE
;
690 // should be fail safe, but ... ??
691 nStatus
= p_set_io_mode( maHandle
, SANE_FALSE
);
692 CheckConsistency( "sane_set_io_mode" );
693 if( nStatus
!= SANE_STATUS_GOOD
)
695 bSynchronousRead
= FALSE
;
696 nStatus
= p_set_io_mode( maHandle
, SANE_TRUE
);
697 CheckConsistency( "sane_set_io_mode" );
698 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
699 if( nStatus
!= SANE_STATUS_GOOD
)
701 fprintf( stderr
, "Sane::Start: driver is confused\n" );
708 if( ! bSynchronousRead
)
710 nStatus
= p_get_select_fd( maHandle
, &fd
);
711 DUMP_STATE( nStatus
, "sane_get_select_fd" );
712 CheckConsistency( "sane_get_select_fd" );
713 if( nStatus
!= SANE_STATUS_GOOD
)
714 bSynchronousRead
= TRUE
;
716 FILE* pFrame
= tmpfile();
723 if( ! bSynchronousRead
)
729 FD_SET( (int)fd
, &fdset
);
732 if( select( fd
+1, &fdset
, NULL
, NULL
, &tv
) == 0 )
733 fprintf( stderr
, "Timout on sane_read descriptor\n" );
736 nStatus
= p_read( maHandle
, pBuffer
, BYTE_BUFFER_SIZE
, &nLen
);
737 CheckConsistency( "sane_read" );
738 if( nLen
&& ( nStatus
== SANE_STATUS_GOOD
||
739 nStatus
== SANE_STATUS_EOF
) )
741 fwrite( pBuffer
, 1, nLen
, pFrame
);
744 DUMP_STATE( nStatus
, "sane_read" );
745 } while( nStatus
== SANE_STATUS_GOOD
);
746 if( nStatus
!= SANE_STATUS_EOF
)
753 int nFrameLength
= ftell( pFrame
);
754 fseek( pFrame
, 0, SEEK_SET
);
755 UINT32 nWidth
= (UINT32
) aParams
.pixels_per_line
;
756 UINT32 nHeight
= (UINT32
) (nFrameLength
/ aParams
.bytes_per_line
);
760 fResl
= 300; // if all else fails that's a good guess
762 nWidthMM
= (int)(((double)nWidth
/ fResl
) * 25.4);
764 nHeightMM
= (int)(((double)nHeight
/ fResl
) * 25.4);
765 #if OSL_DEBUG_LEVEL > 1
766 fprintf( stderr
, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth
, (int)nHeight
, (int)nWidthMM
, (int)nHeightMM
, fResl
);
769 aConverter
.Seek( 18 );
770 aConverter
<< (UINT32
)nWidth
;
771 aConverter
<< (UINT32
)nHeight
;
772 aConverter
.Seek( 38 );
773 aConverter
<< (UINT32
)(1000*nWidth
/nWidthMM
);
774 aConverter
<< (UINT32
)(1000*nHeight
/nHeightMM
);
779 if( eType
== FrameStyle_BW
)
781 aConverter
.Seek( 10 );
782 aConverter
<< (sal_uInt32
)64;
783 aConverter
.Seek( 28 );
784 aConverter
<< (UINT16
) 1;
785 aConverter
.Seek( 54 );
787 aConverter
<< (UINT16
)0xffff;
788 aConverter
<< (UINT8
)0xff;
789 aConverter
<< (UINT8
)0;
790 aConverter
<< (UINT32
)0;
791 aConverter
.Seek( 64 );
793 else if( eType
== FrameStyle_Gray
)
795 aConverter
.Seek( 10 );
796 aConverter
<< (sal_uInt32
)1084;
797 aConverter
.Seek( 28 );
798 aConverter
<< (UINT16
) 8;
799 aConverter
.Seek( 54 );
801 for( nLine
= 0; nLine
< 256; nLine
++ )
803 aConverter
<< (UINT8
)nLine
;
804 aConverter
<< (UINT8
)nLine
;
805 aConverter
<< (UINT8
)nLine
;
806 aConverter
<< (UINT8
)0;
808 aConverter
.Seek( 1084 );
811 for( nLine
= nHeight
-1;
812 nLine
>= 0; nLine
-- )
814 fseek( pFrame
, nLine
* aParams
.bytes_per_line
, SEEK_SET
);
815 if( eType
== FrameStyle_BW
||
816 ( eType
== FrameStyle_Gray
&& aParams
.depth
== 8 )
819 fread( pBuffer
, 1, aParams
.bytes_per_line
, pFrame
);
820 aConverter
.Write( pBuffer
, aParams
.bytes_per_line
);
822 else if( eType
== FrameStyle_Gray
)
824 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
826 UINT8 nGray
= _ReadValue( pFrame
, aParams
.depth
);
830 else if( eType
== FrameStyle_RGB
)
832 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
834 UINT8 nRed
, nGreen
, nBlue
;
835 nRed
= _ReadValue( pFrame
, aParams
.depth
);
836 nGreen
= _ReadValue( pFrame
, aParams
.depth
);
837 nBlue
= _ReadValue( pFrame
, aParams
.depth
);
839 aConverter
<< nGreen
;
843 else if( eType
== FrameStyle_Separated
)
845 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
847 UINT8 nValue
= _ReadValue( pFrame
, aParams
.depth
);
848 switch( aParams
.format
)
851 aConverter
.SeekRel( 2 );
852 aConverter
<< nValue
;
854 case SANE_FRAME_GREEN
:
855 aConverter
.SeekRel( 1 );
856 aConverter
<< nValue
;
857 aConverter
.SeekRel( 1 );
859 case SANE_FRAME_BLUE
:
860 aConverter
<< nValue
;
861 aConverter
.SeekRel( 2 );
863 case SANE_FRAME_GRAY
:
869 int nGap
= aConverter
.Tell() & 3;
871 aConverter
.SeekRel( 4-nGap
);
873 fclose( pFrame
); // deletes tmpfile
874 if( eType
!= FrameStyle_Separated
)
881 aConverter
.Seek( STREAM_SEEK_TO_END
);
882 int nPos
= aConverter
.Tell();
884 aConverter
.Seek( 2 );
885 aConverter
<< (sal_uInt32
) nPos
+1;
886 aConverter
.Seek( 0 );
892 // only cancel a successful operation
893 // sane disrupts memory else
894 p_cancel( maHandle
);
895 CheckConsistency( "sane_cancel" );
903 dbg_msg( "Sane::Start returns with %s\n", bSuccess
? "TRUE" : "FALSE" );
908 int Sane::GetRange( int n
, double*& rpDouble
)
910 if( mppOptions
[n
]->constraint_type
!= SANE_CONSTRAINT_RANGE
&&
911 mppOptions
[n
]->constraint_type
!= SANE_CONSTRAINT_WORD_LIST
)
918 BOOL bIsFixed
= mppOptions
[n
]->type
== SANE_TYPE_FIXED
? TRUE
: FALSE
;
920 dbg_msg( "Sane::GetRange of option %s ", mppOptions
[n
]->name
);
921 if(mppOptions
[n
]->constraint_type
== SANE_CONSTRAINT_RANGE
)
923 double fMin
, fMax
, fQuant
;
926 fMin
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->min
);
927 fMax
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->max
);
928 fQuant
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->quant
);
932 fMin
= (double)mppOptions
[n
]->constraint
.range
->min
;
933 fMax
= (double)mppOptions
[n
]->constraint
.range
->max
;
934 fQuant
= (double)mppOptions
[n
]->constraint
.range
->quant
;
938 dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
939 fMin
, fQuant
, fMax
);
940 nItems
= (int)((fMax
- fMin
)/fQuant
)+1;
941 rpDouble
= new double[ nItems
];
942 double fValue
= fMin
;
943 for( i
= 0; i
< nItems
; i
++, fValue
+= fQuant
)
944 rpDouble
[i
] = fValue
;
945 rpDouble
[ nItems
-1 ] = fMax
;
950 dbg_msg( "normal range [ %lg %lg ]\n",
952 rpDouble
= new double[2];
960 nItems
= mppOptions
[n
]->constraint
.word_list
[0];
961 rpDouble
= new double[nItems
];
962 for( i
=0; i
<nItems
; i
++ )
964 rpDouble
[i
] = bIsFixed
?
965 SANE_UNFIX( mppOptions
[n
]->constraint
.word_list
[i
+1] ) :
966 (double)mppOptions
[n
]->constraint
.word_list
[i
+1];
968 dbg_msg( "wordlist [ %lg ... %lg ]\n",
969 rpDouble
[ 0 ], rpDouble
[ nItems
-1 ] );
974 static const char *ppUnits
[] = {
984 String
Sane::GetOptionUnitName( int n
)
987 SANE_Unit nUnit
= mppOptions
[n
]->unit
;
988 size_t nUnitAsSize
= (size_t)nUnit
;
989 if( nUnitAsSize
> sizeof( ppUnits
)/sizeof( ppUnits
[0] ) )
990 aText
= String::CreateFromAscii( "[unknown units]" );
992 aText
= String( ppUnits
[ nUnit
], gsl_getSystemTextEncoding() );
996 BOOL
Sane::ActivateButtonOption( int n
)
998 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, NULL
);
999 if( nStatus
!= SANE_STATUS_GOOD
)