/** 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; }
int DeviceAttributes_ ( ppd_file_t * ppd, oyOptions_s * options, oyConfig_s * device, const char * ppd_file_location ) { oyOption_s * o = 0; int error = !device; oyOption_s * value3 = oyOptions_Find( options, "device_context", oyNAME_PATTERN ); const char * device_name = oyConfig_FindString( device, "device_name", 0 ); if(!error) { char * manufacturer= 0, * model=0, * serial=0, * device_settings = 0; const char * system_port = 0, * host = 0; const char * keyword = 0; ppd_attr_t * attrs = 0; int attr_n, i, j; char ** color_key_words = 0, * tmp = 0; int color_key_words_n = 0; if(!device_name && !value3 && !ppd_file_location && !ppd) { message(oyMSG_WARN, (oyStruct_s*)options, _DBG_FORMAT_ "The \"device_name\" and \"device_context\" is\n" " missed to select a appropriate device.", _DBG_ARGS_ ); error = 1; return error; } if(!ppd) { message( oyMSG_DBG, (oyStruct_s*)0, _DBG_FORMAT_ "\n" "No PPD obtained for ", _DBG_ARGS_, device_name ); error = -1; return error; } manufacturer = ppd->manufacturer; model = ppd->modelname; serial = 0; /* Not known at this time. */ system_port = device_name; host = cupsServer(); attrs = ppdFindAttr(ppd, "cupsICCProfile", 0); if(attrs && attrs->text) device_settings = attrs->text; if(error <= 0) { size_t size = 0; char * data = 0; oyConfig_s * d = device; oyRankMap * rank_map = oyRankMapCopy( oyConfig_GetRankMap( device ), oyAllocateFunc_ ); if(!rank_map) rank_map = oyRankMapCopy( _api8.rank_map, oyAllocateFunc_ ); OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), manufacturer ) OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), model ) OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), serial ) OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), system_port ) OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), host ) OPTIONS_ADD( oyConfig_GetOptions(d,"backend_core"), device_settings ) if (value3) { /* open the PPD data */ if(ppd_file_location) { FILE * fp = fopen( ppd_file_location, "r" ); size_t lsize = 0; /* Find the total size. */ fseek(fp , 0, SEEK_END); lsize = ftell(fp); rewind (fp); /* Create buffer to read contents into a profile. */ data = (char*) malloc (sizeof(char)*lsize + 1); if (data == NULL) fputs ("Unable to open PPD size.",stderr); size = fread( data, 1, lsize, fp); data[size] = 0; } if(!error && data && size) { o = oyOption_FromRegistration( CMM_BASE_REG OY_SLASH "device_context.PPD.text", 0 ); error = !o; if(!error) error = oyOption_SetFromData( o, data, size ); if(!error) oyOptions_MoveIn( *oyConfig_GetOptions(device,"data"), &o, -1 ); } } /* Collect all ColorKeyWords. */ attr_n = ppd->num_attrs; for(i = 0; i < attr_n; i++) { char key[16]; keyword = ppd->attrs[i]->name; /* we support keys beginning with ColorKeyWords, e.g. "ColorKeyWords" "ColorKeyWords" ... */ snprintf( &key[0], 16, "%s", keyword ); key[14] = 0; if (strcmp(key, "ColorKeyWords") == 0) { if( tmp && tmp[oyStrlen_(tmp) - 1] != ';' ) STRING_ADD( tmp, ";" ); STRING_ADD( tmp, ppd->attrs[i]->value ); } } if(tmp) { color_key_words = oyStringSplit( tmp, ';', &color_key_words_n, oyAllocateFunc_); oyDeAllocateFunc_( tmp ); tmp = 0; } /* add the key/value pairs to the devices backend_core options. */ for(j = 0; j < color_key_words_n; ++j) { const char * keyword = color_key_words[j], * value = NULL; ppd_choice_t * c = ppdFindMarkedChoice( ppd, keyword ); ppd_option_t * o = ppdFindOption( ppd, keyword ); char * reg_name = 0; /* take the marked choice */ if(c) value = c->choice; /* fall back to a default */ else if(o) value = o->defchoice; else /* Scan PPD attributes for matching the ColorKeyWords and */ for(i = 0; i < attr_n; i++) if(oyStrcmp_( ppd->attrs[i]->name, keyword ) == 0) value = ppd->attrs[i]->value; STRING_ADD( reg_name, CMM_BASE_REG OY_SLASH ); STRING_ADD( reg_name, keyword ); if(value) { error= oyOptions_SetFromText( oyConfig_GetOptions(d,"backend_core"), reg_name, value, OY_CREATE_NEW ); oyRankMapAppend( &rank_map, reg_name, 2, -2, 0, 0,0 ); } if(reg_name) oyDeAllocateFunc_( reg_name ); reg_name = 0; } if( color_key_words && color_key_words_n) oyStringListRelease_( &color_key_words, color_key_words_n, oyDeAllocateFunc_ ); else { ppd_option_t * o; while((o = ppdNextOption(ppd)) != 0) { const char * value = 0; char * reg_name = 0; keyword = o->keyword; STRING_ADD( reg_name, CMM_BASE_REG OY_SLASH ); STRING_ADD( reg_name, keyword ); /* take the marked choice */ for(i = 0; i < o->num_choices; ++i) if(o->choices[i].marked) { value = o->choices[i].choice; break; } if(!value) value = o->defchoice; if(value) { error = oyOptions_SetFromText( oyConfig_GetOptions(d,"backend_core"), reg_name, value, OY_CREATE_NEW ); oyRankMapAppend( &rank_map, reg_name, 2, -2, 0, 0,0 ); } if(reg_name) oyDeAllocateFunc_( reg_name ); reg_name = 0; } } oyConfig_SetRankMap( device, rank_map ); oyRankMapRelease( &rank_map, oyDeAllocateFunc_ ); }