diff --git a/src/modules/SANE/sane.c b/src/modules/SANE/sane.c index 490a6402ce6c46af6703cde46243cf68bb0271cc..f4d518dc268c562997d6fed21a95b605bc107e1d 100644 --- a/src/modules/SANE/sane.c +++ b/src/modules/SANE/sane.c @@ -8,6 +8,7 @@ #include <sane.h> #endif #endif +#include <stdio.h> #include "global.h" #include "stralloc.h" @@ -21,6 +22,7 @@ #include "error.h" #include "mapping.h" #include "multiset.h" +#include "backend.h" #include "operators.h" #include "module_support.h" #include "builtin_functions.h" @@ -353,6 +355,8 @@ static void assert_image_program() image_program = program_from_svalue( sp - 1 ); sp--;/* Do not free image program.. */ } + if( !image_program ) + error("No Image.Image?!\n"); } static void f_scanner_simple_scan( INT32 args ) @@ -468,6 +472,141 @@ static void f_scanner_row_scan( INT32 args ) push_int( 0 ); } +struct row_scan_struct +{ + SANE_Handle h; + SANE_Parameters p; + rgb_group *r; + struct object *o; + struct object *t; + int current_row; + char *buffer; + int bufferpos, nonblocking; + struct svalue callback; +}; + +static void nonblocking_row_scan_callback( int fd, void *_c ) +{ + struct row_scan_struct *c = (struct row_scan_struct *)_c; + int done = 0; + int nbytes; + + do + { + int ec; + THREADS_ALLOW(); + if( (ec = sane_read( c->h, c->buffer+c->bufferpos, + c->p.bytes_per_line-c->bufferpos, &nbytes) ) ) + { + done = 1; + } + else + { + c->bufferpos += nbytes; + if( c->bufferpos == c->p.bytes_per_line ) + { + int i; + switch( c->p.format ) + { + case SANE_FRAME_GRAY: + for( i=0; i<c->p.bytes_per_line; i++ ) + { + c->r[i].r = c->buffer[i]; + c->r[i].g = c->buffer[i]; + c->r[i].b = c->buffer[i]; + } + break; + case SANE_FRAME_RGB: + MEMCPY( (char *)c->r, c->buffer, c->p.bytes_per_line ); + break; + default:break; + } + c->bufferpos=0; + } + } + THREADS_DISALLOW(); + + if( !nbytes || c->bufferpos ) + return; /* await more data */ + + c->current_row++; + + if( c->current_row == c->p.lines ) + done = 1; + + ref_push_object( c->o ); + push_int( c->current_row-1 ); + ref_push_object( c->t ); + push_int( done ); + apply_svalue( &c->callback, 4 ); + pop_stack(); + } while( c->nonblocking && !done ); + + if( done ) + { + set_read_callback( fd, 0, 0 ); + free_object( c->o ); + free_object( c->t ); + free_svalue( &c->callback ); + free( c->buffer ); + free( c ); + } +} + +static void f_scanner_nonblocking_row_scan( INT32 args ) +{ + SANE_Parameters p; + SANE_Handle h = THIS->h; + struct svalue *s; + int fd; + struct row_scan_struct *rsp; + + if( sane_start( THIS->h ) ) error("Start failed\n"); + if( sane_get_parameters( THIS->h, &p ) ) error("Get parameters failed\n"); + if( p.depth != 8 ) error("Sorry, only depth 8 supported right now.\n"); + + switch( p.format ) + { + case SANE_FRAME_GRAY: + case SANE_FRAME_RGB: + break; + case SANE_FRAME_RED: + case SANE_FRAME_GREEN: + case SANE_FRAME_BLUE: + error("Composite frame mode not supported for row_scan\n"); + break; + } + + assert_image_program(); + + rsp = malloc( sizeof(struct row_scan_struct) ); + push_int( p.pixels_per_line ); + push_int( 1 ); + rsp->o = clone_object( image_program, 2 ); + rsp->t = fp->current_object; + fp->current_object->refs++; + rsp->r = ((struct image *)rsp->o->storage)->img; + rsp->h = THIS->h; + rsp->p = p; + rsp->buffer = malloc( p.bytes_per_line ); + rsp->current_row = 0; + rsp->bufferpos = 0; + rsp->callback = sp[-1]; + rsp->nonblocking = !sane_set_io_mode( THIS->h, 1 ); + sp--; + + if( sane_get_select_fd( THIS->h, &fd ) ) + { + free_object( rsp->o ); + free_object( rsp->t ); + free( rsp->buffer ); + free( rsp ); + error("Failed to get select fd for scanning device!\n"); + } + set_read_callback( fd, nonblocking_row_scan_callback, (void*)rsp ); + push_int( 0 ); +} + static void f_scanner_cancel_scan( INT32 args ) { sane_cancel( THIS->h ); @@ -484,14 +623,19 @@ static void exit_scanner_struct( struct object *p ) sane_close( THIS->h ); } - - void pike_module_init() { struct program *p; add_function( "list_scanners", f_list_scanners, "function(void:array(mapping))", 0 ); + add_integer_constant( "FrameGray", SANE_FRAME_GRAY,0 ); + add_integer_constant( "FrameRGB", SANE_FRAME_RGB,0 ); + add_integer_constant( "FrameRed", SANE_FRAME_RED,0 ); + add_integer_constant( "FrameGreen",SANE_FRAME_GREEN,0 ); + add_integer_constant( "FrameBlue", SANE_FRAME_BLUE,0 ); + + start_new_program(); ADD_STORAGE( struct scanner ); add_function( "get_option", f_scanner_get_option, @@ -507,6 +651,9 @@ void pike_module_init() add_function( "row_scan", f_scanner_row_scan, "function(function(object,int,object:void):void)", 0 ); + add_function( "nonblocking_row_scan", f_scanner_nonblocking_row_scan, + "function(function(object,int,object,int:void):void)", 0 ); + add_function( "cancel_scan", f_scanner_cancel_scan, "function(void:object)", 0 ); @@ -514,7 +661,7 @@ void pike_module_init() "function(void:mapping)", 0 ); add_function( "create", f_scanner_create, - "function(string:void)", 0 ); + "function(string:void)", ID_STATIC ); set_init_callback(init_scanner_struct); set_exit_callback(exit_scanner_struct);