xref: /AOO41X/main/extensions/source/scanner/sane.cxx (revision 93ed1f2908b97a4746d8a0cef01e9c4b6219d66b)
12a97ec55SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
32a97ec55SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
42a97ec55SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
52a97ec55SAndrew Rist  * distributed with this work for additional information
62a97ec55SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
72a97ec55SAndrew Rist  * to you under the Apache License, Version 2.0 (the
82a97ec55SAndrew Rist  * "License"); you may not use this file except in compliance
92a97ec55SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
112a97ec55SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
132a97ec55SAndrew Rist  * Unless required by applicable law or agreed to in writing,
142a97ec55SAndrew Rist  * software distributed under the License is distributed on an
152a97ec55SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
162a97ec55SAndrew Rist  * KIND, either express or implied.  See the License for the
172a97ec55SAndrew Rist  * specific language governing permissions and limitations
182a97ec55SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
202a97ec55SAndrew Rist  *************************************************************/
212a97ec55SAndrew Rist 
222a97ec55SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_extensions.hxx"
26cdf0e10cSrcweir #include <cstdarg>
27cdf0e10cSrcweir #include <math.h>
28cdf0e10cSrcweir #include <osl/file.h>
29cdf0e10cSrcweir #include <tools/stream.hxx>
30cdf0e10cSrcweir #include <sane.hxx>
31cdf0e10cSrcweir #include <dlfcn.h>
32cdf0e10cSrcweir #include <stdio.h>
33cdf0e10cSrcweir #include <unistd.h>
34cdf0e10cSrcweir #include <sys/time.h>
35cdf0e10cSrcweir #include <sys/types.h>
36cdf0e10cSrcweir #include <sal/config.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
39cdf0e10cSrcweir #include <stdarg.h>
40cdf0e10cSrcweir #define dump_state( a, b, c, d ) fprintf( stderr, a, b, c, d );
41cdf0e10cSrcweir #else
42cdf0e10cSrcweir #define dump_state( a, b, c, d ) ;
43cdf0e10cSrcweir #endif
dbg_msg(const char * pString,...)44cdf0e10cSrcweir inline void dbg_msg( const char* pString, ... )
45cdf0e10cSrcweir {
46cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
47cdf0e10cSrcweir 	va_list ap;
48cdf0e10cSrcweir 	va_start( ap, pString );
49cdf0e10cSrcweir 	vfprintf( stderr, pString, ap );
50cdf0e10cSrcweir 	va_end( ap );
51cdf0e10cSrcweir #else
52cdf0e10cSrcweir     (void)pString;
53cdf0e10cSrcweir #endif
54cdf0e10cSrcweir }
55cdf0e10cSrcweir 
56cdf0e10cSrcweir #define FAIL_SHUTDOWN_STATE( x, y, z ) \
57cdf0e10cSrcweir 	if( x != SANE_STATUS_GOOD )								\
58cdf0e10cSrcweir 	{														\
59cdf0e10cSrcweir 		dump_state( "%s returned error %d (%s)\n",			\
60cdf0e10cSrcweir 				 y, x, p_strstatus( x ) );					\
61cdf0e10cSrcweir 		DeInit();											\
62cdf0e10cSrcweir 		return z;											\
63cdf0e10cSrcweir 	}
64cdf0e10cSrcweir 
65cdf0e10cSrcweir #define FAIL_STATE( x, y, z ) \
66cdf0e10cSrcweir 	if( x != SANE_STATUS_GOOD )								\
67cdf0e10cSrcweir 	{														\
68cdf0e10cSrcweir 		dump_state( "%s returned error %d (%s)\n",			\
69cdf0e10cSrcweir 				 y, x, p_strstatus( x ) );					\
70cdf0e10cSrcweir 		return z;											\
71cdf0e10cSrcweir 	}
72cdf0e10cSrcweir 
73cdf0e10cSrcweir #define DUMP_STATE( x, y ) \
74cdf0e10cSrcweir 	if( x != SANE_STATUS_GOOD )								\
75cdf0e10cSrcweir 	{														\
76cdf0e10cSrcweir 		dump_state( "%s returned error %d (%s)\n",			\
77cdf0e10cSrcweir 				 y, x, p_strstatus( x ) );					\
78cdf0e10cSrcweir 	}
79cdf0e10cSrcweir 
80cdf0e10cSrcweir #define CHECK_STATE( x, y ) \
81cdf0e10cSrcweir 	if( x != SANE_STATUS_GOOD )								\
82cdf0e10cSrcweir 	{														\
83cdf0e10cSrcweir 		dump_state( "%s returned error %d (%s)\n",			\
84cdf0e10cSrcweir 				 y, x, p_strstatus( x ) );					\
85cdf0e10cSrcweir 	}														\
86cdf0e10cSrcweir 	else
87cdf0e10cSrcweir 
88cdf0e10cSrcweir int				Sane::nRefCount = 0;
89cdf0e10cSrcweir oslModule       Sane::pSaneLib = 0;
90cdf0e10cSrcweir SANE_Int		Sane::nVersion = 0;
91cdf0e10cSrcweir SANE_Device**	Sane::ppDevices = 0;
92cdf0e10cSrcweir int				Sane::nDevices = 0;
93cdf0e10cSrcweir 
94cdf0e10cSrcweir SANE_Status		(*Sane::p_init)( SANE_Int*,
95cdf0e10cSrcweir 								 SANE_Auth_Callback ) = 0;
96cdf0e10cSrcweir void			(*Sane::p_exit)() = 0;
97cdf0e10cSrcweir SANE_Status		(*Sane::p_get_devices)( const SANE_Device***,
98cdf0e10cSrcweir 										SANE_Bool ) = 0;
99cdf0e10cSrcweir SANE_Status		(*Sane::p_open)( SANE_String_Const, SANE_Handle ) = 0;
100cdf0e10cSrcweir void			(*Sane::p_close)( SANE_Handle ) = 0;
101cdf0e10cSrcweir const SANE_Option_Descriptor* (*Sane::p_get_option_descriptor)(
102cdf0e10cSrcweir 	SANE_Handle, SANE_Int ) = 0;
103cdf0e10cSrcweir SANE_Status		(*Sane::p_control_option)( SANE_Handle, SANE_Int,
104cdf0e10cSrcweir 										   SANE_Action, void*,
105cdf0e10cSrcweir 										   SANE_Int* ) = 0;
106cdf0e10cSrcweir SANE_Status		(*Sane::p_get_parameters)( SANE_Handle,
107cdf0e10cSrcweir 										   SANE_Parameters* ) = 0;
108cdf0e10cSrcweir SANE_Status		(*Sane::p_start)( SANE_Handle ) = 0;
109cdf0e10cSrcweir SANE_Status		(*Sane::p_read)( SANE_Handle, SANE_Byte*, SANE_Int,
110cdf0e10cSrcweir 								 SANE_Int* ) = 0;
111cdf0e10cSrcweir void			(*Sane::p_cancel)( SANE_Handle ) = 0;
112cdf0e10cSrcweir SANE_Status		(*Sane::p_set_io_mode)( SANE_Handle, SANE_Bool ) = 0;
113cdf0e10cSrcweir SANE_Status		(*Sane::p_get_select_fd)( SANE_Handle, SANE_Int* ) = 0;
114cdf0e10cSrcweir SANE_String_Const (*Sane::p_strstatus)( SANE_Status ) = 0;
115cdf0e10cSrcweir 
116cdf0e10cSrcweir static sal_Bool bSaneSymbolLoadFailed = sal_False;
117cdf0e10cSrcweir 
LoadSymbol(const char * pSymbolname)118cdf0e10cSrcweir inline oslGenericFunction Sane::LoadSymbol( const char* pSymbolname )
119cdf0e10cSrcweir {
120cdf0e10cSrcweir     oslGenericFunction pFunction = osl_getAsciiFunctionSymbol( pSaneLib, pSymbolname );
121cdf0e10cSrcweir 	if( ! pFunction )
122cdf0e10cSrcweir 	{
123cdf0e10cSrcweir 		fprintf( stderr, "Could not load symbol %s\n",
124cdf0e10cSrcweir 				 pSymbolname );
125cdf0e10cSrcweir 		bSaneSymbolLoadFailed = sal_True;
126cdf0e10cSrcweir 	}
127cdf0e10cSrcweir     return pFunction;
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
ControlOption(int nOption,SANE_Action nAction,void * pData)130cdf0e10cSrcweir SANE_Status Sane::ControlOption( int nOption, SANE_Action nAction,
131cdf0e10cSrcweir 								 void* pData )
132cdf0e10cSrcweir {
133cdf0e10cSrcweir 	SANE_Status	nStatus = SANE_STATUS_GOOD;
134cdf0e10cSrcweir 	SANE_Int	nInfo = 0;
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 	nStatus = p_control_option( maHandle, (SANE_Int)nOption,
137cdf0e10cSrcweir 								nAction, pData, &nInfo );
138cdf0e10cSrcweir 	DUMP_STATE( nStatus, "sane_control_option" );
139cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
140cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
141cdf0e10cSrcweir 	{
142cdf0e10cSrcweir 		const char* pAction = "Unknown";
143cdf0e10cSrcweir 		switch( nAction )
144cdf0e10cSrcweir 		{
145cdf0e10cSrcweir 			case SANE_ACTION_GET_VALUE:
146cdf0e10cSrcweir 				pAction = "SANE_ACTION_GET_VALUE";break;
147cdf0e10cSrcweir 			case SANE_ACTION_SET_VALUE:
148cdf0e10cSrcweir 				pAction = "SANE_ACTION_SET_VALUE";break;
149cdf0e10cSrcweir 			case SANE_ACTION_SET_AUTO:
150cdf0e10cSrcweir 				pAction = "SANE_ACTION_SET_AUTO";break;
151cdf0e10cSrcweir 		}
152cdf0e10cSrcweir 		dbg_msg( "Option: \"%s\" action: %s\n",
153cdf0e10cSrcweir 				 ByteString( GetOptionName( nOption ), gsl_getSystemTextEncoding() ).GetBuffer(),
154cdf0e10cSrcweir 				 pAction );
155cdf0e10cSrcweir 	}
156cdf0e10cSrcweir #endif
157cdf0e10cSrcweir //	if( nInfo & ( SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS ) )
158cdf0e10cSrcweir 	if( nInfo &  SANE_INFO_RELOAD_OPTIONS )
159cdf0e10cSrcweir 		ReloadOptions();
160cdf0e10cSrcweir 	return nStatus;
161cdf0e10cSrcweir }
162cdf0e10cSrcweir 
Sane()163cdf0e10cSrcweir Sane::Sane() :
164cdf0e10cSrcweir 		mppOptions( 0 ),
165cdf0e10cSrcweir 		mnOptions( 0 ),
166cdf0e10cSrcweir 		mnDevice( -1 ),
167cdf0e10cSrcweir 		maHandle( 0 )
168cdf0e10cSrcweir {
169cdf0e10cSrcweir 	if( ! nRefCount || ! pSaneLib )
170cdf0e10cSrcweir 		Init();
171cdf0e10cSrcweir 	nRefCount++;
172cdf0e10cSrcweir };
173cdf0e10cSrcweir 
~Sane()174cdf0e10cSrcweir Sane::~Sane()
175cdf0e10cSrcweir {
176cdf0e10cSrcweir 	if( IsOpen() )
177cdf0e10cSrcweir 		Close();
178cdf0e10cSrcweir 	nRefCount--;
179cdf0e10cSrcweir 	if( ! nRefCount && pSaneLib )
180cdf0e10cSrcweir 		DeInit();
181cdf0e10cSrcweir }
182cdf0e10cSrcweir 
Init()183cdf0e10cSrcweir void Sane::Init()
184cdf0e10cSrcweir {
185cdf0e10cSrcweir     ::rtl::OUString sSaneLibName( ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ) );
186cdf0e10cSrcweir     pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
187cdf0e10cSrcweir     if( ! pSaneLib )
188cdf0e10cSrcweir     {
189cdf0e10cSrcweir         sSaneLibName = ::rtl::OUString::createFromAscii( "libsane" SAL_DLLEXTENSION ".1" );
190cdf0e10cSrcweir         pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
191cdf0e10cSrcweir     }
192cdf0e10cSrcweir     // try reasonable places that might not be in the library search path
193cdf0e10cSrcweir 	if( ! pSaneLib )
194cdf0e10cSrcweir     {
195cdf0e10cSrcweir         ::rtl::OUString sSaneLibSystemPath( ::rtl::OUString::createFromAscii( "/usr/local/lib/libsane" SAL_DLLEXTENSION ) );
196cdf0e10cSrcweir         osl_getFileURLFromSystemPath( sSaneLibSystemPath.pData, &sSaneLibName.pData );
197cdf0e10cSrcweir         pSaneLib = osl_loadModule( sSaneLibName.pData, SAL_LOADMODULE_LAZY );
198cdf0e10cSrcweir     }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir 	if( pSaneLib )
201cdf0e10cSrcweir 	{
202cdf0e10cSrcweir 		bSaneSymbolLoadFailed = sal_False;
203cdf0e10cSrcweir 		p_init = (SANE_Status(*)(SANE_Int*, SANE_Auth_Callback ))
204cdf0e10cSrcweir 			LoadSymbol( "sane_init" );
205cdf0e10cSrcweir 		p_exit = (void(*)())
206cdf0e10cSrcweir 			LoadSymbol( "sane_exit" );
207cdf0e10cSrcweir 		p_get_devices = (SANE_Status(*)(const SANE_Device***,
208cdf0e10cSrcweir 										SANE_Bool ))
209cdf0e10cSrcweir 			LoadSymbol( "sane_get_devices" );
210cdf0e10cSrcweir 		p_open = (SANE_Status(*)(SANE_String_Const, SANE_Handle ))
211cdf0e10cSrcweir 			LoadSymbol( "sane_open" );
212cdf0e10cSrcweir 		p_close = (void(*)(SANE_Handle))
213cdf0e10cSrcweir 			LoadSymbol( "sane_close" );
214cdf0e10cSrcweir 		p_get_option_descriptor = (const SANE_Option_Descriptor*(*)(SANE_Handle,
215cdf0e10cSrcweir 															  SANE_Int))
216cdf0e10cSrcweir 			LoadSymbol( "sane_get_option_descriptor" );
217cdf0e10cSrcweir 		p_control_option = (SANE_Status(*)(SANE_Handle, SANE_Int,
218cdf0e10cSrcweir 										   SANE_Action, void*, SANE_Int*))
219cdf0e10cSrcweir 			LoadSymbol( "sane_control_option" );
220cdf0e10cSrcweir 		p_get_parameters = (SANE_Status(*)(SANE_Handle,SANE_Parameters*))
221cdf0e10cSrcweir 			LoadSymbol( "sane_get_parameters" );
222cdf0e10cSrcweir 		p_start = (SANE_Status(*)(SANE_Handle))
223cdf0e10cSrcweir 			LoadSymbol( "sane_start" );
224cdf0e10cSrcweir 		p_read = (SANE_Status(*)(SANE_Handle, SANE_Byte*,
225cdf0e10cSrcweir 								 SANE_Int, SANE_Int* ))
226cdf0e10cSrcweir 			LoadSymbol( "sane_read" );
227cdf0e10cSrcweir 		p_cancel = (void(*)(SANE_Handle))
228cdf0e10cSrcweir 			LoadSymbol( "sane_cancel" );
229cdf0e10cSrcweir 		p_set_io_mode = (SANE_Status(*)(SANE_Handle, SANE_Bool))
230cdf0e10cSrcweir 			LoadSymbol( "sane_set_io_mode" );
231cdf0e10cSrcweir 		p_get_select_fd = (SANE_Status(*)(SANE_Handle, SANE_Int*))
232cdf0e10cSrcweir 			LoadSymbol( "sane_get_select_fd" );
233cdf0e10cSrcweir 		p_strstatus = (SANE_String_Const(*)(SANE_Status))
234cdf0e10cSrcweir 			LoadSymbol( "sane_strstatus" );
235cdf0e10cSrcweir 		if( bSaneSymbolLoadFailed )
236cdf0e10cSrcweir 			DeInit();
237cdf0e10cSrcweir 		else
238cdf0e10cSrcweir 		{
239cdf0e10cSrcweir 			SANE_Status nStatus = p_init( &nVersion, 0 );
240cdf0e10cSrcweir 			FAIL_SHUTDOWN_STATE( nStatus, "sane_init", );
241cdf0e10cSrcweir 			nStatus = p_get_devices( (const SANE_Device***)&ppDevices,
242cdf0e10cSrcweir 									 SANE_FALSE );
243cdf0e10cSrcweir 			FAIL_SHUTDOWN_STATE( nStatus, "sane_get_devices", );
244cdf0e10cSrcweir 			for( nDevices = 0 ; ppDevices[ nDevices ]; nDevices++ ) ;
245cdf0e10cSrcweir 		}
246cdf0e10cSrcweir 	}
247cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
248cdf0e10cSrcweir 	else
249cdf0e10cSrcweir 		fprintf( stderr, "libsane%s could not be opened: %s\n", SAL_DLLEXTENSION,
250cdf0e10cSrcweir 				 dlerror() );
251cdf0e10cSrcweir #endif
252cdf0e10cSrcweir }
253cdf0e10cSrcweir 
DeInit()254cdf0e10cSrcweir void Sane::DeInit()
255cdf0e10cSrcweir {
256cdf0e10cSrcweir 	if( pSaneLib )
257cdf0e10cSrcweir 	{
258cdf0e10cSrcweir 		p_exit();
259cdf0e10cSrcweir         osl_unloadModule( pSaneLib );
260cdf0e10cSrcweir 		pSaneLib = 0;
261cdf0e10cSrcweir 	}
262cdf0e10cSrcweir }
263cdf0e10cSrcweir 
ReloadDevices()264cdf0e10cSrcweir void Sane::ReloadDevices()
265cdf0e10cSrcweir {
266cdf0e10cSrcweir 	if( IsOpen() )
267cdf0e10cSrcweir 		Close();
268cdf0e10cSrcweir 	DeInit();
269cdf0e10cSrcweir 	Init();
270cdf0e10cSrcweir }
271cdf0e10cSrcweir 
ReloadOptions()272cdf0e10cSrcweir void Sane::ReloadOptions()
273cdf0e10cSrcweir {
274cdf0e10cSrcweir 	if( ! IsOpen() )
275cdf0e10cSrcweir 		return;
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 	SANE_Option_Descriptor* pZero = (SANE_Option_Descriptor*)
278cdf0e10cSrcweir 		p_get_option_descriptor( maHandle, 0 );
279cdf0e10cSrcweir 	SANE_Word pOptions[2];
280cdf0e10cSrcweir 	SANE_Status nStatus = p_control_option( maHandle, 0, SANE_ACTION_GET_VALUE,
281cdf0e10cSrcweir 											(void*)pOptions, NULL );
282cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
283cdf0e10cSrcweir 		fprintf( stderr, "Error: sane driver returned %s while reading number of options !\n", p_strstatus( nStatus ) );
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 	mnOptions = pOptions[ 0 ];
286cdf0e10cSrcweir 	if( (size_t)pZero->size > sizeof( SANE_Word ) )
287cdf0e10cSrcweir 		fprintf( stderr, "driver returned numer of options with larger size tha SANE_Word !!!\n" );
288cdf0e10cSrcweir 	if( mppOptions )
289cdf0e10cSrcweir 		delete [] mppOptions;
290cdf0e10cSrcweir 	mppOptions = (const SANE_Option_Descriptor**)new SANE_Option_Descriptor*[ mnOptions ];
291cdf0e10cSrcweir 	mppOptions[ 0 ] = (SANE_Option_Descriptor*)pZero;
292cdf0e10cSrcweir 	for( int i = 1; i < mnOptions; i++ )
293cdf0e10cSrcweir 		mppOptions[ i ] =  (SANE_Option_Descriptor*)
294cdf0e10cSrcweir 			p_get_option_descriptor( maHandle, i );
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 	CheckConsistency( NULL, sal_True );
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 	maReloadOptionsLink.Call( this );
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
Open(const char * name)301cdf0e10cSrcweir sal_Bool Sane::Open( const char* name )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir 	int i;
304cdf0e10cSrcweir 
305cdf0e10cSrcweir 	SANE_Status nStatus = p_open( (SANE_String_Const)name, &maHandle );
306cdf0e10cSrcweir 	FAIL_STATE( nStatus, "sane_open", sal_False );
307cdf0e10cSrcweir 
308cdf0e10cSrcweir 	ReloadOptions();
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 	if( mnDevice == -1 )
311cdf0e10cSrcweir 	{
312cdf0e10cSrcweir 		ByteString aDevice( name );
313cdf0e10cSrcweir 		for( i = 0; i < nDevices; i++ )
314cdf0e10cSrcweir 		{
315cdf0e10cSrcweir 			if( aDevice.Equals( ppDevices[i]->name ) )
316cdf0e10cSrcweir 			{
317cdf0e10cSrcweir 				mnDevice = i;
318cdf0e10cSrcweir 				break;
319cdf0e10cSrcweir 			}
320cdf0e10cSrcweir 		}
321cdf0e10cSrcweir 	}
322cdf0e10cSrcweir 
323cdf0e10cSrcweir 	return sal_True;
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
Open(int n)326cdf0e10cSrcweir sal_Bool Sane::Open( int n )
327cdf0e10cSrcweir {
328cdf0e10cSrcweir 	if( n >= 0 && n < nDevices )
329cdf0e10cSrcweir 	{
330cdf0e10cSrcweir 		mnDevice = n;
331cdf0e10cSrcweir 		return Open( (char*)ppDevices[n]->name );
332cdf0e10cSrcweir 	}
333cdf0e10cSrcweir 	return sal_False;
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
Close()336cdf0e10cSrcweir void Sane::Close()
337cdf0e10cSrcweir {
338cdf0e10cSrcweir 	if( maHandle )
339cdf0e10cSrcweir 	{
340cdf0e10cSrcweir 		p_close( maHandle );
341cdf0e10cSrcweir 		delete [] mppOptions;
342cdf0e10cSrcweir 		mppOptions = 0;
343cdf0e10cSrcweir 		maHandle = 0;
344cdf0e10cSrcweir 		mnDevice = -1;
345cdf0e10cSrcweir 	}
346cdf0e10cSrcweir }
347cdf0e10cSrcweir 
GetOptionByName(const char * rName)348cdf0e10cSrcweir int Sane::GetOptionByName( const char* rName )
349cdf0e10cSrcweir {
350cdf0e10cSrcweir 	int i;
351cdf0e10cSrcweir 	ByteString aOption( rName );
352cdf0e10cSrcweir 	for( i = 0; i < mnOptions; i++ )
353cdf0e10cSrcweir 	{
354cdf0e10cSrcweir 		if( mppOptions[i]->name && aOption.Equals( mppOptions[i]->name ) )
355cdf0e10cSrcweir 			return i;
356cdf0e10cSrcweir 	}
357cdf0e10cSrcweir 	return -1;
358cdf0e10cSrcweir }
359cdf0e10cSrcweir 
GetOptionValue(int n,sal_Bool & rRet)360cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, sal_Bool& rRet )
361cdf0e10cSrcweir {
362cdf0e10cSrcweir 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_BOOL )
363cdf0e10cSrcweir 		return sal_False;
364cdf0e10cSrcweir 	SANE_Word nRet;
365cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, &nRet );
366cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
367cdf0e10cSrcweir 		return sal_False;
368cdf0e10cSrcweir 
369cdf0e10cSrcweir 	rRet = nRet;
370cdf0e10cSrcweir 	return sal_True;
371cdf0e10cSrcweir }
372cdf0e10cSrcweir 
GetOptionValue(int n,ByteString & rRet)373cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, ByteString& rRet )
374cdf0e10cSrcweir {
375cdf0e10cSrcweir 	sal_Bool bSuccess = sal_False;
376cdf0e10cSrcweir 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_STRING )
377cdf0e10cSrcweir 		return sal_False;
378cdf0e10cSrcweir 	char* pRet = new char[mppOptions[n]->size+1];
379cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
380cdf0e10cSrcweir 	if( nStatus == SANE_STATUS_GOOD )
381cdf0e10cSrcweir 	{
382cdf0e10cSrcweir 		bSuccess = sal_True;
383cdf0e10cSrcweir 		rRet = pRet;
384cdf0e10cSrcweir 	}
385cdf0e10cSrcweir 	delete [] pRet;
386cdf0e10cSrcweir 	return bSuccess;
387cdf0e10cSrcweir }
388cdf0e10cSrcweir 
GetOptionValue(int n,double & rRet,int nElement)389cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, double& rRet, int nElement )
390cdf0e10cSrcweir {
391cdf0e10cSrcweir 	sal_Bool bSuccess = sal_False;
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
394cdf0e10cSrcweir 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
395cdf0e10cSrcweir 		return sal_False;
396cdf0e10cSrcweir 
397cdf0e10cSrcweir 	SANE_Word* pRet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
398cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pRet );
399cdf0e10cSrcweir 	if( nStatus == SANE_STATUS_GOOD )
400cdf0e10cSrcweir 	{
401cdf0e10cSrcweir 		bSuccess = sal_True;
402cdf0e10cSrcweir 		if( mppOptions[n]->type == SANE_TYPE_INT )
403cdf0e10cSrcweir 			rRet = (double)pRet[ nElement ];
404cdf0e10cSrcweir 		else
405cdf0e10cSrcweir 			rRet = SANE_UNFIX( pRet[nElement] );
406cdf0e10cSrcweir 	}
407cdf0e10cSrcweir 	delete [] pRet;
408cdf0e10cSrcweir 	return bSuccess;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir 
GetOptionValue(int n,double * pSet)411cdf0e10cSrcweir sal_Bool Sane::GetOptionValue( int n, double* pSet )
412cdf0e10cSrcweir {
413cdf0e10cSrcweir 	if( ! maHandle  || ! ( mppOptions[n]->type == SANE_TYPE_FIXED ||
414cdf0e10cSrcweir 						   mppOptions[n]->type == SANE_TYPE_INT ) )
415cdf0e10cSrcweir 		return sal_False;
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 	SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
418cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pFixedSet );
419cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
420cdf0e10cSrcweir 	{
421cdf0e10cSrcweir 		delete [] pFixedSet;
422cdf0e10cSrcweir 		return sal_False;
423cdf0e10cSrcweir 	}
424cdf0e10cSrcweir 	for( size_t i = 0; i <mppOptions[n]->size/sizeof(SANE_Word); i++ )
425cdf0e10cSrcweir 	{
426cdf0e10cSrcweir 		if( mppOptions[n]->type == SANE_TYPE_FIXED )
427cdf0e10cSrcweir 			pSet[i] = SANE_UNFIX( pFixedSet[i] );
428cdf0e10cSrcweir 		else
429cdf0e10cSrcweir 			pSet[i] = (double) pFixedSet[i];
430cdf0e10cSrcweir 	}
431cdf0e10cSrcweir 	delete [] pFixedSet;
432cdf0e10cSrcweir 	return sal_True;
433cdf0e10cSrcweir }
434cdf0e10cSrcweir 
SetOptionValue(int n,sal_Bool bSet)435cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, sal_Bool bSet )
436cdf0e10cSrcweir {
437cdf0e10cSrcweir 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_BOOL )
438cdf0e10cSrcweir 		return sal_False;
439cdf0e10cSrcweir 	SANE_Word nRet = bSet ? SANE_TRUE : SANE_FALSE;
440cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nRet );
441cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
442cdf0e10cSrcweir 		return sal_False;
443cdf0e10cSrcweir 	return sal_True;
444cdf0e10cSrcweir }
445cdf0e10cSrcweir 
SetOptionValue(int n,const String & rSet)446cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, const String& rSet )
447cdf0e10cSrcweir {
448cdf0e10cSrcweir 	if( ! maHandle  ||  mppOptions[n]->type != SANE_TYPE_STRING )
449cdf0e10cSrcweir 		return sal_False;
450cdf0e10cSrcweir 	ByteString aSet( rSet, gsl_getSystemTextEncoding() );
451cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, (void*)aSet.GetBuffer() );
452cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
453cdf0e10cSrcweir 		return sal_False;
454cdf0e10cSrcweir 	return sal_True;
455cdf0e10cSrcweir }
456cdf0e10cSrcweir 
SetOptionValue(int n,double fSet,int nElement)457cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, double fSet, int nElement )
458cdf0e10cSrcweir {
459cdf0e10cSrcweir 	sal_Bool bSuccess = sal_False;
460cdf0e10cSrcweir 
461cdf0e10cSrcweir 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
462cdf0e10cSrcweir 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
463cdf0e10cSrcweir 		return sal_False;
464cdf0e10cSrcweir 
465cdf0e10cSrcweir 	SANE_Status nStatus;
466cdf0e10cSrcweir 	if( mppOptions[n]->size/sizeof(SANE_Word) > 1 )
467cdf0e10cSrcweir 	{
468cdf0e10cSrcweir 		SANE_Word* pSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
469cdf0e10cSrcweir 		nStatus = ControlOption( n, SANE_ACTION_GET_VALUE, pSet );
470cdf0e10cSrcweir 		if( nStatus == SANE_STATUS_GOOD )
471cdf0e10cSrcweir 		{
472cdf0e10cSrcweir 			pSet[nElement] = mppOptions[n]->type == SANE_TYPE_INT ?
473cdf0e10cSrcweir 				(SANE_Word)fSet : SANE_FIX( fSet );
474cdf0e10cSrcweir 			nStatus = ControlOption(  n, SANE_ACTION_SET_VALUE, pSet );
475cdf0e10cSrcweir 		}
476cdf0e10cSrcweir 		delete [] pSet;
477cdf0e10cSrcweir 	}
478cdf0e10cSrcweir 	else
479cdf0e10cSrcweir 	{
480cdf0e10cSrcweir 		SANE_Word nSetTo =
481cdf0e10cSrcweir 			mppOptions[n]->type == SANE_TYPE_INT ?
482cdf0e10cSrcweir 			(SANE_Word)fSet : SANE_FIX( fSet );
483cdf0e10cSrcweir 
484cdf0e10cSrcweir 		nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, &nSetTo );
485cdf0e10cSrcweir 		if( nStatus == SANE_STATUS_GOOD )
486cdf0e10cSrcweir 			bSuccess = sal_True;
487cdf0e10cSrcweir 	}
488cdf0e10cSrcweir 	return bSuccess;
489cdf0e10cSrcweir }
490cdf0e10cSrcweir 
SetOptionValue(int n,double * pSet)491cdf0e10cSrcweir sal_Bool Sane::SetOptionValue( int n, double* pSet )
492cdf0e10cSrcweir {
493cdf0e10cSrcweir 	if( ! maHandle  ||  ( mppOptions[n]->type != SANE_TYPE_INT &&
494cdf0e10cSrcweir 						  mppOptions[n]->type != SANE_TYPE_FIXED ) )
495cdf0e10cSrcweir 		return sal_False;
496cdf0e10cSrcweir 	SANE_Word* pFixedSet = new SANE_Word[mppOptions[n]->size/sizeof(SANE_Word)];
497cdf0e10cSrcweir 	for( size_t i = 0; i < mppOptions[n]->size/sizeof(SANE_Word); i++ )
498cdf0e10cSrcweir 	{
499cdf0e10cSrcweir 		if( mppOptions[n]->type == SANE_TYPE_FIXED )
500cdf0e10cSrcweir 			pFixedSet[i] = SANE_FIX( pSet[i] );
501cdf0e10cSrcweir 		else
502cdf0e10cSrcweir 			pFixedSet[i] = (SANE_Word)pSet[i];
503cdf0e10cSrcweir 	}
504cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, pFixedSet );
505cdf0e10cSrcweir 	delete [] pFixedSet;
506cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
507cdf0e10cSrcweir 		return sal_False;
508cdf0e10cSrcweir 	return sal_True;
509cdf0e10cSrcweir }
510cdf0e10cSrcweir 
511cdf0e10cSrcweir enum FrameStyleType {
512cdf0e10cSrcweir 	FrameStyle_BW, FrameStyle_Gray, FrameStyle_RGB, FrameStyle_Separated
513cdf0e10cSrcweir };
514cdf0e10cSrcweir 
515cdf0e10cSrcweir #define BYTE_BUFFER_SIZE 32768
516cdf0e10cSrcweir 
_ReadValue(FILE * fp,int depth)517cdf0e10cSrcweir static inline sal_uInt8 _ReadValue( FILE* fp, int depth )
518cdf0e10cSrcweir {
519cdf0e10cSrcweir 	if( depth == 16 )
520cdf0e10cSrcweir 	{
521cdf0e10cSrcweir 		sal_uInt16 nWord;
522cdf0e10cSrcweir 		// data always come in native byte order !
523cdf0e10cSrcweir 		// 16 bits is not really supported by backends as of now
524cdf0e10cSrcweir 		// e.g. UMAX Astra 1200S delivers 16 bit but in BIGENDIAN
525cdf0e10cSrcweir 		// against SANE documentation (xscanimage gets the same result
526cdf0e10cSrcweir 		// as we do
527cdf0e10cSrcweir 		fread( &nWord, 1, 2, fp );
528cdf0e10cSrcweir 		return (sal_uInt8)( nWord / 256 );
529cdf0e10cSrcweir 	}
530cdf0e10cSrcweir 	sal_uInt8 nByte;
531cdf0e10cSrcweir 	fread( &nByte, 1, 1, fp );
532cdf0e10cSrcweir 	return nByte;
533cdf0e10cSrcweir }
534cdf0e10cSrcweir 
CheckConsistency(const char * pMes,sal_Bool bInit)535cdf0e10cSrcweir sal_Bool Sane::CheckConsistency( const char* pMes, sal_Bool bInit )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir 	static SANE_Option_Descriptor** pDescArray = NULL;
538cdf0e10cSrcweir 	static SANE_Option_Descriptor*  pZero = NULL;
539cdf0e10cSrcweir 
540cdf0e10cSrcweir 	if( bInit )
541cdf0e10cSrcweir 	{
542cdf0e10cSrcweir 		pDescArray = (SANE_Option_Descriptor**)mppOptions;
543cdf0e10cSrcweir 		if( mppOptions )
544cdf0e10cSrcweir 			pZero = (SANE_Option_Descriptor*)mppOptions[0];
545cdf0e10cSrcweir 		return sal_True;
546cdf0e10cSrcweir 	}
547cdf0e10cSrcweir 
548cdf0e10cSrcweir 	sal_Bool bConsistent = sal_True;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 	if( pDescArray != mppOptions )
551cdf0e10cSrcweir 		bConsistent = sal_False;
552cdf0e10cSrcweir 	if( pZero != mppOptions[0] )
553cdf0e10cSrcweir 		bConsistent = sal_False;
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 	if( ! bConsistent )
556cdf0e10cSrcweir 		dbg_msg( "Sane is not consistent. (%s)\n", pMes );
557cdf0e10cSrcweir 
558cdf0e10cSrcweir 	return bConsistent;
559cdf0e10cSrcweir }
560cdf0e10cSrcweir 
Start(BitmapTransporter & rBitmap)561cdf0e10cSrcweir sal_Bool Sane::Start( BitmapTransporter& rBitmap )
562cdf0e10cSrcweir {
563cdf0e10cSrcweir 	int nStream = 0, nLine = 0, i = 0;
564cdf0e10cSrcweir 	SANE_Parameters	aParams;
565cdf0e10cSrcweir 	FrameStyleType eType = FrameStyle_Gray;
566cdf0e10cSrcweir 	sal_Bool bSuccess = sal_True;
567cdf0e10cSrcweir 	sal_Bool bWidthSet = sal_False;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 	if( ! maHandle )
570cdf0e10cSrcweir 		return sal_False;
571cdf0e10cSrcweir 
572cdf0e10cSrcweir     int nWidthMM	= 0;
573cdf0e10cSrcweir     int nHeightMM	= 0;
574cdf0e10cSrcweir     double fTLx, fTLy, fBRx, fBRy, fResl = 0.0;
575cdf0e10cSrcweir     int nOption;
576cdf0e10cSrcweir     if( ( nOption = GetOptionByName( "tl-x" ) ) != -1	&&
577cdf0e10cSrcweir         GetOptionValue( nOption, fTLx, 0 )				&&
578cdf0e10cSrcweir         GetOptionUnit( nOption ) == SANE_UNIT_MM )
579cdf0e10cSrcweir     {
580cdf0e10cSrcweir         if( ( nOption = GetOptionByName( "br-x" ) ) != -1	&&
581cdf0e10cSrcweir             GetOptionValue( nOption, fBRx, 0 )				&&
582cdf0e10cSrcweir             GetOptionUnit( nOption ) == SANE_UNIT_MM )
583cdf0e10cSrcweir         {
584cdf0e10cSrcweir             nWidthMM = (int)fabs(fBRx - fTLx);
585cdf0e10cSrcweir         }
586cdf0e10cSrcweir     }
587cdf0e10cSrcweir     if( ( nOption = GetOptionByName( "tl-y" ) ) != -1	&&
588cdf0e10cSrcweir         GetOptionValue( nOption, fTLy, 0 )				&&
589cdf0e10cSrcweir         GetOptionUnit( nOption ) == SANE_UNIT_MM )
590cdf0e10cSrcweir     {
591cdf0e10cSrcweir         if( ( nOption = GetOptionByName( "br-y" ) ) != -1	&&
592cdf0e10cSrcweir             GetOptionValue( nOption, fBRy, 0 )				&&
593cdf0e10cSrcweir             GetOptionUnit( nOption ) == SANE_UNIT_MM )
594cdf0e10cSrcweir         {
595cdf0e10cSrcweir             nHeightMM = (int)fabs(fBRy - fTLy);
596cdf0e10cSrcweir         }
597cdf0e10cSrcweir     }
598cdf0e10cSrcweir     if( ( nOption = GetOptionByName( "resolution" ) ) != -1 )
599cdf0e10cSrcweir         GetOptionValue( nOption, fResl );
600cdf0e10cSrcweir 
601cdf0e10cSrcweir 	sal_uInt8* pBuffer = NULL;
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 	SANE_Status nStatus = SANE_STATUS_GOOD;
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 	rBitmap.lock();
606cdf0e10cSrcweir 	SvMemoryStream& aConverter = rBitmap.getStream();
607cdf0e10cSrcweir 	aConverter.Seek( 0 );
608cdf0e10cSrcweir 	aConverter.SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
609cdf0e10cSrcweir 
610cdf0e10cSrcweir 	// write bitmap stream header
611cdf0e10cSrcweir 	aConverter << 'B' << 'M';
612cdf0e10cSrcweir 	aConverter << (sal_uInt32) 0;
613cdf0e10cSrcweir 	aConverter << (sal_uInt32) 0;
614cdf0e10cSrcweir 	aConverter << (sal_uInt32) 60;
615cdf0e10cSrcweir 
616cdf0e10cSrcweir 	// write BITMAPINFOHEADER
617cdf0e10cSrcweir 	aConverter << (sal_uInt32)40;
618cdf0e10cSrcweir 	aConverter << (sal_uInt32)0; // fill in width later
619cdf0e10cSrcweir 	aConverter << (sal_uInt32)0; // fill in height later
620cdf0e10cSrcweir 	aConverter << (sal_uInt16)1;
621cdf0e10cSrcweir 	// create header for 24 bits
622cdf0e10cSrcweir 	// correct later if necessary
623cdf0e10cSrcweir 	aConverter << (sal_uInt16)24;
624cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
625cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
626cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
627cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
628cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
629cdf0e10cSrcweir 	aConverter << (sal_uInt32)0;
630cdf0e10cSrcweir 
631cdf0e10cSrcweir 	for( nStream=0; nStream < 3 && bSuccess ; nStream++ )
632cdf0e10cSrcweir 	{
633cdf0e10cSrcweir 		nStatus = p_start( maHandle );
634cdf0e10cSrcweir 		DUMP_STATE( nStatus, "sane_start" );
635cdf0e10cSrcweir 		CheckConsistency( "sane_start" );
636cdf0e10cSrcweir 		if( nStatus == SANE_STATUS_GOOD )
637cdf0e10cSrcweir 		{
638cdf0e10cSrcweir 			nStatus = p_get_parameters( maHandle, &aParams );
639cdf0e10cSrcweir 			DUMP_STATE( nStatus, "sane_get_parameters" );
640cdf0e10cSrcweir 			CheckConsistency( "sane_get_parameters" );
641cdf0e10cSrcweir 			if (nStatus != SANE_STATUS_GOOD || aParams.bytes_per_line == 0)
642cdf0e10cSrcweir 			{
643cdf0e10cSrcweir 				bSuccess = sal_False;
644cdf0e10cSrcweir 			    break;
645cdf0e10cSrcweir 			}
646cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
647cdf0e10cSrcweir 			const char* ppFormats[] = { "SANE_FRAME_GRAY", "SANE_FRAME_RGB",
648cdf0e10cSrcweir 								  "SANE_FRAME_RED", "SANE_FRAME_GREEN",
649cdf0e10cSrcweir 								  "SANE_FRAME_BLUE", "Unknown !!!" };
650cdf0e10cSrcweir 			fprintf( stderr, "Parameters for frame %d:\n", nStream );
651cdf0e10cSrcweir 			if( aParams.format < 0 || aParams.format > 4 )
652cdf0e10cSrcweir 				aParams.format = (SANE_Frame)5;
653cdf0e10cSrcweir 			fprintf( stderr, "format:           %s\n", ppFormats[ (int)aParams.format ] );
654cdf0e10cSrcweir 			fprintf( stderr, "last_frame:       %s\n", aParams.last_frame ? "TRUE" : "FALSE" );
655cdf0e10cSrcweir 			fprintf( stderr, "depth:            %d\n", (int)aParams.depth );
656cdf0e10cSrcweir 			fprintf( stderr, "pixels_per_line:  %d\n", (int)aParams.pixels_per_line );
657cdf0e10cSrcweir 			fprintf( stderr, "bytes_per_line:   %d\n", (int)aParams.bytes_per_line );
658cdf0e10cSrcweir #endif
659cdf0e10cSrcweir 			if( ! pBuffer )
660cdf0e10cSrcweir 			{
661cdf0e10cSrcweir 				pBuffer = new sal_uInt8[ BYTE_BUFFER_SIZE < 4*aParams.bytes_per_line ? 4*aParams.bytes_per_line : BYTE_BUFFER_SIZE ];
662cdf0e10cSrcweir 			}
663cdf0e10cSrcweir 
664cdf0e10cSrcweir 			if( aParams.last_frame )
665cdf0e10cSrcweir 				nStream=3;
666cdf0e10cSrcweir 
667cdf0e10cSrcweir 			switch( aParams.format )
668cdf0e10cSrcweir 			{
669cdf0e10cSrcweir 				case SANE_FRAME_GRAY:
670cdf0e10cSrcweir 					eType = FrameStyle_Gray;
671cdf0e10cSrcweir 					if( aParams.depth == 1 )
672cdf0e10cSrcweir 						eType = FrameStyle_BW;
673cdf0e10cSrcweir 					break;
674cdf0e10cSrcweir 				case SANE_FRAME_RGB:
675cdf0e10cSrcweir 					eType = FrameStyle_RGB;
676cdf0e10cSrcweir 					break;
677cdf0e10cSrcweir 				case SANE_FRAME_RED:
678cdf0e10cSrcweir 				case SANE_FRAME_GREEN:
679cdf0e10cSrcweir 				case SANE_FRAME_BLUE:
680cdf0e10cSrcweir 					eType = FrameStyle_Separated;
681cdf0e10cSrcweir 					break;
682cdf0e10cSrcweir 				default:
683cdf0e10cSrcweir 					fprintf( stderr, "Warning: unknown frame style !!!\n" );
684cdf0e10cSrcweir 			}
685cdf0e10cSrcweir 
686cdf0e10cSrcweir 			sal_Bool bSynchronousRead = sal_True;
687cdf0e10cSrcweir 
688cdf0e10cSrcweir 			// should be fail safe, but ... ??
689cdf0e10cSrcweir 			nStatus = p_set_io_mode( maHandle, SANE_FALSE );
690cdf0e10cSrcweir 			CheckConsistency( "sane_set_io_mode" );
691cdf0e10cSrcweir 			if( nStatus != SANE_STATUS_GOOD )
692cdf0e10cSrcweir 			{
693cdf0e10cSrcweir 				bSynchronousRead = sal_False;
694cdf0e10cSrcweir 				nStatus = p_set_io_mode( maHandle, SANE_TRUE );
695cdf0e10cSrcweir 				CheckConsistency( "sane_set_io_mode" );
696cdf0e10cSrcweir #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
697cdf0e10cSrcweir 				if( nStatus != SANE_STATUS_GOOD )
698cdf0e10cSrcweir 					// what ?!?
699cdf0e10cSrcweir 					fprintf( stderr, "Sane::Start: driver is confused\n" );
700cdf0e10cSrcweir #endif
701cdf0e10cSrcweir 			}
702cdf0e10cSrcweir 
703cdf0e10cSrcweir 			SANE_Int nLen=0;
704cdf0e10cSrcweir 			SANE_Int fd = 0;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir 			if( ! bSynchronousRead )
707cdf0e10cSrcweir 			{
708cdf0e10cSrcweir 				nStatus = p_get_select_fd( maHandle, &fd );
709cdf0e10cSrcweir 				DUMP_STATE( nStatus, "sane_get_select_fd" );
710cdf0e10cSrcweir 				CheckConsistency( "sane_get_select_fd" );
711cdf0e10cSrcweir 				if( nStatus != SANE_STATUS_GOOD )
712cdf0e10cSrcweir 					bSynchronousRead = sal_True;
713cdf0e10cSrcweir 			}
714cdf0e10cSrcweir 			FILE* pFrame = tmpfile();
715cdf0e10cSrcweir 			if( ! pFrame )
716cdf0e10cSrcweir 			{
717cdf0e10cSrcweir 				bSuccess = sal_False;
718cdf0e10cSrcweir 				break;
719cdf0e10cSrcweir 			}
720cdf0e10cSrcweir 			do {
721cdf0e10cSrcweir 				if( ! bSynchronousRead )
722cdf0e10cSrcweir 				{
723cdf0e10cSrcweir 					fd_set fdset;
724cdf0e10cSrcweir 					struct timeval tv;
725cdf0e10cSrcweir 
726cdf0e10cSrcweir 					FD_ZERO( &fdset );
727cdf0e10cSrcweir 					FD_SET( (int)fd, &fdset );
728cdf0e10cSrcweir 					tv.tv_sec = 5;
729cdf0e10cSrcweir 					tv.tv_usec = 0;
730cdf0e10cSrcweir 					if( select( fd+1, &fdset, NULL, NULL, &tv ) == 0 )
731cdf0e10cSrcweir 						fprintf( stderr, "Timout on sane_read descriptor\n" );
732cdf0e10cSrcweir 				}
733cdf0e10cSrcweir 				nLen = 0;
734cdf0e10cSrcweir 				nStatus = p_read( maHandle, pBuffer, BYTE_BUFFER_SIZE, &nLen );
735cdf0e10cSrcweir 				CheckConsistency( "sane_read" );
736cdf0e10cSrcweir 				if( nLen && ( nStatus == SANE_STATUS_GOOD ||
737cdf0e10cSrcweir 							  nStatus == SANE_STATUS_EOF ) )
738cdf0e10cSrcweir 				{
739cdf0e10cSrcweir 					fwrite( pBuffer, 1, nLen, pFrame );
740cdf0e10cSrcweir 				}
741cdf0e10cSrcweir 				else
742cdf0e10cSrcweir 					DUMP_STATE( nStatus, "sane_read" );
743cdf0e10cSrcweir 			} while( nStatus == SANE_STATUS_GOOD );
744cdf0e10cSrcweir 			if( nStatus != SANE_STATUS_EOF )
745cdf0e10cSrcweir 			{
746cdf0e10cSrcweir 				fclose( pFrame );
747cdf0e10cSrcweir 				bSuccess = sal_False;
748cdf0e10cSrcweir 				break;
749cdf0e10cSrcweir 			}
750cdf0e10cSrcweir 
751cdf0e10cSrcweir 			int nFrameLength = ftell( pFrame );
752cdf0e10cSrcweir 			fseek( pFrame, 0, SEEK_SET );
753cdf0e10cSrcweir 			sal_uInt32 nWidth = (sal_uInt32) aParams.pixels_per_line;
754cdf0e10cSrcweir 			sal_uInt32 nHeight = (sal_uInt32) (nFrameLength / aParams.bytes_per_line);
755cdf0e10cSrcweir 			if( ! bWidthSet )
756cdf0e10cSrcweir 			{
757cdf0e10cSrcweir                 if( ! fResl )
758cdf0e10cSrcweir                     fResl = 300; // if all else fails that's a good guess
759cdf0e10cSrcweir                 if( ! nWidthMM )
760cdf0e10cSrcweir                     nWidthMM = (int)(((double)nWidth / fResl) * 25.4);
761cdf0e10cSrcweir                 if( ! nHeightMM )
762cdf0e10cSrcweir                     nHeightMM = (int)(((double)nHeight / fResl) * 25.4);
763cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
764cdf0e10cSrcweir 				fprintf( stderr, "set dimensions to (%d, %d) Pixel, (%d, %d) mm, resolution is %lg\n", (int)nWidth, (int)nHeight, (int)nWidthMM, (int)nHeightMM, fResl );
765cdf0e10cSrcweir #endif
766cdf0e10cSrcweir 
767cdf0e10cSrcweir 				aConverter.Seek( 18 );
768cdf0e10cSrcweir 				aConverter << (sal_uInt32)nWidth;
769cdf0e10cSrcweir 				aConverter << (sal_uInt32)nHeight;
770cdf0e10cSrcweir                 aConverter.Seek( 38 );
771cdf0e10cSrcweir                 aConverter << (sal_uInt32)(1000*nWidth/nWidthMM);
772cdf0e10cSrcweir                 aConverter << (sal_uInt32)(1000*nHeight/nHeightMM);
773cdf0e10cSrcweir 				bWidthSet = sal_True;
774cdf0e10cSrcweir 			}
775cdf0e10cSrcweir 			aConverter.Seek(60);
776cdf0e10cSrcweir 
777cdf0e10cSrcweir 			if( eType == FrameStyle_BW )
778cdf0e10cSrcweir 			{
779cdf0e10cSrcweir 				aConverter.Seek( 10 );
780cdf0e10cSrcweir 				aConverter << (sal_uInt32)64;
781cdf0e10cSrcweir 				aConverter.Seek( 28 );
782cdf0e10cSrcweir 				aConverter << (sal_uInt16) 1;
783cdf0e10cSrcweir 				aConverter.Seek( 54 );
784cdf0e10cSrcweir 				// write color table
785cdf0e10cSrcweir 				aConverter << (sal_uInt16)0xffff;
786cdf0e10cSrcweir 				aConverter << (sal_uInt8)0xff;
787cdf0e10cSrcweir 				aConverter << (sal_uInt8)0;
788cdf0e10cSrcweir 				aConverter << (sal_uInt32)0;
789cdf0e10cSrcweir 				aConverter.Seek( 64 );
790cdf0e10cSrcweir 			}
791cdf0e10cSrcweir 			else if( eType == FrameStyle_Gray )
792cdf0e10cSrcweir 			{
793cdf0e10cSrcweir  				aConverter.Seek( 10 );
794cdf0e10cSrcweir  				aConverter << (sal_uInt32)1084;
795cdf0e10cSrcweir 				aConverter.Seek( 28 );
796cdf0e10cSrcweir 				aConverter << (sal_uInt16) 8;
797cdf0e10cSrcweir 				aConverter.Seek( 54 );
798cdf0e10cSrcweir 				// write color table
799cdf0e10cSrcweir 				for( nLine = 0; nLine < 256; nLine++ )
800cdf0e10cSrcweir 				{
801cdf0e10cSrcweir 					aConverter << (sal_uInt8)nLine;
802cdf0e10cSrcweir 					aConverter << (sal_uInt8)nLine;
803cdf0e10cSrcweir 					aConverter << (sal_uInt8)nLine;
804cdf0e10cSrcweir 					aConverter << (sal_uInt8)0;
805cdf0e10cSrcweir 				}
806cdf0e10cSrcweir 				aConverter.Seek( 1084 );
807cdf0e10cSrcweir 			}
808cdf0e10cSrcweir 
809cdf0e10cSrcweir 			for( nLine = nHeight-1;
810cdf0e10cSrcweir 				 nLine >= 0; nLine-- )
811cdf0e10cSrcweir 			{
812cdf0e10cSrcweir 				fseek( pFrame, nLine * aParams.bytes_per_line, SEEK_SET );
813cdf0e10cSrcweir 				if( eType == FrameStyle_BW ||
814cdf0e10cSrcweir 					( eType == FrameStyle_Gray && aParams.depth == 8 )
815cdf0e10cSrcweir 					)
816cdf0e10cSrcweir 				{
817cdf0e10cSrcweir 					fread( pBuffer, 1, aParams.bytes_per_line, pFrame );
818cdf0e10cSrcweir 					aConverter.Write( pBuffer, aParams.bytes_per_line );
819cdf0e10cSrcweir 				}
820cdf0e10cSrcweir 				else if( eType == FrameStyle_Gray )
821cdf0e10cSrcweir 				{
822cdf0e10cSrcweir 					for( i = 0; i < (aParams.pixels_per_line); i++ )
823cdf0e10cSrcweir 					{
824cdf0e10cSrcweir 						sal_uInt8 nGray = _ReadValue( pFrame, aParams.depth );
825cdf0e10cSrcweir 						aConverter << nGray;
826cdf0e10cSrcweir 					}
827cdf0e10cSrcweir 				}
828cdf0e10cSrcweir 				else if( eType == FrameStyle_RGB )
829cdf0e10cSrcweir 				{
830cdf0e10cSrcweir 					for( i = 0; i < (aParams.pixels_per_line); i++ )
831cdf0e10cSrcweir 					{
832cdf0e10cSrcweir 						sal_uInt8 nRed, nGreen, nBlue;
833cdf0e10cSrcweir 						nRed	= _ReadValue( pFrame, aParams.depth );
834cdf0e10cSrcweir 						nGreen	= _ReadValue( pFrame, aParams.depth );
835cdf0e10cSrcweir 						nBlue	= _ReadValue( pFrame, aParams.depth );
836cdf0e10cSrcweir 						aConverter << nBlue;
837cdf0e10cSrcweir 						aConverter << nGreen;
838cdf0e10cSrcweir 						aConverter << nRed;
839cdf0e10cSrcweir 					}
840cdf0e10cSrcweir 				}
841cdf0e10cSrcweir 				else if( eType == FrameStyle_Separated )
842cdf0e10cSrcweir 				{
843cdf0e10cSrcweir 					for( i = 0; i < (aParams.pixels_per_line); i++ )
844cdf0e10cSrcweir 					{
845cdf0e10cSrcweir 						sal_uInt8 nValue = _ReadValue( pFrame, aParams.depth );
846cdf0e10cSrcweir 						switch( aParams.format )
847cdf0e10cSrcweir 						{
848cdf0e10cSrcweir 							case SANE_FRAME_RED:
849cdf0e10cSrcweir 								aConverter.SeekRel( 2 );
850cdf0e10cSrcweir 								aConverter << nValue;
851cdf0e10cSrcweir 								break;
852cdf0e10cSrcweir 							case SANE_FRAME_GREEN:
853cdf0e10cSrcweir 								aConverter.SeekRel( 1 );
854cdf0e10cSrcweir 								aConverter << nValue;
855cdf0e10cSrcweir 								aConverter.SeekRel( 1 );
856cdf0e10cSrcweir 								break;
857cdf0e10cSrcweir 							case SANE_FRAME_BLUE:
858cdf0e10cSrcweir 								aConverter << nValue;
859cdf0e10cSrcweir 								aConverter.SeekRel( 2 );
860cdf0e10cSrcweir 								break;
861cdf0e10cSrcweir                             case SANE_FRAME_GRAY:
862cdf0e10cSrcweir                             case SANE_FRAME_RGB:
863cdf0e10cSrcweir                                 break;
864cdf0e10cSrcweir 						}
865cdf0e10cSrcweir 					}
866cdf0e10cSrcweir 				}
867cdf0e10cSrcweir  				int nGap = aConverter.Tell() & 3;
868cdf0e10cSrcweir  				if( nGap )
869cdf0e10cSrcweir  					aConverter.SeekRel( 4-nGap );
870cdf0e10cSrcweir 			}
871cdf0e10cSrcweir 			fclose( pFrame ); // deletes tmpfile
872cdf0e10cSrcweir 			if( eType != FrameStyle_Separated )
873cdf0e10cSrcweir 				break;
874cdf0e10cSrcweir 		}
875cdf0e10cSrcweir 		else
876cdf0e10cSrcweir 			bSuccess = sal_False;
877cdf0e10cSrcweir 	}
878cdf0e10cSrcweir 	// get stream length
879cdf0e10cSrcweir 	aConverter.Seek( STREAM_SEEK_TO_END );
880cdf0e10cSrcweir 	int nPos = aConverter.Tell();
881cdf0e10cSrcweir 
882cdf0e10cSrcweir 	aConverter.Seek( 2 );
883cdf0e10cSrcweir 	aConverter << (sal_uInt32) nPos+1;
884cdf0e10cSrcweir 	aConverter.Seek( 0 );
885cdf0e10cSrcweir 
886cdf0e10cSrcweir 	rBitmap.unlock();
887cdf0e10cSrcweir 
888cdf0e10cSrcweir 	if( bSuccess )
889cdf0e10cSrcweir 	{
890cdf0e10cSrcweir 		// only cancel a successful operation
891cdf0e10cSrcweir 		// sane disrupts memory else
892cdf0e10cSrcweir 		p_cancel( maHandle );
893cdf0e10cSrcweir 		CheckConsistency( "sane_cancel" );
894cdf0e10cSrcweir 	}
895cdf0e10cSrcweir 	if( pBuffer )
896cdf0e10cSrcweir 		delete [] pBuffer;
897cdf0e10cSrcweir 
898cdf0e10cSrcweir 	ReloadOptions();
899cdf0e10cSrcweir 
900cdf0e10cSrcweir 
901cdf0e10cSrcweir 	dbg_msg( "Sane::Start returns with %s\n", bSuccess ? "TRUE" : "FALSE" );
902cdf0e10cSrcweir 
903cdf0e10cSrcweir 	return bSuccess;
904cdf0e10cSrcweir }
905cdf0e10cSrcweir 
GetRange(int n,double * & rpDouble)906cdf0e10cSrcweir int Sane::GetRange( int n, double*& rpDouble )
907cdf0e10cSrcweir {
908cdf0e10cSrcweir 	if( mppOptions[n]->constraint_type != SANE_CONSTRAINT_RANGE &&
909cdf0e10cSrcweir 		mppOptions[n]->constraint_type != SANE_CONSTRAINT_WORD_LIST )
910cdf0e10cSrcweir 	{
911cdf0e10cSrcweir 		return -1;
912cdf0e10cSrcweir 	}
913cdf0e10cSrcweir 
914cdf0e10cSrcweir 	rpDouble = 0;
915cdf0e10cSrcweir 	int nItems, i;
916cdf0e10cSrcweir 	sal_Bool bIsFixed = mppOptions[n]->type == SANE_TYPE_FIXED ? sal_True : sal_False;
917cdf0e10cSrcweir 
918cdf0e10cSrcweir 	dbg_msg( "Sane::GetRange of option %s ", mppOptions[n]->name );
919cdf0e10cSrcweir 	if(mppOptions[n]->constraint_type == SANE_CONSTRAINT_RANGE )
920cdf0e10cSrcweir 	{
921cdf0e10cSrcweir 		double fMin, fMax, fQuant;
922cdf0e10cSrcweir 		if( bIsFixed )
923cdf0e10cSrcweir 		{
924cdf0e10cSrcweir 			fMin = SANE_UNFIX( mppOptions[n]->constraint.range->min );
925cdf0e10cSrcweir 			fMax = SANE_UNFIX( mppOptions[n]->constraint.range->max );
926cdf0e10cSrcweir 			fQuant = SANE_UNFIX( mppOptions[n]->constraint.range->quant );
927cdf0e10cSrcweir 		}
928cdf0e10cSrcweir 		else
929cdf0e10cSrcweir 		{
930cdf0e10cSrcweir 			fMin = (double)mppOptions[n]->constraint.range->min;
931cdf0e10cSrcweir 			fMax = (double)mppOptions[n]->constraint.range->max;
932cdf0e10cSrcweir 			fQuant = (double)mppOptions[n]->constraint.range->quant;
933cdf0e10cSrcweir 		}
934cdf0e10cSrcweir 		if( fQuant != 0.0 )
935cdf0e10cSrcweir 		{
936cdf0e10cSrcweir 			dbg_msg( "quantum range [ %lg ; %lg ; %lg ]\n",
937cdf0e10cSrcweir 					 fMin, fQuant, fMax );
938cdf0e10cSrcweir 			nItems = (int)((fMax - fMin)/fQuant)+1;
939cdf0e10cSrcweir 			rpDouble = new double[ nItems ];
940cdf0e10cSrcweir 			double fValue = fMin;
941cdf0e10cSrcweir 			for( i = 0; i < nItems; i++, fValue += fQuant )
942cdf0e10cSrcweir 				rpDouble[i] = fValue;
943cdf0e10cSrcweir 			rpDouble[ nItems-1 ] = fMax;
944cdf0e10cSrcweir 			return nItems;
945cdf0e10cSrcweir 		}
946cdf0e10cSrcweir 		else
947cdf0e10cSrcweir 		{
948cdf0e10cSrcweir 			dbg_msg( "normal range [ %lg %lg ]\n",
949cdf0e10cSrcweir 					 fMin, fMax );
950cdf0e10cSrcweir 			rpDouble = new double[2];
951cdf0e10cSrcweir 			rpDouble[0] = fMin;
952cdf0e10cSrcweir 			rpDouble[1] = fMax;
953cdf0e10cSrcweir 			return 0;
954cdf0e10cSrcweir 		}
955cdf0e10cSrcweir 	}
956cdf0e10cSrcweir 	else
957cdf0e10cSrcweir 	{
958cdf0e10cSrcweir 		nItems = mppOptions[n]->constraint.word_list[0];
959cdf0e10cSrcweir 		rpDouble = new double[nItems];
960cdf0e10cSrcweir 		for( i=0; i<nItems; i++ )
961cdf0e10cSrcweir 		{
962cdf0e10cSrcweir 			rpDouble[i] = bIsFixed ?
963cdf0e10cSrcweir 				SANE_UNFIX( mppOptions[n]->constraint.word_list[i+1] ) :
964cdf0e10cSrcweir 				(double)mppOptions[n]->constraint.word_list[i+1];
965cdf0e10cSrcweir 		}
966cdf0e10cSrcweir 		dbg_msg( "wordlist [ %lg ... %lg ]\n",
967cdf0e10cSrcweir 				 rpDouble[ 0 ], rpDouble[ nItems-1 ] );
968cdf0e10cSrcweir 		return nItems;
969cdf0e10cSrcweir 	}
970cdf0e10cSrcweir }
971cdf0e10cSrcweir 
972cdf0e10cSrcweir static const char *ppUnits[] = {
973cdf0e10cSrcweir 	"",
974cdf0e10cSrcweir 	"[Pixel]",
975cdf0e10cSrcweir 	"[Bit]",
976cdf0e10cSrcweir 	"[mm]",
977cdf0e10cSrcweir 	"[DPI]",
978cdf0e10cSrcweir 	"[%]",
979cdf0e10cSrcweir 	"[usec]"
980cdf0e10cSrcweir };
981cdf0e10cSrcweir 
GetOptionUnitName(int n)982cdf0e10cSrcweir String Sane::GetOptionUnitName( int n )
983cdf0e10cSrcweir {
984cdf0e10cSrcweir 	String aText;
985cdf0e10cSrcweir 	SANE_Unit nUnit = mppOptions[n]->unit;
986cdf0e10cSrcweir     size_t nUnitAsSize = (size_t)nUnit;
987*93ed1f29SArmin Le Grand     if (nUnitAsSize >= sizeof(ppUnits)/sizeof(ppUnits[0]))
988cdf0e10cSrcweir 		aText = String::CreateFromAscii( "[unknown units]" );
989cdf0e10cSrcweir 	else
990cdf0e10cSrcweir 		aText = String( ppUnits[ nUnit ], gsl_getSystemTextEncoding() );
991cdf0e10cSrcweir 	return aText;
992cdf0e10cSrcweir }
993cdf0e10cSrcweir 
ActivateButtonOption(int n)994cdf0e10cSrcweir sal_Bool Sane::ActivateButtonOption( int n )
995cdf0e10cSrcweir {
996cdf0e10cSrcweir 	SANE_Status nStatus = ControlOption( n, SANE_ACTION_SET_VALUE, NULL );
997cdf0e10cSrcweir 	if( nStatus != SANE_STATUS_GOOD )
998cdf0e10cSrcweir 		return sal_False;
999cdf0e10cSrcweir 	return sal_True;
1000cdf0e10cSrcweir }
1001