void babl_init_db (void) { const char *path = fish_cache_path (); long length = -1; char seps[] = "\n\r"; Babl *babl = NULL; char *contents = NULL; char *token; char *tokp; const Babl *from_format = NULL; const Babl *to_format = NULL; time_t tim = time (NULL); if (getenv ("BABL_DEBUG_CONVERSIONS")) return; babl_file_get_contents (path, &contents, &length, NULL); if (!contents) return; token = strtok_r (contents, seps, &tokp); while( token != NULL ) { switch (token[0]) { case '-': /* finalize */ if (babl) { if (((babl->fish.pixels + babl->fish.processings) % 100) == (tim % 100)) { /* 1% chance of individual cached conversions being dropped - * making sure mis-measured conversions do not stick around for a long time*/ babl_free (babl); } else babl_db_insert (babl_fish_db(), babl); } from_format = NULL; to_format = NULL; babl=NULL; break; case '#': /* if babl has changed in git .. drop whole cache */ { if (strcmp ( token, cache_header ())) { free (contents); return; } } break; case '\t': if (strchr (token, '=')) { char seps2[] = " "; char *tokp2; char *token2; char name[4096]; _babl_fish_create_name (name, from_format, to_format, 1); babl = babl_db_exist_by_name (babl_fish_db (), name); if (babl) { fprintf (stderr, "%s:%i: loading of cache failed\n", __FUNCTION__, __LINE__); return; } babl = babl_calloc (1, sizeof (BablFishPath) + strlen (name) + 1); babl_set_destructor (babl, _babl_fish_path_destroy); babl->class_type = BABL_FISH_PATH; babl->instance.id = babl_fish_get_id (from_format, to_format); babl->instance.name = ((char *) babl) + sizeof (BablFishPath); strcpy (babl->instance.name, name); babl->fish.source = from_format; babl->fish.destination = to_format; babl->fish_path.conversion_list = babl_list_init_with_size (10); token2 = strtok_r (&token[1], seps2, &tokp2); while( token2 != NULL ) { if (!strncmp (token2, "error=", 6)) { babl->fish.error = babl_parse_double (token2 + 6); } else if (!strncmp (token2, "cost=", 5)) { babl->fish_path.cost = babl_parse_double (token2 + 5); } else if (!strncmp (token2, "pixels=", 7)) { babl->fish.pixels = strtol (token2 + 7, NULL, 10); } else if (!strncmp (token2, "processings=", 12)) { babl->fish.processings = strtol (token2 + 12, NULL, 10); } token2 = strtok_r (NULL, seps2, &tokp2); } } else { Babl *conv = (void*)babl_db_find(babl_conversion_db(), &token[1]); if (!conv) { return; } else babl_list_insert_last (babl->fish_path.conversion_list, conv); } break; default: if (!from_format) { from_format = (void*)babl_db_find(babl_format_db(), token); if (!from_format) return; } else { to_format = (void*)babl_db_find(babl_format_db(), token); if (!to_format) return; } break; } token = strtok_r (NULL, seps, &tokp); } if (contents) free (contents); }
static void get_conversion_path (PathContext *pc, Babl *current_format, int current_length, int max_length) { if (current_length > max_length) { /* We have reached the maximum recursion * depth, let's bail out */ return; } else if ((current_length > 0) && (current_format == pc->to_format)) { /* We have found a candidate path, let's * see about it's properties */ double path_cost = 0.0; double ref_cost = 0.0; double path_error = 1.0; int i; for (i = 0; i < babl_list_size (pc->current_path); i++) { path_error *= (1.0 + babl_conversion_error ((BablConversion *) pc->current_path->items[i])); } if (path_error - 1.0 <= legal_error ()) /* check this before the next; which does a more accurate measurement of the error */ { FishPathInstrumentation fpi; memset (&fpi, 0, sizeof (fpi)); fpi.source = (Babl*) babl_list_get_first (pc->current_path)->conversion.source; fpi.destination = pc->to_format; get_path_instrumentation (&fpi, pc->current_path, &path_cost, &ref_cost, &path_error); if ((path_cost < ref_cost) && /* do not use paths that took longer to compute than reference */ (path_cost < pc->fish_path->fish_path.cost) && (path_error <= legal_error ())) { /* We have found the best path so far, * let's copy it into our new fish */ pc->fish_path->fish_path.cost = path_cost; pc->fish_path->fish.error = path_error; babl_list_copy (pc->current_path, pc->fish_path->fish_path.conversion_list); } destroy_path_instrumentation (&fpi); } } else { /* * Bummer, we have to search deeper... */ BablList *list; int i; list = current_format->format.from_list; if (list) { /* Mark the current format in conversion path as visited */ current_format->format.visited = 1; /* Iterate through unvisited formats from the current format ...*/ for (i = 0; i < babl_list_size (list); i++) { Babl *next_conversion = BABL (list->items[i]); Babl *next_format = BABL (next_conversion->conversion.destination); if (!next_format->format.visited) { /* next_format is not in the current path, we can pay a visit */ babl_list_insert_last (pc->current_path, next_conversion); get_conversion_path (pc, next_format, current_length + 1, max_length); babl_list_remove_last (pc->current_path); } } /* Remove the current format from current path */ current_format->format.visited = 0; } } }