36#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
38#define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
40#define dump_state( a, b, c, d ) ;
42static void dbg_msg(
const char* pString, ... )
44#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
46 va_start( ap, pString );
47 vfprintf( stderr, pString, ap );
54#define FAIL_SHUTDOWN_STATE( x, y, z ) \
55 if( x != SANE_STATUS_GOOD ) \
57 dump_state( "%s returned error %d (%s)\n", \
58 y, x, p_strstatus( x ) ); \
63#define FAIL_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 ) ); \
71#define DUMP_STATE( x, y ) \
72 if( x != SANE_STATUS_GOOD ) \
74 dump_state( "%s returned error %d (%s)\n", \
75 y, x, p_strstatus( x ) ); \
85 SANE_Auth_Callback ) =
nullptr;
88 SANE_Bool ) =
nullptr;
89SANE_Status (*
Sane::p_open)( SANE_String_Const, SANE_Handle ) =
nullptr;
91const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
92 SANE_Handle, SANE_Int ) =
nullptr;
95 SANE_Int* ) =
nullptr;
97 SANE_Parameters* ) =
nullptr;
99SANE_Status (*
Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
100 SANE_Int* ) =
nullptr;
110 oslGenericFunction pFunction = osl_getAsciiFunctionSymbol(
pSaneLib, pSymbolname );
113 fprintf( stderr,
"Could not load symbol %s\n",
126 nAction,
pData, &nInfo );
128#if OSL_DEBUG_LEVEL > 0
129 if( nStatus != SANE_STATUS_GOOD )
131 const char* pAction =
"Unknown";
134 case SANE_ACTION_GET_VALUE:
135 pAction =
"SANE_ACTION_GET_VALUE";
break;
136 case SANE_ACTION_SET_VALUE:
137 pAction =
"SANE_ACTION_SET_VALUE";
break;
138 case SANE_ACTION_SET_AUTO:
139 pAction =
"SANE_ACTION_SET_AUTO";
break;
141 dbg_msg(
"Option: \"%s\" action: %s\n",
146 if( nInfo & SANE_INFO_RELOAD_OPTIONS )
172#ifndef DISABLE_DYNLOADING
174 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
178 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
184 osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
185 pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
191 p_init =
reinterpret_cast<SANE_Status(*)(SANE_Int*, SANE_Auth_Callback )
>(
193 p_exit =
reinterpret_cast<void(*)()
>(
195 p_get_devices =
reinterpret_cast<SANE_Status(*)(
const SANE_Device***,
198 p_open =
reinterpret_cast<SANE_Status(*)(SANE_String_Const, SANE_Handle )
>(
200 p_close =
reinterpret_cast<void(*)(SANE_Handle)
>(
206 SANE_Action,
void*, SANE_Int*)
>(
208 p_get_parameters =
reinterpret_cast<SANE_Status(*)(SANE_Handle,SANE_Parameters*)
>(
210 p_start =
reinterpret_cast<SANE_Status(*)(SANE_Handle)
>(
212 p_read =
reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Byte*,
213 SANE_Int, SANE_Int* )
>(
215 p_cancel =
reinterpret_cast<void(*)(SANE_Handle)
>(
217 p_set_io_mode =
reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Bool)
>(
219 p_get_select_fd =
reinterpret_cast<SANE_Status(*)(SANE_Handle, SANE_Int*)
>(
221 p_strstatus =
reinterpret_cast<SANE_String_Const(*)(SANE_Status)
>(
235#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
247#ifndef DISABLE_DYNLOADING
268 SANE_Word pOptions[2];
270 static_cast<void*
>(pOptions),
nullptr );
271 if( nStatus != SANE_STATUS_GOOD )
272 fprintf( stderr,
"Error: sane driver returned %s while reading number of options !\n",
p_strstatus( nStatus ) );
276 fprintf( stderr,
"driver returned number of options with larger size than SANE_Word!!!\n" );
296 OString aDevice(
name );
334 OString aOption( rName );
348 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_GET_VALUE, &nRet );
349 if( nStatus != SANE_STATUS_GOOD )
358 bool bSuccess =
false;
362 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_GET_VALUE, pRet.get() );
363 if( nStatus == SANE_STATUS_GOOD )
373 bool bSuccess =
false;
379 std::unique_ptr<SANE_Word[]> pRet(
new SANE_Word[
mppOptions[
n]->
size/
sizeof(SANE_Word)]);
380 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_GET_VALUE, pRet.get() );
381 if( nStatus == SANE_STATUS_GOOD )
385 rRet =
static_cast<double>(pRet[ nElement ]);
387 rRet = SANE_UNFIX( pRet[nElement] );
398 std::unique_ptr<SANE_Word[]> pFixedSet(
new SANE_Word[
mppOptions[
n]->
size/
sizeof(SANE_Word)]);
399 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_GET_VALUE, pFixedSet.get() );
400 if( nStatus != SANE_STATUS_GOOD )
402 for(
size_t i = 0;
i <
mppOptions[
n]->size/
sizeof(SANE_Word);
i++ )
405 pSet[
i] = SANE_UNFIX( pFixedSet[
i] );
407 pSet[
i] =
static_cast<double>(pFixedSet[
i]);
416 SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
425 ControlOption(
n, SANE_ACTION_SET_VALUE,
const_cast<char *
>(aSet.getStr()) );
436 std::unique_ptr<SANE_Word[]> pSet(
new SANE_Word[
mppOptions[
n]->
size/
sizeof(SANE_Word)]);
437 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_GET_VALUE, pSet.get() );
438 if( nStatus == SANE_STATUS_GOOD )
440 pSet[nElement] =
mppOptions[
n]->type == SANE_TYPE_INT ?
441 static_cast<SANE_Word
>(fSet) : SANE_FIX( fSet );
449 static_cast<SANE_Word
>(fSet) : SANE_FIX( fSet );
460 std::unique_ptr<SANE_Word[]> pFixedSet(
new SANE_Word[
mppOptions[
n]->
size/
sizeof(SANE_Word)]);
461 for(
size_t i = 0;
i <
mppOptions[
n]->size/
sizeof(SANE_Word);
i++ )
464 pFixedSet[
i] = SANE_FIX( pSet[
i] );
466 pFixedSet[
i] =
static_cast<SANE_Word
>(pSet[
i]);
474 FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
479#define BYTE_BUFFER_SIZE 32768
491 size_t items_read = fread( &nWord, 1, 2, fp );
495 SAL_WARN(
"extensions.scanner",
"short read, abandoning" );
499 return static_cast<sal_uInt8>( nWord / 256 );
502 size_t items_read = fread( &nByte, 1, 1, fp );
505 SAL_WARN(
"extensions.scanner",
"short read, abandoning" );
513 static const SANE_Option_Descriptor** pDescArray =
nullptr;
514 static const SANE_Option_Descriptor* pZero =
nullptr;
524 bool bConsistent =
true;
532 dbg_msg(
"Sane is not consistent. (%s)\n", pMes );
539 int nStream = 0, nLine = 0,
i = 0;
540 SANE_Parameters aParams;
541 FrameStyleType
eType = FrameStyle_Gray;
542 bool bSuccess =
true;
543 bool bWidthSet =
false;
550 double fTLx, fTLy, fResl = 0.0;
563 nWidthMM =
static_cast<int>(fabs(fBRx - fTLx));
577 nHeightMM =
static_cast<int>(fabs(fBRy - fTLy));
583 std::unique_ptr<sal_uInt8[]> pBuffer;
585 SANE_Status nStatus = SANE_STATUS_GOOD;
589 aConverter.
Seek( 0 );
590 aConverter.
SetEndian( SvStreamEndian::LITTLE );
613 for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
618 if( nStatus == SANE_STATUS_GOOD )
623 if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0)
628#if (OSL_DEBUG_LEVEL > 0) || defined DBG_UTIL
629 const char*
const ppFormats[] = {
"SANE_FRAME_GRAY",
"SANE_FRAME_RGB",
630 "SANE_FRAME_RED",
"SANE_FRAME_GREEN",
631 "SANE_FRAME_BLUE",
"Unknown !!!" };
632 fprintf( stderr,
"Parameters for frame %d:\n", nStream );
634 typename std::make_unsigned<
635 typename std::underlying_type<SANE_Frame>::type
>::type>(
639 aParams.format = SANE_Frame(5);
641 fprintf( stderr,
"format: %s\n", ppFormats[
static_cast<int>(aParams.format) ] );
642 fprintf( stderr,
"last_frame: %s\n", aParams.last_frame ?
"TRUE" :
"FALSE" );
643 fprintf( stderr,
"depth: %d\n",
static_cast<int>(aParams.depth) );
644 fprintf( stderr,
"pixels_per_line: %d\n",
static_cast<int>(aParams.pixels_per_line) );
645 fprintf( stderr,
"bytes_per_line: %d\n",
static_cast<int>(aParams.bytes_per_line) );
652 if( aParams.last_frame )
655 switch( aParams.format )
657 case SANE_FRAME_GRAY:
658 eType = FrameStyle_Gray;
659 if( aParams.depth == 1 )
660 eType = FrameStyle_BW;
663 eType = FrameStyle_RGB;
666 case SANE_FRAME_GREEN:
667 case SANE_FRAME_BLUE:
668 eType = FrameStyle_Separated;
671 fprintf( stderr,
"Warning: unknown frame style !!!\n" );
674 bool bSynchronousRead =
true;
679 if( nStatus != SANE_STATUS_GOOD )
681 bSynchronousRead =
false;
684 if (nStatus != SANE_STATUS_GOOD)
686 SAL_WARN(
"extensions.scanner",
"SANE driver status is: " << nStatus);
693 if( ! bSynchronousRead )
698 if( nStatus != SANE_STATUS_GOOD )
699 bSynchronousRead =
true;
710 if( ! bSynchronousRead )
716 FD_SET(
static_cast<int>(fd), &fdset );
719 if( select( fd+1, &fdset,
nullptr,
nullptr, &tv ) == 0 )
720 fprintf( stderr,
"Timeout on sane_read descriptor\n" );
725 if( nLen && ( nStatus == SANE_STATUS_GOOD ||
726 nStatus == SANE_STATUS_EOF ) )
728 bSuccess = (
static_cast<size_t>(nLen) == fwrite( pBuffer.get(), 1, nLen, pFrame ));
734 }
while( nStatus == SANE_STATUS_GOOD );
735 if (nStatus != SANE_STATUS_EOF || !bSuccess)
742 int nFrameLength = ftell( pFrame );
743 fseek( pFrame, 0, SEEK_SET );
744 sal_uInt32 nWidth =
static_cast<sal_uInt32
>(aParams.pixels_per_line);
745 sal_uInt32 nHeight =
static_cast<sal_uInt32
>(nFrameLength / aParams.bytes_per_line);
751 nWidthMM =
static_cast<int>((
static_cast<double>(nWidth) / fResl) * 25.4);
753 nHeightMM =
static_cast<int>((
static_cast<double>(nHeight) / fResl) * 25.4);
754 SAL_INFO(
"extensions.scanner",
"set dimensions to(" << nWidth <<
", " << nHeight <<
") Pixel, (" << nWidthMM <<
", " << nHeightMM <<
755 ") mm, resolution is " << fResl);
757 aConverter.
Seek( 18 );
760 aConverter.
Seek( 38 );
767 if(
eType == FrameStyle_BW )
769 aConverter.
Seek( 10 );
771 aConverter.
Seek( 28 );
773 aConverter.
Seek( 54 );
779 aConverter.
Seek( 64 );
781 else if(
eType == FrameStyle_Gray )
783 aConverter.
Seek( 10 );
785 aConverter.
Seek( 28 );
787 aConverter.
Seek( 54 );
789 for( nLine = 0; nLine < 256; nLine++ )
796 aConverter.
Seek( 1084 );
799 for (nLine = nHeight-1; nLine >= 0; --nLine)
801 if (fseek(pFrame, nLine * aParams.bytes_per_line, SEEK_SET) == -1)
806 if(
eType == FrameStyle_BW ||
807 (
eType == FrameStyle_Gray && aParams.depth == 8 )
810 SANE_Int items_read = fread( pBuffer.get(), 1, aParams.bytes_per_line, pFrame );
811 if (items_read != aParams.bytes_per_line)
813 SAL_WARN(
"extensions.scanner",
"short read, padding with zeros" );
814 memset(pBuffer.get() + items_read, 0, aParams.bytes_per_line - items_read);
816 aConverter.
WriteBytes(pBuffer.get(), aParams.bytes_per_line);
818 else if(
eType == FrameStyle_Gray )
820 for(
i = 0;
i < (aParams.pixels_per_line);
i++ )
826 else if(
eType == FrameStyle_RGB )
828 for(
i = 0;
i < (aParams.pixels_per_line);
i++ )
831 nRed =
ReadValue( pFrame, aParams.depth );
832 nGreen =
ReadValue( pFrame, aParams.depth );
833 nBlue =
ReadValue( pFrame, aParams.depth );
839 else if(
eType == FrameStyle_Separated )
841 for(
i = 0;
i < (aParams.pixels_per_line);
i++ )
844 switch( aParams.format )
850 case SANE_FRAME_GREEN:
855 case SANE_FRAME_BLUE:
859 case SANE_FRAME_GRAY:
865 int nGap = aConverter.
Tell() & 3;
870 if(
eType != FrameStyle_Separated )
879 aConverter.
Seek( 2 );
881 aConverter.
Seek( 0 );
897 dbg_msg(
"Sane::Start returns with %s\n", bSuccess ?
"TRUE" :
"FALSE" );
904 if(
mppOptions[
n]->constraint_type != SANE_CONSTRAINT_RANGE &&
905 mppOptions[
n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
912 bool bIsFixed =
mppOptions[
n]->type == SANE_TYPE_FIXED;
915 if(
mppOptions[
n]->constraint_type == SANE_CONSTRAINT_RANGE )
917 double fMin, fMax, fQuant;
920 fMin = SANE_UNFIX(
mppOptions[
n]->constraint.range->min );
921 fMax = SANE_UNFIX(
mppOptions[
n]->constraint.range->max );
922 fQuant = SANE_UNFIX(
mppOptions[
n]->constraint.range->quant );
926 fMin =
static_cast<double>(
mppOptions[
n]->constraint.range->min);
927 fMax =
static_cast<double>(
mppOptions[
n]->constraint.range->max);
928 fQuant =
static_cast<double>(
mppOptions[
n]->constraint.range->quant);
932 dbg_msg(
"quantum range [ %lg ; %lg ; %lg ]\n",
933 fMin, fQuant, fMax );
934 nItems =
static_cast<int>((fMax - fMin)/fQuant)+1;
935 rpDouble.reset(
new double[ nItems ]);
936 double fValue = fMin;
937 for(
i = 0;
i < nItems;
i++, fValue += fQuant )
938 rpDouble[
i] = fValue;
939 rpDouble[ nItems-1 ] = fMax;
944 dbg_msg(
"normal range [ %lg %lg ]\n",
946 rpDouble.reset(
new double[2]);
955 rpDouble.reset(
new double[nItems]);
956 for(
i=0;
i<nItems;
i++ )
958 rpDouble[
i] = bIsFixed ?
959 SANE_UNFIX(
mppOptions[
n]->constraint.word_list[
i+1] ) :
960 static_cast<double>(
mppOptions[
n]->constraint.word_list[
i+1]);
962 dbg_msg(
"wordlist [ %lg ... %lg ]\n",
963 rpDouble[ 0 ], rpDouble[ nItems-1 ] );
982 size_t nUnitAsSize =
static_cast<size_t>(nUnit);
984 aText =
"[unknown units]";
986 aText = OUString(
ppUnits[ nUnit ], strlen(
ppUnits[ nUnit ]), osl_getThreadTextEncoding() );
992 SANE_Status nStatus =
ControlOption(
n, SANE_ACTION_SET_VALUE,
nullptr );
993 return nStatus == SANE_STATUS_GOOD;
SvMemoryStream & getStream()
SANE_Unit GetOptionUnit(int n)
static SANE_Status(* p_get_devices)(const SANE_Device ***, SANE_Bool)
bool CheckConsistency(const char *, bool bInit=false)
bool GetOptionValue(int, bool &)
static SANE_Status(* p_get_select_fd)(SANE_Handle, SANE_Int *)
bool ActivateButtonOption(int)
OUString GetOptionUnitName(int n)
Link< Sane &, void > maReloadOptionsLink
int GetOptionByName(const char *)
static SANE_Status(* p_start)(SANE_Handle)
bool Start(BitmapTransporter &)
static const SANE_Option_Descriptor *(* p_get_option_descriptor)(SANE_Handle, SANE_Int)
OUString GetOptionName(int n)
int GetRange(int, std::unique_ptr< double[]> &)
static SANE_Status(* p_read)(SANE_Handle, SANE_Byte *, SANE_Int, SANE_Int *)
static SANE_Status(* p_init)(SANE_Int *, SANE_Auth_Callback)
static SANE_Device ** ppDevices
static void(* p_close)(SANE_Handle)
static SANE_Status(* p_control_option)(SANE_Handle, SANE_Int, SANE_Action, void *, SANE_Int *)
std::unique_ptr< const SANE_Option_Descriptor *[]> mppOptions
SANE_Status ControlOption(int, SANE_Action, void *)
static SANE_String_Const(* p_strstatus)(SANE_Status)
static SANE_Status(* p_set_io_mode)(SANE_Handle, SANE_Bool)
static SANE_Status(* p_get_parameters)(SANE_Handle, SANE_Parameters *)
static SANE_Status(* p_open)(SANE_String_Const, SANE_Handle)
static oslGenericFunction LoadSymbol(const char *)
void SetOptionValue(int, bool)
static void(* p_cancel)(SANE_Handle)
static oslModule pSaneLib
virtual sal_uInt64 TellEnd() override
void SetEndian(SvStreamEndian SvStreamEndian)
std::size_t WriteBytes(const void *pData, std::size_t nSize)
SvStream & WriteUChar(unsigned char nChar)
SvStream & WriteUInt16(sal_uInt16 nUInt16)
SvStream & WriteUInt32(sal_uInt32 nUInt32)
sal_uInt64 Seek(sal_uInt64 nPos)
SvStream & WriteChar(char nChar)
sal_uInt64 SeekRel(sal_Int64 nPos)
void EnableKillingFile(bool bEnable=true)
OUString GetFileName() const
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
#define SAL_N_ELEMENTS(arr)
std::unique_ptr< sal_Int32[]> pData
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
static sal_uInt8 ReadValue(FILE *fp, int depth)
#define FAIL_SHUTDOWN_STATE(x, y, z)
static const char * ppUnits[]
static void dbg_msg(const char *pString,...)
#define FAIL_STATE(x, y, z)
static bool bSaneSymbolLoadFailed