1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
33 #include <tools/stream.hxx>
39 #include <sys/types.h>
40 #include <sal/config.h>
42 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
44 #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
46 #define dump_state( a, b, c, d ) ;
48 inline void dbg_msg( const char* pString
, ... )
50 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
52 va_start( ap
, pString
);
53 vfprintf( stderr
, pString
, ap
);
60 #define FAIL_SHUTDOWN_STATE( x, y, z ) \
61 if( x != SANE_STATUS_GOOD ) \
63 dump_state( "%s returned error %d (%s)\n", \
64 y, x, p_strstatus( x ) ); \
69 #define FAIL_STATE( x, y, z ) \
70 if( x != SANE_STATUS_GOOD ) \
72 dump_state( "%s returned error %d (%s)\n", \
73 y, x, p_strstatus( x ) ); \
77 #define DUMP_STATE( x, y ) \
78 if( x != SANE_STATUS_GOOD ) \
80 dump_state( "%s returned error %d (%s)\n", \
81 y, x, p_strstatus( x ) ); \
84 #define CHECK_STATE( x, y ) \
85 if( x != SANE_STATUS_GOOD ) \
87 dump_state( "%s returned error %d (%s)\n", \
88 y, x, p_strstatus( x ) ); \
92 int Sane::nRefCount
= 0;
93 oslModule
Sane::pSaneLib
= 0;
94 SANE_Int
Sane::nVersion
= 0;
95 SANE_Device
** Sane::ppDevices
= 0;
96 int Sane::nDevices
= 0;
98 SANE_Status (*Sane::p_init
)( SANE_Int
*,
99 SANE_Auth_Callback
) = 0;
100 void (*Sane::p_exit
)() = 0;
101 SANE_Status (*Sane::p_get_devices
)( const SANE_Device
***,
103 SANE_Status (*Sane::p_open
)( SANE_String_Const
, SANE_Handle
) = 0;
104 void (*Sane::p_close
)( SANE_Handle
) = 0;
105 const SANE_Option_Descriptor
* (*Sane::p_get_option_descriptor
)(
106 SANE_Handle
, SANE_Int
) = 0;
107 SANE_Status (*Sane::p_control_option
)( SANE_Handle
, SANE_Int
,
110 SANE_Status (*Sane::p_get_parameters
)( SANE_Handle
,
111 SANE_Parameters
* ) = 0;
112 SANE_Status (*Sane::p_start
)( SANE_Handle
) = 0;
113 SANE_Status (*Sane::p_read
)( SANE_Handle
, SANE_Byte
*, SANE_Int
,
115 void (*Sane::p_cancel
)( SANE_Handle
) = 0;
116 SANE_Status (*Sane::p_set_io_mode
)( SANE_Handle
, SANE_Bool
) = 0;
117 SANE_Status (*Sane::p_get_select_fd
)( SANE_Handle
, SANE_Int
* ) = 0;
118 SANE_String_Const (*Sane::p_strstatus
)( SANE_Status
) = 0;
120 static BOOL bSaneSymbolLoadFailed
= FALSE
;
122 inline oslGenericFunction
Sane::LoadSymbol( const char* pSymbolname
)
124 oslGenericFunction pFunction
= osl_getAsciiFunctionSymbol( pSaneLib
, pSymbolname
);
127 fprintf( stderr
, "Could not load symbol %s\n",
129 bSaneSymbolLoadFailed
= TRUE
;
134 SANE_Status
Sane::ControlOption( int nOption
, SANE_Action nAction
,
137 SANE_Status nStatus
= SANE_STATUS_GOOD
;
140 nStatus
= p_control_option( maHandle
, (SANE_Int
)nOption
,
141 nAction
, pData
, &nInfo
);
142 DUMP_STATE( nStatus
, "sane_control_option" );
143 #if OSL_DEBUG_LEVEL > 1
144 if( nStatus
!= SANE_STATUS_GOOD
)
146 const char* pAction
= "Unknown";
149 case SANE_ACTION_GET_VALUE
:
150 pAction
= "SANE_ACTION_GET_VALUE";break;
151 case SANE_ACTION_SET_VALUE
:
152 pAction
= "SANE_ACTION_SET_VALUE";break;
153 case SANE_ACTION_SET_AUTO
:
154 pAction
= "SANE_ACTION_SET_AUTO";break;
156 dbg_msg( "Option: \"%s\" action: %s\n",
157 ByteString( GetOptionName( nOption
), gsl_getSystemTextEncoding() ).GetBuffer(),
161 // if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
162 if( nInfo
& SANE_INFO_RELOAD_OPTIONS
)
173 if( ! nRefCount
|| ! pSaneLib
)
183 if( ! nRefCount
&& pSaneLib
)
189 ::rtl::OUString
sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION
) );
190 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
193 sSaneLibName
= ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION
".1" );
194 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
196 // try reasonable places that might not be in the library search path
199 ::rtl::OUString
sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION
) );
200 osl_getFileURLFromSystemPath( sSaneLibSystemPath
.pData
, &sSaneLibName
.pData
);
201 pSaneLib
= osl_loadModule( sSaneLibName
.pData
, SAL_LOADMODULE_LAZY
);
206 bSaneSymbolLoadFailed
= FALSE
;
207 p_init
= (SANE_Status(*)(SANE_Int
*, SANE_Auth_Callback
))
208 LoadSymbol( "sane_init" );
210 LoadSymbol( "sane_exit" );
211 p_get_devices
= (SANE_Status(*)(const SANE_Device
***,
213 LoadSymbol( "sane_get_devices" );
214 p_open
= (SANE_Status(*)(SANE_String_Const
, SANE_Handle
))
215 LoadSymbol( "sane_open" );
216 p_close
= (void(*)(SANE_Handle
))
217 LoadSymbol( "sane_close" );
218 p_get_option_descriptor
= (const SANE_Option_Descriptor
*(*)(SANE_Handle
,
220 LoadSymbol( "sane_get_option_descriptor" );
221 p_control_option
= (SANE_Status(*)(SANE_Handle
, SANE_Int
,
222 SANE_Action
, void*, SANE_Int
*))
223 LoadSymbol( "sane_control_option" );
224 p_get_parameters
= (SANE_Status(*)(SANE_Handle
,SANE_Parameters
*))
225 LoadSymbol( "sane_get_parameters" );
226 p_start
= (SANE_Status(*)(SANE_Handle
))
227 LoadSymbol( "sane_start" );
228 p_read
= (SANE_Status(*)(SANE_Handle
, SANE_Byte
*,
229 SANE_Int
, SANE_Int
* ))
230 LoadSymbol( "sane_read" );
231 p_cancel
= (void(*)(SANE_Handle
))
232 LoadSymbol( "sane_cancel" );
233 p_set_io_mode
= (SANE_Status(*)(SANE_Handle
, SANE_Bool
))
234 LoadSymbol( "sane_set_io_mode" );
235 p_get_select_fd
= (SANE_Status(*)(SANE_Handle
, SANE_Int
*))
236 LoadSymbol( "sane_get_select_fd" );
237 p_strstatus
= (SANE_String_Const(*)(SANE_Status
))
238 LoadSymbol( "sane_strstatus" );
239 if( bSaneSymbolLoadFailed
)
243 SANE_Status nStatus
= p_init( &nVersion
, 0 );
244 FAIL_SHUTDOWN_STATE( nStatus
, "sane_init", );
245 nStatus
= p_get_devices( (const SANE_Device
***)&ppDevices
,
247 FAIL_SHUTDOWN_STATE( nStatus
, "sane_get_devices", );
248 for( nDevices
= 0 ; ppDevices
[ nDevices
]; nDevices
++ ) ;
251 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
253 fprintf( stderr
, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION
,
263 osl_unloadModule( pSaneLib
);
268 void Sane::ReloadDevices()
276 void Sane::ReloadOptions()
281 SANE_Option_Descriptor
* pZero
= (SANE_Option_Descriptor
*)
282 p_get_option_descriptor( maHandle
, 0 );
283 SANE_Word pOptions
[2];
284 SANE_Status nStatus
= p_control_option( maHandle
, 0, SANE_ACTION_GET_VALUE
,
285 (void*)pOptions
, NULL
);
286 if( nStatus
!= SANE_STATUS_GOOD
)
287 fprintf( stderr
, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus
) );
289 mnOptions
= pOptions
[ 0 ];
290 if( (size_t)pZero
->size
> sizeof( SANE_Word
) )
291 fprintf( stderr
, "driver returned numer of options with larger size tha SANE_Word !!!\n" );
293 delete [] mppOptions
;
294 mppOptions
= (const SANE_Option_Descriptor
**)new SANE_Option_Descriptor
*[ mnOptions
];
295 mppOptions
[ 0 ] = (SANE_Option_Descriptor
*)pZero
;
296 for( int i
= 1; i
< mnOptions
; i
++ )
297 mppOptions
[ i
] = (SANE_Option_Descriptor
*)
298 p_get_option_descriptor( maHandle
, i
);
300 CheckConsistency( NULL
, TRUE
);
302 maReloadOptionsLink
.Call( this );
305 BOOL
Sane::Open( const char* name
)
309 SANE_Status nStatus
= p_open( (SANE_String_Const
)name
, &maHandle
);
310 FAIL_STATE( nStatus
, "sane_open", FALSE
);
316 ByteString
aDevice( name
);
317 for( i
= 0; i
< nDevices
; i
++ )
319 if( aDevice
.Equals( ppDevices
[i
]->name
) )
330 BOOL
Sane::Open( int n
)
332 if( n
>= 0 && n
< nDevices
)
335 return Open( (char*)ppDevices
[n
]->name
);
345 delete [] mppOptions
;
352 int Sane::GetOptionByName( const char* rName
)
355 ByteString
aOption( rName
);
356 for( i
= 0; i
< mnOptions
; i
++ )
358 if( mppOptions
[i
]->name
&& aOption
.Equals( mppOptions
[i
]->name
) )
364 BOOL
Sane::GetOptionValue( int n
, BOOL
& rRet
)
366 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_BOOL
)
369 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, &nRet
);
370 if( nStatus
!= SANE_STATUS_GOOD
)
377 BOOL
Sane::GetOptionValue( int n
, ByteString
& rRet
)
379 BOOL bSuccess
= FALSE
;
380 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_STRING
)
382 char* pRet
= new char[mppOptions
[n
]->size
+1];
383 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pRet
);
384 if( nStatus
== SANE_STATUS_GOOD
)
393 BOOL
Sane::GetOptionValue( int n
, double& rRet
, int nElement
)
395 BOOL bSuccess
= FALSE
;
397 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
398 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
401 SANE_Word
* pRet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
402 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pRet
);
403 if( nStatus
== SANE_STATUS_GOOD
)
406 if( mppOptions
[n
]->type
== SANE_TYPE_INT
)
407 rRet
= (double)pRet
[ nElement
];
409 rRet
= SANE_UNFIX( pRet
[nElement
] );
415 BOOL
Sane::GetOptionValue( int n
, double* pSet
)
417 if( ! maHandle
|| ! ( mppOptions
[n
]->type
== SANE_TYPE_FIXED
||
418 mppOptions
[n
]->type
== SANE_TYPE_INT
) )
421 SANE_Word
* pFixedSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
422 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pFixedSet
);
423 if( nStatus
!= SANE_STATUS_GOOD
)
428 for( size_t i
= 0; i
<mppOptions
[n
]->size
/sizeof(SANE_Word
); i
++ )
430 if( mppOptions
[n
]->type
== SANE_TYPE_FIXED
)
431 pSet
[i
] = SANE_UNFIX( pFixedSet
[i
] );
433 pSet
[i
] = (double) pFixedSet
[i
];
439 BOOL
Sane::SetOptionValue( int n
, BOOL bSet
)
441 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_BOOL
)
443 SANE_Word nRet
= bSet
? SANE_TRUE
: SANE_FALSE
;
444 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, &nRet
);
445 if( nStatus
!= SANE_STATUS_GOOD
)
450 BOOL
Sane::SetOptionValue( int n
, const String
& rSet
)
452 if( ! maHandle
|| mppOptions
[n
]->type
!= SANE_TYPE_STRING
)
454 ByteString
aSet( rSet
, gsl_getSystemTextEncoding() );
455 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, (void*)aSet
.GetBuffer() );
456 if( nStatus
!= SANE_STATUS_GOOD
)
461 BOOL
Sane::SetOptionValue( int n
, double fSet
, int nElement
)
463 BOOL bSuccess
= FALSE
;
465 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
466 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
470 if( mppOptions
[n
]->size
/sizeof(SANE_Word
) > 1 )
472 SANE_Word
* pSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
473 nStatus
= ControlOption( n
, SANE_ACTION_GET_VALUE
, pSet
);
474 if( nStatus
== SANE_STATUS_GOOD
)
476 pSet
[nElement
] = mppOptions
[n
]->type
== SANE_TYPE_INT
?
477 (SANE_Word
)fSet
: SANE_FIX( fSet
);
478 nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, pSet
);
485 mppOptions
[n
]->type
== SANE_TYPE_INT
?
486 (SANE_Word
)fSet
: SANE_FIX( fSet
);
488 nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, &nSetTo
);
489 if( nStatus
== SANE_STATUS_GOOD
)
495 BOOL
Sane::SetOptionValue( int n
, double* pSet
)
497 if( ! maHandle
|| ( mppOptions
[n
]->type
!= SANE_TYPE_INT
&&
498 mppOptions
[n
]->type
!= SANE_TYPE_FIXED
) )
500 SANE_Word
* pFixedSet
= new SANE_Word
[mppOptions
[n
]->size
/sizeof(SANE_Word
)];
501 for( size_t i
= 0; i
< mppOptions
[n
]->size
/sizeof(SANE_Word
); i
++ )
503 if( mppOptions
[n
]->type
== SANE_TYPE_FIXED
)
504 pFixedSet
[i
] = SANE_FIX( pSet
[i
] );
506 pFixedSet
[i
] = (SANE_Word
)pSet
[i
];
508 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, pFixedSet
);
510 if( nStatus
!= SANE_STATUS_GOOD
)
515 enum FrameStyleType
{
516 FrameStyle_BW
, FrameStyle_Gray
, FrameStyle_RGB
, FrameStyle_Separated
519 #define BYTE_BUFFER_SIZE 32768
521 static inline UINT8
_ReadValue( FILE* fp
, int depth
)
526 // data always come in native byte order !
527 // 16 bits is not really supported by backends as of now
528 // e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
529 // against SANE documentation (xscanimage gets the same result
531 fread( &nWord
, 1, 2, fp
);
532 return (UINT8
)( nWord
/ 256 );
535 fread( &nByte
, 1, 1, fp
);
539 BOOL
Sane::CheckConsistency( const char* pMes
, BOOL bInit
)
541 static SANE_Option_Descriptor
** pDescArray
= NULL
;
542 static SANE_Option_Descriptor
* pZero
= NULL
;
546 pDescArray
= (SANE_Option_Descriptor
**)mppOptions
;
548 pZero
= (SANE_Option_Descriptor
*)mppOptions
[0];
552 BOOL bConsistent
= TRUE
;
554 if( pDescArray
!= mppOptions
)
556 if( pZero
!= mppOptions
[0] )
560 dbg_msg( "Sane is not consistent. (%s)\n", pMes
);
565 BOOL
Sane::Start( BitmapTransporter
& rBitmap
)
567 int nStream
= 0, nLine
= 0, i
= 0;
568 SANE_Parameters aParams
;
569 FrameStyleType eType
= FrameStyle_Gray
;
570 BOOL bSuccess
= TRUE
;
571 BOOL bWidthSet
= FALSE
;
578 double fTLx
, fTLy
, fBRx
, fBRy
, fResl
= 0.0;
580 if( ( nOption
= GetOptionByName( "tl-x" ) ) != -1 &&
581 GetOptionValue( nOption
, fTLx
, 0 ) &&
582 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
584 if( ( nOption
= GetOptionByName( "br-x" ) ) != -1 &&
585 GetOptionValue( nOption
, fBRx
, 0 ) &&
586 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
588 nWidthMM
= (int)fabs(fBRx
- fTLx
);
591 if( ( nOption
= GetOptionByName( "tl-y" ) ) != -1 &&
592 GetOptionValue( nOption
, fTLy
, 0 ) &&
593 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
595 if( ( nOption
= GetOptionByName( "br-y" ) ) != -1 &&
596 GetOptionValue( nOption
, fBRy
, 0 ) &&
597 GetOptionUnit( nOption
) == SANE_UNIT_MM
)
599 nHeightMM
= (int)fabs(fBRy
- fTLy
);
602 if( ( nOption
= GetOptionByName( "resolution" ) ) != -1 )
603 GetOptionValue( nOption
, fResl
);
605 BYTE
* pBuffer
= NULL
;
607 SANE_Status nStatus
= SANE_STATUS_GOOD
;
610 SvMemoryStream
& aConverter
= rBitmap
.getStream();
611 aConverter
.Seek( 0 );
612 aConverter
.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
614 // write bitmap stream header
615 aConverter
<< 'B' << 'M';
616 aConverter
<< (sal_uInt32
) 0;
617 aConverter
<< (sal_uInt32
) 0;
618 aConverter
<< (sal_uInt32
) 60;
620 // write BITMAPINFOHEADER
621 aConverter
<< (UINT32
)40;
622 aConverter
<< (UINT32
)0; // fill in width later
623 aConverter
<< (UINT32
)0; // fill in height later
624 aConverter
<< (UINT16
)1;
625 // create header for 24 bits
626 // correct later if necessary
627 aConverter
<< (UINT16
)24;
628 aConverter
<< (UINT32
)0;
629 aConverter
<< (UINT32
)0;
630 aConverter
<< (UINT32
)0;
631 aConverter
<< (UINT32
)0;
632 aConverter
<< (UINT32
)0;
633 aConverter
<< (UINT32
)0;
635 for( nStream
=0; nStream
< 3 && bSuccess
; nStream
++ )
637 nStatus
= p_start( maHandle
);
638 DUMP_STATE( nStatus
, "sane_start" );
639 CheckConsistency( "sane_start" );
640 if( nStatus
== SANE_STATUS_GOOD
)
642 nStatus
= p_get_parameters( maHandle
, &aParams
);
643 DUMP_STATE( nStatus
, "sane_get_parameters" );
644 CheckConsistency( "sane_get_parameters" );
645 if (nStatus
!= SANE_STATUS_GOOD
|| aParams
.bytes_per_line
== 0)
650 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
651 const char* ppFormats
[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
652 "SANE_FRAME_RED", "SANE_FRAME_GREEN",
653 "SANE_FRAME_BLUE", "Unknown !!!" };
654 fprintf( stderr
, "Parameters for frame %d:\n", nStream
);
655 if( aParams
.format
< 0 || aParams
.format
> 4 )
656 aParams
.format
= (SANE_Frame
)5;
657 fprintf( stderr
, "format: %s\n", ppFormats
[ (int)aParams
.format
] );
658 fprintf( stderr
, "last_frame: %s\n", aParams
.last_frame
? "TRUE" : "FALSE" );
659 fprintf( stderr
, "depth: %d\n", (int)aParams
.depth
);
660 fprintf( stderr
, "pixels_per_line: %d\n", (int)aParams
.pixels_per_line
);
661 fprintf( stderr
, "bytes_per_line: %d\n", (int)aParams
.bytes_per_line
);
665 pBuffer
= new BYTE
[ BYTE_BUFFER_SIZE
< 4*aParams
.bytes_per_line
? 4*aParams
.bytes_per_line
: BYTE_BUFFER_SIZE
];
668 if( aParams
.last_frame
)
671 switch( aParams
.format
)
673 case SANE_FRAME_GRAY
:
674 eType
= FrameStyle_Gray
;
675 if( aParams
.depth
== 1 )
676 eType
= FrameStyle_BW
;
679 eType
= FrameStyle_RGB
;
682 case SANE_FRAME_GREEN
:
683 case SANE_FRAME_BLUE
:
684 eType
= FrameStyle_Separated
;
687 fprintf( stderr
, "Warning: unknown frame style !!!\n" );
690 BOOL bSynchronousRead
= TRUE
;
692 // should be fail safe, but ... ??
693 nStatus
= p_set_io_mode( maHandle
, SANE_FALSE
);
694 CheckConsistency( "sane_set_io_mode" );
695 if( nStatus
!= SANE_STATUS_GOOD
)
697 bSynchronousRead
= FALSE
;
698 nStatus
= p_set_io_mode( maHandle
, SANE_TRUE
);
699 CheckConsistency( "sane_set_io_mode" );
700 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
701 if( nStatus
!= SANE_STATUS_GOOD
)
703 fprintf( stderr
, "Sane::Start: driver is confused\n" );
710 if( ! bSynchronousRead
)
712 nStatus
= p_get_select_fd( maHandle
, &fd
);
713 DUMP_STATE( nStatus
, "sane_get_select_fd" );
714 CheckConsistency( "sane_get_select_fd" );
715 if( nStatus
!= SANE_STATUS_GOOD
)
716 bSynchronousRead
= TRUE
;
718 FILE* pFrame
= tmpfile();
725 if( ! bSynchronousRead
)
731 FD_SET( (int)fd
, &fdset
);
734 if( select( fd
+1, &fdset
, NULL
, NULL
, &tv
) == 0 )
735 fprintf( stderr
, "Timout on sane_read descriptor\n" );
738 nStatus
= p_read( maHandle
, pBuffer
, BYTE_BUFFER_SIZE
, &nLen
);
739 CheckConsistency( "sane_read" );
740 if( nLen
&& ( nStatus
== SANE_STATUS_GOOD
||
741 nStatus
== SANE_STATUS_EOF
) )
743 fwrite( pBuffer
, 1, nLen
, pFrame
);
746 DUMP_STATE( nStatus
, "sane_read" );
747 } while( nStatus
== SANE_STATUS_GOOD
);
748 if( nStatus
!= SANE_STATUS_EOF
)
755 int nFrameLength
= ftell( pFrame
);
756 fseek( pFrame
, 0, SEEK_SET
);
757 UINT32 nWidth
= (UINT32
) aParams
.pixels_per_line
;
758 UINT32 nHeight
= (UINT32
) (nFrameLength
/ aParams
.bytes_per_line
);
762 fResl
= 300; // if all else fails that's a good guess
764 nWidthMM
= (int)(((double)nWidth
/ fResl
) * 25.4);
766 nHeightMM
= (int)(((double)nHeight
/ fResl
) * 25.4);
767 #if OSL_DEBUG_LEVEL > 1
768 fprintf( stderr
, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth
, (int)nHeight
, (int)nWidthMM
, (int)nHeightMM
, fResl
);
771 aConverter
.Seek( 18 );
772 aConverter
<< (UINT32
)nWidth
;
773 aConverter
<< (UINT32
)nHeight
;
774 aConverter
.Seek( 38 );
775 aConverter
<< (UINT32
)(1000*nWidth
/nWidthMM
);
776 aConverter
<< (UINT32
)(1000*nHeight
/nHeightMM
);
781 if( eType
== FrameStyle_BW
)
783 aConverter
.Seek( 10 );
784 aConverter
<< (sal_uInt32
)64;
785 aConverter
.Seek( 28 );
786 aConverter
<< (UINT16
) 1;
787 aConverter
.Seek( 54 );
789 aConverter
<< (UINT16
)0xffff;
790 aConverter
<< (UINT8
)0xff;
791 aConverter
<< (UINT8
)0;
792 aConverter
<< (UINT32
)0;
793 aConverter
.Seek( 64 );
795 else if( eType
== FrameStyle_Gray
)
797 aConverter
.Seek( 10 );
798 aConverter
<< (sal_uInt32
)1084;
799 aConverter
.Seek( 28 );
800 aConverter
<< (UINT16
) 8;
801 aConverter
.Seek( 54 );
803 for( nLine
= 0; nLine
< 256; nLine
++ )
805 aConverter
<< (UINT8
)nLine
;
806 aConverter
<< (UINT8
)nLine
;
807 aConverter
<< (UINT8
)nLine
;
808 aConverter
<< (UINT8
)0;
810 aConverter
.Seek( 1084 );
813 for( nLine
= nHeight
-1;
814 nLine
>= 0; nLine
-- )
816 fseek( pFrame
, nLine
* aParams
.bytes_per_line
, SEEK_SET
);
817 if( eType
== FrameStyle_BW
||
818 ( eType
== FrameStyle_Gray
&& aParams
.depth
== 8 )
821 fread( pBuffer
, 1, aParams
.bytes_per_line
, pFrame
);
822 aConverter
.Write( pBuffer
, aParams
.bytes_per_line
);
824 else if( eType
== FrameStyle_Gray
)
826 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
828 UINT8 nGray
= _ReadValue( pFrame
, aParams
.depth
);
832 else if( eType
== FrameStyle_RGB
)
834 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
836 UINT8 nRed
, nGreen
, nBlue
;
837 nRed
= _ReadValue( pFrame
, aParams
.depth
);
838 nGreen
= _ReadValue( pFrame
, aParams
.depth
);
839 nBlue
= _ReadValue( pFrame
, aParams
.depth
);
841 aConverter
<< nGreen
;
845 else if( eType
== FrameStyle_Separated
)
847 for( i
= 0; i
< (aParams
.pixels_per_line
); i
++ )
849 UINT8 nValue
= _ReadValue( pFrame
, aParams
.depth
);
850 switch( aParams
.format
)
853 aConverter
.SeekRel( 2 );
854 aConverter
<< nValue
;
856 case SANE_FRAME_GREEN
:
857 aConverter
.SeekRel( 1 );
858 aConverter
<< nValue
;
859 aConverter
.SeekRel( 1 );
861 case SANE_FRAME_BLUE
:
862 aConverter
<< nValue
;
863 aConverter
.SeekRel( 2 );
865 case SANE_FRAME_GRAY
:
871 int nGap
= aConverter
.Tell() & 3;
873 aConverter
.SeekRel( 4-nGap
);
875 fclose( pFrame
); // deletes tmpfile
876 if( eType
!= FrameStyle_Separated
)
883 aConverter
.Seek( STREAM_SEEK_TO_END
);
884 int nPos
= aConverter
.Tell();
886 aConverter
.Seek( 2 );
887 aConverter
<< (sal_uInt32
) nPos
+1;
888 aConverter
.Seek( 0 );
894 // only cancel a successful operation
895 // sane disrupts memory else
896 p_cancel( maHandle
);
897 CheckConsistency( "sane_cancel" );
905 dbg_msg( "Sane::Start returns with %s\n", bSuccess
? "TRUE" : "FALSE" );
910 int Sane::GetRange( int n
, double*& rpDouble
)
912 if( mppOptions
[n
]->constraint_type
!= SANE_CONSTRAINT_RANGE
&&
913 mppOptions
[n
]->constraint_type
!= SANE_CONSTRAINT_WORD_LIST
)
920 BOOL bIsFixed
= mppOptions
[n
]->type
== SANE_TYPE_FIXED
? TRUE
: FALSE
;
922 dbg_msg( "Sane::GetRange of option %s ", mppOptions
[n
]->name
);
923 if(mppOptions
[n
]->constraint_type
== SANE_CONSTRAINT_RANGE
)
925 double fMin
, fMax
, fQuant
;
928 fMin
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->min
);
929 fMax
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->max
);
930 fQuant
= SANE_UNFIX( mppOptions
[n
]->constraint
.range
->quant
);
934 fMin
= (double)mppOptions
[n
]->constraint
.range
->min
;
935 fMax
= (double)mppOptions
[n
]->constraint
.range
->max
;
936 fQuant
= (double)mppOptions
[n
]->constraint
.range
->quant
;
940 dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
941 fMin
, fQuant
, fMax
);
942 nItems
= (int)((fMax
- fMin
)/fQuant
)+1;
943 rpDouble
= new double[ nItems
];
944 double fValue
= fMin
;
945 for( i
= 0; i
< nItems
; i
++, fValue
+= fQuant
)
946 rpDouble
[i
] = fValue
;
947 rpDouble
[ nItems
-1 ] = fMax
;
952 dbg_msg( "normal range [ %lg %lg ]\n",
954 rpDouble
= new double[2];
962 nItems
= mppOptions
[n
]->constraint
.word_list
[0];
963 rpDouble
= new double[nItems
];
964 for( i
=0; i
<nItems
; i
++ )
966 rpDouble
[i
] = bIsFixed
?
967 SANE_UNFIX( mppOptions
[n
]->constraint
.word_list
[i
+1] ) :
968 (double)mppOptions
[n
]->constraint
.word_list
[i
+1];
970 dbg_msg( "wordlist [ %lg ... %lg ]\n",
971 rpDouble
[ 0 ], rpDouble
[ nItems
-1 ] );
976 static const char *ppUnits
[] = {
986 String
Sane::GetOptionUnitName( int n
)
989 SANE_Unit nUnit
= mppOptions
[n
]->unit
;
990 size_t nUnitAsSize
= (size_t)nUnit
;
991 if( nUnitAsSize
> sizeof( ppUnits
)/sizeof( ppUnits
[0] ) )
992 aText
= String::CreateFromAscii( "[unknown units]" );
994 aText
= String( ppUnits
[ nUnit
], gsl_getSystemTextEncoding() );
998 BOOL
Sane::ActivateButtonOption( int n
)
1000 SANE_Status nStatus
= ControlOption( n
, SANE_ACTION_SET_VALUE
, NULL
);
1001 if( nStatus
!= SANE_STATUS_GOOD
)