diff options
Diffstat (limited to 'src/MediaMetadata.vala')
-rw-r--r-- | src/MediaMetadata.vala | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/MediaMetadata.vala b/src/MediaMetadata.vala new file mode 100644 index 0000000..ad0d719 --- /dev/null +++ b/src/MediaMetadata.vala @@ -0,0 +1,128 @@ +/* Copyright 2010-2014 Yorba Foundation + * + * This software is licensed under the GNU Lesser General Public License + * (version 2.1 or later). See the COPYING file in this distribution. + */ + +public abstract class MediaMetadata { + public MediaMetadata() { + } + + public abstract void read_from_file(File file) throws Error; + + public abstract MetadataDateTime? get_creation_date_time(); + + public abstract string? get_title(); + + public abstract string? get_comment(); +} + +public struct MetadataRational { + public int numerator; + public int denominator; + + public MetadataRational(int numerator, int denominator) { + this.numerator = numerator; + this.denominator = denominator; + } + + private bool is_component_valid(int component) { + return (component >= 0) && (component <= 1000000); + } + + public bool is_valid() { + return (is_component_valid(numerator) && is_component_valid(denominator)); + } + + public string to_string() { + return (is_valid()) ? ("%d/%d".printf(numerator, denominator)) : ""; + } +} + +public errordomain MetadataDateTimeError { + INVALID_FORMAT, + UNSUPPORTED_FORMAT +} + +public class MetadataDateTime { + + private time_t timestamp; + + public MetadataDateTime(time_t timestamp) { + this.timestamp = timestamp; + } + + public MetadataDateTime.from_exif(string label) throws MetadataDateTimeError { + if (!from_exif_date_time(label, out timestamp)) + throw new MetadataDateTimeError.INVALID_FORMAT("%s is not EXIF format date/time", label); + } + + public MetadataDateTime.from_iptc(string date, string time) throws MetadataDateTimeError { + // TODO: Support IPTC date/time format + throw new MetadataDateTimeError.UNSUPPORTED_FORMAT("IPTC date/time format not currently supported"); + } + + public MetadataDateTime.from_xmp(string label) throws MetadataDateTimeError { + TimeVal time_val = TimeVal(); + if (!time_val.from_iso8601(label)) + throw new MetadataDateTimeError.INVALID_FORMAT("%s is not XMP format date/time", label); + + timestamp = time_val.tv_sec; + } + + public time_t get_timestamp() { + return timestamp; + } + + public string get_exif_label() { + return to_exif_date_time(timestamp); + } + + // TODO: get_iptc_date() and get_iptc_time() + + public string get_xmp_label() { + TimeVal time_val = TimeVal(); + time_val.tv_sec = timestamp; + time_val.tv_usec = 0; + + return time_val.to_iso8601(); + } + + public static bool from_exif_date_time(string date_time, out time_t timestamp) { + timestamp = 0; + + Time tm = Time(); + + // Check standard EXIF format + if (date_time.scanf("%d:%d:%d %d:%d:%d", + &tm.year, &tm.month, &tm.day, &tm.hour, &tm.minute, &tm.second) != 6) { + // Fallback in a more generic format + string tmp = date_time.dup(); + tmp.canon("0123456789", ' '); + if (tmp.scanf("%4d%2d%2d%2d%2d%2d", + &tm.year, &tm.month, &tm.day, &tm.hour, &tm.minute,&tm.second) != 6) + return false; + } + + // watch for bogosity + if (tm.year <= 1900 || tm.month <= 0 || tm.day < 0 || tm.hour < 0 || tm.minute < 0 || tm.second < 0) + return false; + + tm.year -= 1900; + tm.month--; + tm.isdst = -1; + + timestamp = tm.mktime(); + + return true; + } + + public static string to_exif_date_time(time_t timestamp) { + return Time.local(timestamp).format("%Y:%m:%d %H:%M:%S"); + } + + public string to_string() { + return to_exif_date_time(timestamp); + } +} + |