Mercurial > geeqie.yaz
comparison src/metadata.c @ 1238:947e603a52c6
simplified metadata interface, dropped metadata_read,
fixes for older exiv2 versions
author | nadvornik |
---|---|
date | Sat, 10 Jan 2009 20:40:37 +0000 |
parents | 31f50c1b6a9a |
children | 30e207ac22e4 |
comparison
equal
deleted
inserted
replaced
1237:824a1e1775b8 | 1238:947e603a52c6 |
---|---|
323 } | 323 } |
324 } | 324 } |
325 | 325 |
326 fclose(f); | 326 fclose(f); |
327 | 327 |
328 *keywords = g_list_reverse(list); | 328 if (keywords) |
329 { | |
330 *keywords = g_list_reverse(list); | |
331 } | |
332 else | |
333 { | |
334 string_list_free(list); | |
335 } | |
336 | |
329 if (comment_build) | 337 if (comment_build) |
330 { | 338 { |
331 if (comment) | 339 if (comment) |
332 { | 340 { |
333 gint len; | 341 gint len; |
418 g_list_free(list); | 426 g_list_free(list); |
419 | 427 |
420 return g_list_reverse(newlist); | 428 return g_list_reverse(newlist); |
421 } | 429 } |
422 | 430 |
423 | 431 GList *metadata_read_list(FileData *fd, const gchar *key) |
424 static gint metadata_xmp_read(FileData *fd, GList **keywords, gchar **comment) | |
425 { | 432 { |
426 ExifData *exif; | 433 ExifData *exif; |
427 | 434 GList *list = NULL; |
428 exif = exif_read_fd(fd); | 435 if (!fd) return NULL; |
429 if (!exif) return FALSE; | 436 |
430 | 437 /* unwritten data overide everything */ |
431 if (comment) | 438 if (fd->modified_xmp) |
432 { | 439 { |
433 gchar *text; | 440 list = g_hash_table_lookup(fd->modified_xmp, key); |
434 ExifItem *item = exif_get_item(exif, COMMENT_KEY); | 441 if (list) return string_list_copy(list); |
435 | 442 } |
436 text = exif_item_get_string(item, 0); | 443 |
437 *comment = utf8_validate_or_convert(text); | 444 /* |
438 g_free(text); | 445 Legacy metadata file is the primary source if it exists. |
439 } | 446 Merging the lists does not make much sense, because the existence of |
440 | 447 legacy metadata file indicates that the other metadata sources are not |
441 if (keywords) | 448 writable and thus it would not be possible to delete the keywords |
442 { | 449 that comes from the image file. |
443 ExifItem *item; | 450 */ |
444 guint i; | 451 if (strcmp(key, KEYWORD_KEY) == 0) |
452 { | |
453 if (metadata_legacy_read(fd, &list, NULL)) return list; | |
454 } | |
455 | |
456 if (strcmp(key, COMMENT_KEY) == 0) | |
457 { | |
458 gchar *comment = NULL; | |
459 if (metadata_legacy_read(fd, NULL, &comment)) return g_list_append(NULL, comment); | |
460 } | |
461 | |
462 exif = exif_read_fd(fd); /* this is cached, thus inexpensive */ | |
463 if (!exif) return NULL; | |
464 list = exif_get_metadata(exif, key); | |
465 exif_free_fd(fd, exif); | |
466 return list; | |
467 } | |
468 | |
469 gchar *metadata_read_string(FileData *fd, const gchar *key) | |
470 { | |
471 GList *string_list = metadata_read_list(fd, key); | |
472 if (string_list) | |
473 { | |
474 gchar *str = string_list->data; | |
475 string_list->data = NULL; | |
476 string_list_free(string_list); | |
477 return str; | |
478 } | |
479 return NULL; | |
480 } | |
481 | |
482 gboolean metadata_append_string(FileData *fd, const gchar *key, const char *value) | |
483 { | |
484 gchar *str = metadata_read_string(fd, key); | |
485 | |
486 if (!str) | |
487 { | |
488 return metadata_write_string(fd, key, value); | |
489 } | |
490 else | |
491 { | |
492 gchar *new_string = g_strconcat(str, value, NULL); | |
493 gboolean ret = metadata_write_string(fd, key, new_string); | |
494 g_free(str); | |
495 g_free(new_string); | |
496 return ret; | |
497 } | |
498 } | |
499 | |
500 gboolean metadata_append_list(FileData *fd, const gchar *key, const GList *values) | |
501 { | |
502 GList *list = metadata_read_list(fd, key); | |
503 | |
504 if (!list) | |
505 { | |
506 return metadata_write_list(fd, key, values); | |
507 } | |
508 else | |
509 { | |
510 gboolean ret; | |
511 list = g_list_concat(list, string_list_copy(values)); | |
512 list = remove_duplicate_strings_from_list(list); | |
445 | 513 |
446 *keywords = NULL; | 514 ret = metadata_write_list(fd, key, list); |
447 item = exif_get_item(exif, KEYWORD_KEY); | 515 string_list_free(list); |
448 for (i = 0; i < exif_item_get_elements(item); i++) | 516 return ret; |
449 { | 517 } |
450 gchar *kw = exif_item_get_string(item, i); | |
451 gchar *utf8_kw; | |
452 | |
453 if (!kw) break; | |
454 | |
455 utf8_kw = utf8_validate_or_convert(kw); | |
456 *keywords = g_list_append(*keywords, (gpointer) utf8_kw); | |
457 g_free(kw); | |
458 } | |
459 | |
460 /* FIXME: | |
461 * Exiv2 handles Iptc keywords as multiple entries with the | |
462 * same key, thus exif_get_item returns only the first keyword | |
463 * and the only way to get all keywords is to iterate through | |
464 * the item list. | |
465 */ | |
466 /* Read IPTC keywords only if there are no XMP keywords | |
467 * IPTC does not have standard charset, thus the encoding may differ | |
468 * from XMP and keyword merging is not reliable. | |
469 */ | |
470 if (!*keywords) | |
471 { | |
472 for (item = exif_get_first_item(exif); | |
473 item; | |
474 item = exif_get_next_item(exif)) | |
475 { | |
476 guint tag; | |
477 | |
478 tag = exif_item_get_tag_id(item); | |
479 if (tag == 0x0019) | |
480 { | |
481 gchar *tag_name = exif_item_get_tag_name(item); | |
482 | |
483 if (strcmp(tag_name, "Iptc.Application2.Keywords") == 0) | |
484 { | |
485 gchar *kw; | |
486 gchar *utf8_kw; | |
487 | |
488 kw = exif_item_get_data_as_text(item); | |
489 if (!kw) continue; | |
490 | |
491 utf8_kw = utf8_validate_or_convert(kw); | |
492 *keywords = g_list_append(*keywords, (gpointer) utf8_kw); | |
493 g_free(kw); | |
494 } | |
495 g_free(tag_name); | |
496 } | |
497 } | |
498 } | |
499 } | |
500 | |
501 exif_free_fd(fd, exif); | |
502 | |
503 return (comment && *comment) || (keywords && *keywords); | |
504 } | |
505 | |
506 gint metadata_read(FileData *fd, GList **keywords, gchar **comment) | |
507 { | |
508 GList *keywords_xmp = NULL; | |
509 GList *keywords_legacy = NULL; | |
510 gchar *comment_xmp = NULL; | |
511 gchar *comment_legacy = NULL; | |
512 gint result_xmp, result_legacy; | |
513 | |
514 if (!fd) return FALSE; | |
515 | |
516 result_xmp = metadata_xmp_read(fd, &keywords_xmp, &comment_xmp); | |
517 result_legacy = metadata_legacy_read(fd, &keywords_legacy, &comment_legacy); | |
518 | |
519 if (!result_xmp && !result_legacy) | |
520 { | |
521 return FALSE; | |
522 } | |
523 | |
524 if (keywords) | |
525 { | |
526 if (result_xmp && result_legacy) | |
527 *keywords = g_list_concat(keywords_xmp, keywords_legacy); | |
528 else | |
529 *keywords = result_xmp ? keywords_xmp : keywords_legacy; | |
530 | |
531 *keywords = remove_duplicate_strings_from_list(*keywords); | |
532 } | |
533 else | |
534 { | |
535 if (result_xmp) string_list_free(keywords_xmp); | |
536 if (result_legacy) string_list_free(keywords_legacy); | |
537 } | |
538 | |
539 | |
540 if (comment) | |
541 { | |
542 if (result_xmp && result_legacy && comment_xmp && comment_legacy && *comment_xmp && *comment_legacy) | |
543 *comment = g_strdup_printf("%s\n%s", comment_xmp, comment_legacy); | |
544 else | |
545 *comment = result_xmp ? comment_xmp : comment_legacy; | |
546 } | |
547 | |
548 if (result_xmp && (!comment || *comment != comment_xmp)) g_free(comment_xmp); | |
549 if (result_legacy && (!comment || *comment != comment_legacy)) g_free(comment_legacy); | |
550 | |
551 // return FALSE in the following cases: | |
552 // - only looking for a comment and didn't find one | |
553 // - only looking for keywords and didn't find any | |
554 // - looking for either a comment or keywords, but found nothing | |
555 if ((!keywords && comment && !*comment) || | |
556 (!comment && keywords && !*keywords) || | |
557 ( comment && !*comment && keywords && !*keywords)) | |
558 return FALSE; | |
559 | |
560 return TRUE; | |
561 } | |
562 | |
563 void metadata_set(FileData *fd, GList *new_keywords, gchar *new_comment, gboolean append) | |
564 { | |
565 gchar *comment = NULL; | |
566 GList *keywords = NULL; | |
567 GList *keywords_list = NULL; | |
568 | |
569 metadata_read(fd, &keywords, &comment); | |
570 | |
571 if (new_comment) | |
572 { | |
573 if (append && comment && *comment) | |
574 { | |
575 gchar *tmp = comment; | |
576 | |
577 comment = g_strconcat(tmp, new_comment, NULL); | |
578 g_free(tmp); | |
579 } | |
580 else | |
581 { | |
582 g_free(comment); | |
583 comment = g_strdup(new_comment); | |
584 } | |
585 } | |
586 | |
587 if (new_keywords) | |
588 { | |
589 if (append && keywords && g_list_length(keywords) > 0) | |
590 { | |
591 GList *work; | |
592 | |
593 work = new_keywords; | |
594 while (work) | |
595 { | |
596 gchar *key; | |
597 GList *p; | |
598 | |
599 key = work->data; | |
600 work = work->next; | |
601 | |
602 p = keywords; | |
603 while (p && key) | |
604 { | |
605 gchar *needle = p->data; | |
606 p = p->next; | |
607 | |
608 if (strcmp(needle, key) == 0) key = NULL; | |
609 } | |
610 | |
611 if (key) keywords = g_list_append(keywords, g_strdup(key)); | |
612 } | |
613 keywords_list = keywords; | |
614 } | |
615 else | |
616 { | |
617 keywords_list = new_keywords; | |
618 } | |
619 } | |
620 | |
621 metadata_write_string(fd, COMMENT_KEY, comment); | |
622 metadata_write_list(fd, KEYWORD_KEY, keywords); | |
623 | |
624 string_list_free(keywords); | |
625 g_free(comment); | |
626 } | 518 } |
627 | 519 |
628 gboolean find_string_in_list(GList *list, const gchar *string) | 520 gboolean find_string_in_list(GList *list, const gchar *string) |
629 { | 521 { |
630 while (list) | 522 while (list) |
685 | 577 |
686 gboolean meta_data_get_keyword_mark(FileData *fd, gint n, gpointer data) | 578 gboolean meta_data_get_keyword_mark(FileData *fd, gint n, gpointer data) |
687 { | 579 { |
688 GList *keywords; | 580 GList *keywords; |
689 gboolean found = FALSE; | 581 gboolean found = FALSE; |
690 if (metadata_read(fd, &keywords, NULL)) | 582 keywords = metadata_read_list(fd, KEYWORD_KEY); |
583 if (keywords) | |
691 { | 584 { |
692 GList *work = keywords; | 585 GList *work = keywords; |
693 | 586 |
694 while (work) | 587 while (work) |
695 { | 588 { |
711 { | 604 { |
712 GList *keywords = NULL; | 605 GList *keywords = NULL; |
713 gboolean found = FALSE; | 606 gboolean found = FALSE; |
714 gboolean changed = FALSE; | 607 gboolean changed = FALSE; |
715 GList *work; | 608 GList *work; |
716 metadata_read(fd, &keywords, NULL); | 609 keywords = metadata_read_list(fd, KEYWORD_KEY); |
717 | 610 |
718 work = keywords; | 611 work = keywords; |
719 | 612 |
720 while (work) | 613 while (work) |
721 { | 614 { |