static void SaneDev_dealloc(SaneDevObject *self) { if (self->h) sane_close(self->h); self->h=NULL; PyObject_DEL(self); }
static void deAlloc (_ScanDevice * self) { if (self->h) sane_close (self->h); self->h = NULL; PyObject_DEL (self); }
static PyObject * SaneDev_close(SaneDevObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) return NULL; if (self->h) sane_close(self->h); self->h=NULL; Py_INCREF(Py_None); return (Py_None); }
static void sane_idadone(void *data) { struct sane_state *h = data; sane_cancel(h->sane); sane_close(h->sane); sane_exit(); free(h->buf); free(h); }
void sane_exit (void) { struct device *dev; for (dev = devices_head; dev; dev = dev->next) if (dev->dn != -1) sane_close(dev); /* implies flush */ free_devices (); }
static PyObject *closeScan (_ScanDevice * self, PyObject * args) { if (!PyArg_ParseTuple (args, "")) return NULL; if (self->h) sane_close (self->h); self->h = NULL; Py_INCREF (Py_None); return (Py_None); }
void sane_exit (void) { DBG (DBG_proc, "sane_exit: enter\n"); while (first_dev) { sane_close (first_dev); } if (devlist) { free (devlist); devlist = NULL; } DBG (DBG_proc, "sane_exit: exit\n"); }
void sane_exit( void ) { ST400_Device *dev; DBG(DCODE, "sane_exit()\n"); while( (dev = st400_devices) != NULL ) { st400_devices = dev->next; sane_close(dev); free((char *)(dev->sane.name)); free(dev); } st400_num_devices = 0; if( st400_device_array ) { DBG(DCODE, "sane_exit: freeing device array\n"); free(st400_device_array); st400_device_array = NULL; st400_status.array_valid = 0; } }
/** Function Configs_Modify * @brief oyCMMapi8_s SANE scanner manipulation * * @version Oyranos: 0.1.10 * @since 2009/01/19 (Oyranos: 0.1.10) * @date 2009/08/21 * * \todo { Test } */ int Configs_Modify(oyConfigs_s * devices, oyOptions_s * options) { oyOption_s *version_opt = NULL; oyOption_s *version_opt_dev = NULL; oyConfig_s *device = NULL; int num_devices, g_error = 0; int call_sane_exit = 0; const char *command_list = NULL, *command_properties = NULL; oyAlloc_f allocateFunc = malloc; printf(PRFX "Entering %s(). Options:\n%s", __func__, oyOptions_GetText(options, oyNAME_NICK)); /* "error handling" section */ if (!devices || !oyConfigs_Count(devices)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n " "No devices given! Options:\n%s", _DBG_ARGS_, oyOptions_GetText(options, oyNAME_NICK) ); return 1; } /* "help" call section */ if (oyOptions_FindString(options, "command", "help") || !options || !oyOptions_Count(options)) { /** oyMSG_WARN should make shure our message is visible. */ ConfigsFromPatternUsage((oyStruct_s *) options); return 0; } num_devices = oyConfigs_Count(devices); command_list = oyOptions_FindString(options, "command", "list"); command_properties = oyOptions_FindString(options, "command", "properties"); /* Now we get some options [IN], and we already have some devices with * possibly already assigned options. Those provided through the input * oyOptions_s should take presedence over ::data & ::backend_core ones. * OTOH, all device_* options have a 1-1 relationship meaning if * one changes, probably all other should. So the simplest [naive] approach * would be to ignore all device_* options [IN] that are already in device. * Except from driver_version which has a special meaning. */ /* Handle "driver_version" option [IN] */ /* Check the first device to see if a positive driver_version is provided. */ /* If not, consult the input options */ device = oyConfigs_Get(devices, 0); version_opt_dev = oyConfig_Find(device, "driver_version"); if (version_opt_dev && oyOption_GetValueInt(version_opt_dev, 0) > 0) call_sane_exit = 0; else check_driver_version(options, &version_opt, &call_sane_exit); oyConfig_Release(&device); oyOption_Release(&version_opt_dev); if (command_list) { /* "list" call section */ int i; for (i = 0; i < num_devices; ++i) { const SANE_Device *device_context = NULL; SANE_Status status = SANE_STATUS_INVAL; oyOption_s *name_opt_dev = NULL, *handle_opt_dev = NULL, *context_opt_dev = NULL; const char *sane_name = NULL, *sane_model = NULL; int error = 0; device = oyConfigs_Get(devices, i); if(oyOptions_Count(*oyConfig_GetOptions(device,"backend_core"))) printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK)); if(oyOptions_Count(*oyConfig_GetOptions(device,"data"))) printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK)); /*Ignore device without a device_name*/ if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_name\" is missing from config object!"); oyConfig_Release(&device); g_error++; continue; } /*Handle "driver_version" option [OUT] */ version_opt_dev = oyConfig_Find(device, "driver_version"); if (!version_opt_dev && version_opt) oyOptions_MoveIn(*oyConfig_GetOptions(device,"backend_core"), &version_opt, -1); oyOption_Release(&version_opt_dev); /*Handle "device_context" option */ /*This is always provided by Configs_FromPattern() * [or should be alternatively by the user]. * Configs_Modify() will not scan for SANE devices * because it takes too long*/ context_opt_dev = oyConfig_Find(device, "device_context"); if (!context_opt_dev) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" option is missing!"); error = g_error = 1; } if (!error) { device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc); sane_name = device_context->name; sane_model = device_context->model; } /*Handle "oyNAME_NAME" option */ name_opt_dev = oyConfig_Find(device, "oyNAME_NAME"); if (!error && !name_opt_dev && oyOptions_Find(options, "oyNAME_NAME", oyNAME_PATTERN)) oyOptions_SetFromString(oyConfig_GetOptions(device,"backend_core"), CMM_BASE_REG OY_SLASH "oyNAME_NAME", sane_model, OY_CREATE_NEW); /*Handle "device_handle" option */ handle_opt_dev = oyConfig_Find(device, "device_handle"); if (!error && !handle_opt_dev) { oyPointer_s *handle_ptr = NULL; SANE_Handle h; status = sane_open(sane_name, &h); if (status == SANE_STATUS_GOOD) { handle_ptr = oyPointer_New(0); oyPointer_Set(handle_ptr, "SANE", "handle", (oyPointer)h, "sane_release_handle", sane_release_handle); oyOptions_MoveInStruct(oyConfig_GetOptions(device,"data"), CMM_BASE_REG OY_SLASH "device_handle", (oyStruct_s **) &handle_ptr, OY_CREATE_NEW); } else printf(PRFX "Unable to open sane device \"%s\": %s\n", sane_name, sane_strstatus(status)); } /*Create static rank_map, if not already there*/ if (!oyConfig_GetRankMap( device)) oyConfig_SetRankMap( device, _api8.rank_map ); /*Cleanup*/ oyConfig_Release(&device); oyOption_Release(&context_opt_dev); oyOption_Release(&name_opt_dev); oyOption_Release(&handle_opt_dev); } } else if (command_properties) { /* "properties" call section */ int i; /*Return a full list of scanner H/W & * SANE driver S/W color options * with the according rank map */ for (i = 0; i < num_devices; ++i) { SANE_Device *device_context = NULL; SANE_Status status = SANE_STATUS_INVAL; SANE_Handle device_handle; oyOption_s *name_opt_dev = NULL, *handle_opt_dev = NULL, *context_opt_dev = NULL; oyConfig_s *device_new = NULL; char *device_name = NULL; /* All previous device properties are considered obsolete * and a new device is created. Basic options are moved from * the old to new device */ device = oyConfigs_Get(devices, i); device_new = oyConfig_FromRegistration(CMM_BASE_REG, 0); printf(PRFX "Backend core:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"backend_core"), oyNAME_NICK)); printf(PRFX "Data:\n%s", oyOptions_GetText(*oyConfig_GetOptions(device,"data"), oyNAME_NICK)); /*Ignore device without a device_name*/ if (!oyOptions_FindString(*oyConfig_GetOptions(device,"backend_core"), "device_name", NULL)) { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_name\" is NULL, or missing from config object!"); oyConfig_Release(&device); oyConfig_Release(&device_new); g_error++; continue; } /*Handle "driver_version" option [OUT] */ if (version_opt) { oyOption_s *tmp = oyOption_Copy(version_opt, 0); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &tmp, -1); } /* 1. Get the "device_name" from old device */ name_opt_dev = oyConfig_Find(device, "device_name"); device_name = oyOption_GetValueText(name_opt_dev, allocateFunc); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"backend_core"), &name_opt_dev, -1); /* 2. Get the "device_context" from old device */ /* It should be there, see "list" call above */ context_opt_dev = oyConfig_Find(device, "device_context"); if (context_opt_dev) { device_context = (SANE_Device*)oyOption_GetData(context_opt_dev, NULL, allocateFunc); if (device_context) { oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &context_opt_dev, -1); } else { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" is NULL!"); oyOption_Release(&context_opt_dev); g_error++; } } else { SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ ": %s\n", _DBG_ARGS_, "The \"device_context\" option is missing!"); g_error++; } /* 3. Get the scanner H/W properties from old device */ /* FIXME: we only recompute them, just in case they are not in old device */ if (device_context) { DeviceInfoFromContext_(device_context, oyConfig_GetOptions(device_new,"backend_core")); } /* 4. Get the "device_handle" from old device */ /* If not there, get one from SANE */ handle_opt_dev = oyConfig_Find(device, "device_handle"); if (handle_opt_dev) { oyPointer_s * oy_struct = (oyPointer_s*)oyOption_GetStruct( handle_opt_dev, oyOBJECT_POINTER_S ); device_handle = (SANE_Handle)oyPointer_GetPointer(oy_struct); oyPointer_Release( &oy_struct ); oyOptions_MoveIn(*oyConfig_GetOptions(device_new,"data"), &handle_opt_dev, -1); } else { printf(PRFX "Opening sane device \"%s\"..", device_name); fflush(NULL); status = sane_open( device_name, &device_handle ); if (status != SANE_STATUS_GOOD) printf("[FAIL: %s]\n", sane_strstatus(status)); else printf("[OK]\n"); } if (handle_opt_dev || status == SANE_STATUS_GOOD) { /* Use the device_handle to get the device color options */ ColorInfoFromHandle(device_handle, oyConfig_GetOptions(device_new,"backend_core")); /*5. Set the rank map*/ oyConfig_SetRankMap( device_new, _api8.rank_map ); } /*Cleanup*/ /* Remove old, add new device */ oyConfig_Release(&device); oyConfigs_ReleaseAt(devices, i); oyConfigs_MoveIn(devices, &device_new, -1); /*If we had to open a SANE device, we'll have to close it*/ if (status == SANE_STATUS_GOOD) { printf(PRFX "sane_close(%s)\n", device_name); sane_close(device_handle); } free(device_context); free(device_name); } } else { /*unsupported, wrong or no command */ SANE_msg(oyMSG_WARN, (oyStruct_s *) options, _DBG_FORMAT_ "\n " "No supported commands in options:\n%s", _DBG_ARGS_, oyOptions_GetText(options, oyNAME_NICK) ); ConfigsFromPatternUsage((oyStruct_s *) options); g_error = 1; } /*Cleanup*/ if (call_sane_exit) { printf(PRFX "sane_exit()\n"); sane_exit(); } oyOption_Release(&version_opt); printf(PRFX "Leaving %s\n", __func__); return g_error; }
// -------------------------------------------------------------- void ControlsWindow::MessageReceived ( BMessage * msg ) { switch (msg->what) { case SET_DEVICE_MSG: { ssize_t data_size; SANE_Status status; const SANE_Device * device_info; if ( msg->FindData("device", B_RAW_TYPE, (const void **) &device_info, &data_size) != B_OK ) break; m_device_info = device_info; if ( m_device ) sane_close(m_device); m_device = NULL; ScannerOptionView * option; BView * child; child = m_panel->ChildAt(0); while ( child ) { option = dynamic_cast<ScannerOptionView *>(child); if ( option ) option->RemoveSelf(); child = child->NextSibling(); }; status = sane_open(m_device_info->name, &m_device); if ( status != SANE_STATUS_GOOD ) { fprintf (stderr, "sane_open: %s\n", sane_strstatus (status)); BAlert * alert = new BAlert("sane_open", sane_strstatus(status), "Argh"); alert->Go(); break; }; const SANE_Option_Descriptor * desc; // m_options_lv->MakeEmpty(); printf("Options for device %s:\n", m_device_info->name); int opt = 1; // skip first option (option 0 = number of options) BRect r = m_panel->Bounds(); r.top = 80; r.InsetBy(8, 8); while ( (desc = sane_get_option_descriptor(m_device, opt)) != NULL ) { if (desc->type != SANE_TYPE_GROUP) { ScannerOptionView * ov = new ScannerOptionView(r, desc->name, B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT, 0, m_device, opt); if ( ov->Build() == B_OK ) { m_panel->AddChild(ov); r.top += ov->Bounds().Height(); m_tooltip->SetText(ov, desc->desc); } else delete ov; }; BString label; if (desc->type == SANE_TYPE_GROUP) label << "-- "; label << desc->title; if (desc->type == SANE_TYPE_GROUP) label << " --"; printf(" %d: name = %s\n" " title = %s\n" " desc = %s\n" " type = %d\n" " unit = %s\n" " size = %d\n" " cap = 0x%0x\n", opt, desc->name, desc->title, desc->desc, desc->type, get_unit2(desc->unit), desc->size, desc->cap); // m_options_lv->AddItem(new BStringItem(label.String())); opt++; }; BMessage * msg; msg = new BMessage(MainWindow::DEVICE_CHANGED_MSG); msg->AddString("device_name", m_device_info->name); m_parent_window->PostMessage(msg); delete msg; break; }; case SCAN_MSG: { SANE_Handle device; device = Device(); if ( ! device ) break; if ( m_scan_thread_id != -1 ) { // already launched... m_cancel_scan = true; break; }; m_cancel_scan = false; m_scan_thread_id = spawn_thread(_ScanThread, "scan", B_NORMAL_PRIORITY, this); resume_thread(m_scan_thread_id); break; }; default: inherited::MessageReceived(msg); } }
// -------------------------------------------------------------- ControlsWindow::~ControlsWindow() { if ( m_device ) sane_close(m_device); }
/* Open device, return the device handle */ SANE_Status sane_open (SANE_String_Const devname, SANE_Handle * handle) { unsigned i, j, id = 0; struct scanner *s; SANE_Int h, bus; SANE_Status st = SANE_STATUS_GOOD; if (!devlist) { st = sane_get_devices (NULL, 0); if (st) return st; } for (i = 0; devlist[i]; i++) { if (!strcmp (devlist[i]->name, devname)) break; } if (!devlist[i]) return SANE_STATUS_INVAL; for (j = 0; j < sizeof (known_devices) / sizeof (known_devices[0]); j++) { if (!strcmp (devlist[i]->model, known_devices[j].scanner.model)) { id = known_devices[j].id; break; } } st = sanei_usb_open (devname, &h); if (st == SANE_STATUS_ACCESS_DENIED) return st; if (st) { st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) { return st; } bus = SCSI; } else { bus = USB; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s = malloc (sizeof (struct scanner)); if (!s) return SANE_STATUS_NO_MEM; memset (s, 0, sizeof (struct scanner)); s->buffer = malloc (MAX_READ_DATA_SIZE + BULK_HEADER_SIZE); if (!s->buffer) return SANE_STATUS_NO_MEM; s->file = h; s->bus = bus; s->id = id; strcpy (s->name, devname); *handle = s; for (i = 0; i < 3; i++) { st = kvs40xx_test_unit_ready (s); if (st) { if (s->bus == SCSI) { sanei_scsi_close (s->file); st = sanei_scsi_open (devname, &h, kvs40xx_sense_handler, NULL); if (st) return st; } else { sanei_usb_release_interface (s->file, 0); sanei_usb_close (s->file); st = sanei_usb_open (devname, &h); if (st) return st; st = sanei_usb_claim_interface (h, 0); if (st) { sanei_usb_close (h); return st; } } s->file = h; } else break; } if (i == 3) return SANE_STATUS_DEVICE_BUSY; if (id == KV_S4085C || id == KV_S4065C) { char str[16]; st = inquiry (s, str); if (st) goto err; if (id == KV_S4085C) s->id = !strcmp (str, "KV-S4085CL") ? KV_S4085CL : KV_S4085CW; else s->id = !strcmp (str, "KV-S4065CL") ? KV_S4065CL : KV_S4065CW; } kvs40xx_init_options (s); st = kvs40xx_set_timeout (s, s->val[FEED_TIMEOUT].w); if (st) goto err; return SANE_STATUS_GOOD; err: sane_close (s); return st; }
static void* sane_idainit(FILE *fp, char *filename, unsigned int page, struct ida_image_info *info, int thumbnail) { const SANE_Option_Descriptor *opt; SANE_Int flags, count; struct sane_state *h; int rc,i,value,dpi = 0; h = malloc(sizeof(*h)); memset(h,0,sizeof(*h)); if (SANE_STATUS_GOOD != (rc = sane_init(NULL,NULL))) { fprintf(stderr,"sane_init: %s\n",sane_strstatus(rc)); goto oops; } if (SANE_STATUS_GOOD != (rc = sane_open(filename,&h->sane))) { fprintf(stderr,"sane_open: %s\n",sane_strstatus(rc)); goto oops; } /* set options */ opt = sane_get_option_descriptor(h->sane,0); rc = sane_control_option(h->sane, 0, SANE_ACTION_GET_VALUE, &count, &flags); for (i = 1; i < count; i++) { opt = sane_get_option_descriptor(h->sane,i); if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_TL_X)) { value = opt->constraint.range->min; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &value, &flags); } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_TL_Y)) { value = opt->constraint.range->min; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &value, &flags); } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_BR_X)) { value = opt->constraint.range->max; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &value, &flags); } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_BR_Y)) { value = opt->constraint.range->max; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &value, &flags); } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_PREVIEW)) { value = SANE_FALSE; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &value, &flags); } else if (opt->cap & SANE_CAP_AUTOMATIC) sane_control_option(h->sane, i, SANE_ACTION_SET_AUTO, NULL, &flags); if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_RESOLUTION)) { if (sane_res) { dpi = sane_res; sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE, &dpi, &flags); } sane_control_option(h->sane, i, SANE_ACTION_GET_VALUE, &dpi, &flags); } if (debug) dump_desc(h->sane,i,opt); } if (SANE_STATUS_GOOD != (rc = sane_start(h->sane))) { fprintf(stderr,"sane_start: %s\n",sane_strstatus(rc)); goto oops; } h->started = 1; if (SANE_STATUS_GOOD != (rc = sane_get_parameters(h->sane,&h->parm))) { fprintf(stderr,"sane_get_parameters: %s\n",sane_strstatus(rc)); goto oops; } if (h->parm.format != SANE_FRAME_GRAY && h->parm.format != SANE_FRAME_RGB) { fprintf(stderr,"sane: unsupported frame format (%d)\n",h->parm.format); goto oops; } if (h->parm.depth != 8) { fprintf(stderr,"sane: unsupported color depth (%d)\n",h->parm.depth); goto oops; } if (-1 == h->parm.lines) { fprintf(stderr,"sane: can't handle unknown image size\n"); goto oops; } info->width = h->parm.pixels_per_line; info->height = h->parm.lines; if (dpi) info->dpi = dpi; h->buf = malloc(h->parm.bytes_per_line * BUF_LINES); if (debug) fprintf(stderr,"sane: scanning %dx%d %s\n",info->width,info->height, (h->parm.format == SANE_FRAME_GRAY) ? "gray" : "color"); return h; oops: if (h->buf) free(h->buf); if (h->started) sane_cancel(h->sane); if (h->sane) sane_close(h->sane); sane_exit(); free(h); return NULL; }
extern char *internalGetScannerDetails(char *device, char *lang) { char *answer = NULL; SANE_Status status; char *deviceList = o_strdup("");; int hlp = 0, resolution = 300, minRes=50, maxRes=50, phashAvailable=0; char *resolution_s, *maxRes_s, *minRes_s; SANE_Handle *openDeviceHandle; o_log(DEBUGM, "sane_open of \"%s\"", device); status = sane_open (device, (SANE_Handle)&openDeviceHandle); if(status != SANE_STATUS_GOOD) { o_log(ERROR, "Could not open: '%s' with error: %s", device, sane_strstatus(status)); free(deviceList); return NULL; } // // Find resolution ranges // for (hlp = 0; hlp < 9999; hlp++) { const SANE_Option_Descriptor *sod; sod = sane_get_option_descriptor (openDeviceHandle, hlp); if (sod == NULL) break; // Just a placeholder if (sod->type == SANE_TYPE_GROUP || sod->name == NULL || hlp == 0) continue; if ( 0 == strcmp(sod->name, SANE_NAME_SCAN_RESOLUTION) ) { // Some kind of sliding range if (sod->constraint_type == SANE_CONSTRAINT_RANGE) { o_log(DEBUGM, "Resolution setting detected as 'range'"); // Fixed resolution if (sod->type == SANE_TYPE_FIXED) maxRes = (int)SANE_UNFIX (sod->constraint.range->max); else maxRes = sod->constraint.range->max; } // A fixed list of options else if (sod->constraint_type == SANE_CONSTRAINT_WORD_LIST) { int lastIndex = sod->constraint.word_list[0]; o_log(DEBUGM, "Resolution setting detected as 'word list': lastIndex = %d",lastIndex); // maxRes = sod->constraint.word_list[lastIndex]; // resolution list cannot be treated as low to high ordered list // remark: impl capability to select scan resolution in webInterface int n=0; maxRes = 0; for (n=1; n<=lastIndex; n++ ) { o_log(DEBUGM, "index results %d --> %d", n ,(int)sod->constraint.word_list[n]); if ( maxRes < sod->constraint.word_list[n] ) { maxRes=sod->constraint.word_list[n]; } } } break; // we've found our resolution - no need to search more } } o_log(DEBUGM, "Determined max resultion to be %d", maxRes); // Define a default if(resolution >= maxRes) resolution = maxRes; if(resolution <= minRes) resolution = minRes; o_log(DEBUGM, "sane_cancel"); sane_cancel(openDeviceHandle); o_log(DEBUGM, "sane_close"); sane_close(openDeviceHandle); // // What languages can we OCR for? // char *availableLangs = o_strdup(""); #ifdef CAN_OCR struct simpleLinkedList *languages = getOCRAvailableLanguages(); while (languages != NULL ) { if ( checkOCRLanguage( languages->data ) == 0 ) { o_concatf(&availableLangs, "<lang>%s</lang>", languages->data); } languages = sll_getNext(languages); } sll_destroy( languages ); #endif /* CAN_OCR */ // // Can we give the option of doing 'find simmilar'? // #ifdef CAN_PHASH phashAvailable = 1; #endif /* CAN_PHASH */ // Build Reply // resolution_s = itoa(resolution,10); maxRes_s = itoa(maxRes,10); minRes_s = itoa(minRes,10); o_concatf(&deviceList, "<Resolution><max>%s</max><min>%s</min><default>%s</default></Resolution><OCRLanguages>%s</OCRLanguages><phash>%d</phash>", maxRes_s, minRes_s, resolution_s, availableLangs, phashAvailable); free(maxRes_s); free(minRes_s); free(resolution_s); free(availableLangs); // The escaped string placeholder will be interprited in the sane dispatcher client answer = o_printf("<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerDetails>%s</ScannerDetails></Response>", deviceList); free(deviceList); return answer; }
char *internalDoScanningOperation(char *uuid, char *lang) { int request_resolution = 0; int docid; int current_page = 0; int total_requested_pages; double totbytes = 0; SANE_Status status; SANE_Handle *openDeviceHandle; SANE_Byte *raw_image; SANE_Parameters pars; char *docid_s; char *total_requested_pages_s; char *devName; char *outFilename; char *raw_image_format; char *header; o_log(DEBUGM, "doScanningOperation: sane initialized uuid(%s)",(char *)uuid); updateScanProgress(uuid, SCAN_WAITING_ON_SCANNER, 0); // Open the device devName = getScanParam(uuid, SCAN_PARAM_DEVNAME); o_log(DEBUGM, "sane_open of \"%s\"",devName); status = sane_open ((SANE_String_Const) devName, (SANE_Handle)&openDeviceHandle); if(status != SANE_STATUS_GOOD) { handleSaneErrors("Cannot open device ", devName, status, 0); updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status); free(devName); return 0; } free(devName); /* ========================================================== */ if ( ! setOptions( (char *)uuid, openDeviceHandle, &request_resolution ) ) return 0; o_log(DEBUGM, "sane_start: setOptions returned request_resolution %d\n",request_resolution); int timeout = 5; while( 0 < timeout ) { status = sane_start (openDeviceHandle); if(status == SANE_STATUS_GOOD) { break; } else { if(status == SANE_STATUS_DEVICE_BUSY ) { // BUSY signal could be the scanner just having a // bit of lag - specially network connected devices timeout--; if ( timeout == 0 ) { handleSaneErrors("Cannot start scanning", "even after trying several time", status, 0); updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status); return 0; } else { o_log(WARNING, "Device reports not ready to 'start', waiting 500ms. Will try another %d times", timeout); usleep(500 * 1000); // 500ms or 0.5sec } } else { handleSaneErrors("Cannot start scanning", "", status, 0); updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status); return 0; } } } // Get scanning params (from the scanner) if( request_resolution == 0 ) { o_log(DEBUGM, "Resolution did not get set in scanner setup."); updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10004); return 0; } o_log(DEBUGM, "Get scanning params"); status = sane_get_parameters (openDeviceHandle, &pars); o_log(INFORMATION, "Scanner Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d", sane_strstatus (status), pars.format, pars.last_frame, pars.bytes_per_line, pars.pixels_per_line, pars.lines, pars.depth); switch (pars.format) { case SANE_FRAME_GRAY: o_log(DEBUGM, "Expecting Gray data (1 channel only)."); raw_image_format = o_strdup( "P5" ); break; case SANE_FRAME_RGB: o_log(DEBUGM, "Expecting RGB data (3 channels)."); raw_image_format = o_strdup( "P6" ); break; default: o_log(DEBUGM, "backend returns three frames speratly. We do not currently support this."); updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10003); return 0; break; } header = o_printf ("%s\n# SANE data follows\n%d %d\n%d\n", raw_image_format, pars.pixels_per_line, pars.lines, (pars.depth <= 8) ? 255 : 65535); free( raw_image_format ); // Save Record // docid_s = getScanParam(uuid, SCAN_PARAM_DOCID); total_requested_pages_s = getScanParam(uuid, SCAN_PARAM_REQUESTED_PAGES); total_requested_pages = atoi(total_requested_pages_s); free(total_requested_pages_s); if( docid_s == NULL ) { o_log(DEBUGM, "Saving record"); updateScanProgress(uuid, SCAN_DB_WORKING, 0); docid_s = addNewScannedDoc(pars.lines, pars.pixels_per_line, request_resolution, total_requested_pages); setScanParam(uuid, SCAN_PARAM_DOCID, docid_s); setScanParam(uuid, SCAN_PARAM_ON_PAGE, "1"); current_page = 1; } else { char *current_page_s = getScanParam(uuid, SCAN_PARAM_ON_PAGE); current_page = atoi(current_page_s); free(current_page_s); current_page++; current_page_s = itoa(current_page, 10); setScanParam(uuid, SCAN_PARAM_ON_PAGE, current_page_s); free(current_page_s); } docid = atoi(docid_s); free(docid_s); totbytes = (double)((pars.bytes_per_line * pars.lines)); /* ========================================================== */ raw_image = collectData( (char *)uuid, openDeviceHandle, totbytes, pars.bytes_per_line, header ); o_log(INFORMATION, "Scanning done."); o_log(DEBUGM, "sane_cancel"); sane_cancel(openDeviceHandle); o_log(DEBUGM, "sane_close"); sane_close(openDeviceHandle); // Convert Raw into JPEG // updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 0); PIX *pix; if ( ( pix = pixReadMem( raw_image, (pars.bytes_per_line*pars.lines)+strlen(header) ) ) == NULL) { o_log(ERROR, "Could not load the image data into a PIX"); } updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 55); o_log(INFORMATION, "Convertion process: Loaded (depth: %d)", pixGetDepth(pix)); free(raw_image); free(header); outFilename = o_printf("%s/scans/%d_%d.jpg", BASE_DIR, docid, current_page); pixWrite(outFilename, pix, IFF_JFIF_JPEG); free(outFilename); updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 100); o_log(INFORMATION, "Conversion process: Complete"); // Do OCR - on this page // - OCR libs just wants the raw data and not the image header ocrImage( uuid, docid, current_page, request_resolution, pix, lang ); #ifdef CAN_PHASH // Calulate the pHash, so we can compare images later if( current_page == 1 ) { updateScanProgress(uuid, SCAN_CALULATING_PHASH, 0); unsigned long long hash = getImagePhash_px( pix ); savePhash( docid, hash ); } #endif /* CAN_PHASH */ pixDestroy( &pix ); // cleaup && What should we do next // o_log(DEBUGM, "mostly done."); if(current_page >= total_requested_pages) updateScanProgress(uuid, SCAN_FINISHED, docid); else updateScanProgress(uuid, SCAN_WAITING_ON_NEW_PAGE, ++current_page); o_log(DEBUGM, "Page scan done."); return o_strdup("OK"); }
void testsane (const char *dev_name) { int hlp, x; SANE_Status bla; SANE_Int blubb; SANE_Handle hand; SANE_Parameters pars; const SANE_Option_Descriptor *sod; const SANE_Device **device_list; char buffer[2048]; bla = sane_init (&blubb, auth_callback); fprintf (stderr, "Init : stat=%d ver=%x\nPress Enter to continue...", bla, blubb); getchar (); if (bla != SANE_STATUS_GOOD) return; bla = sane_get_devices (&device_list, SANE_FALSE); fprintf (stderr, "GetDev : stat=%s\n", sane_strstatus (bla)); if (bla != SANE_STATUS_GOOD) return; bla = sane_open (dev_name, &hand); fprintf (stderr, "Open : stat=%s hand=%p\n", sane_strstatus (bla), hand); if (bla != SANE_STATUS_GOOD) return; bla = sane_set_io_mode (hand, 0); fprintf (stderr, "SetIoMode : stat=%s\n", sane_strstatus (bla)); for (hlp = 0; hlp < 9999; hlp++) { sod = sane_get_option_descriptor (hand, hlp); if (sod == NULL) break; fprintf (stderr, "Gopt(%d) : stat=%p\n", hlp, sod); fprintf (stderr, "name : %s\n", sod->name); fprintf (stderr, "title: %s\n", sod->title); fprintf (stderr, "desc : %s\n", sod->desc); fprintf (stderr, "type : %d\n", sod->type); fprintf (stderr, "unit : %d\n", sod->unit); fprintf (stderr, "size : %d\n", sod->size); fprintf (stderr, "cap : %d\n", sod->cap); fprintf (stderr, "ctyp : %d\n", sod->constraint_type); switch (sod->constraint_type) { case SANE_CONSTRAINT_NONE: break; case SANE_CONSTRAINT_STRING_LIST: fprintf (stderr, "stringlist:\n"); break; case SANE_CONSTRAINT_WORD_LIST: fprintf (stderr, "wordlist (%d) : ", sod->constraint.word_list[0]); for (x = 1; x <= sod->constraint.word_list[0]; x++) fprintf (stderr, " %d ", sod->constraint.word_list[x]); fprintf (stderr, "\n"); break; case SANE_CONSTRAINT_RANGE: fprintf (stderr, "range: %d-%d %d \n", sod->constraint.range->min, sod->constraint.range->max, sod->constraint.range->quant); break; } } bla = sane_get_parameters (hand, &pars); fprintf (stderr, "Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d\n", sane_strstatus (bla), pars.format, pars.last_frame, pars.bytes_per_line, pars.pixels_per_line, pars.lines, pars.depth); if (bla != SANE_STATUS_GOOD) return; bla = sane_start (hand); fprintf (stderr, "Start : stat=%s\n", sane_strstatus (bla)); if (bla != SANE_STATUS_GOOD) return; do { bla = sane_read (hand, buffer, sizeof (buffer), &blubb); /*printf("Read : stat=%s len=%d\n",sane_strstatus (bla),blubb); */ if (bla != SANE_STATUS_GOOD) { if (bla == SANE_STATUS_EOF) break; return; } fwrite (buffer, 1, blubb, stdout); } while (1); sane_cancel (hand); fprintf (stderr, "Cancel.\n"); sane_close (hand); fprintf (stderr, "Close\n"); for (hlp = 0; hlp < 20; hlp++) fprintf (stderr, "STRS %d=%s\n", hlp, sane_strstatus (hlp)); fprintf (stderr, "Exit.\n"); }