1use libc::{c_char, c_int, size_t};
9
10pub mod consts;
11
12pub use consts::*;
13
14pub enum Xmp {}
15pub enum XmpFile {}
16pub enum XmpString {}
17pub enum XmpIterator {}
18
19#[derive(Clone, Copy, Eq, PartialEq, Debug)]
20#[repr(i32)]
21pub enum XmpError {
23 Unknown = 0,
26 TBD = -1,
28 Unavailable = -2,
30 BadObject = -3,
32 BadParam = -4,
34 BadValue = -5,
36 AssertFailure = -6,
38 EnforceFailure = -7,
40 Unimplemented = -8,
42 InternalFailure = -9,
44 Deprecated = -10,
46 ExternalFailure = -11,
48 UserAbort = -12,
50 StdException = -13,
52 UnknownException = -14,
54 NoMemory = -15,
56
57 BadSchema = -101,
60 BadXPath = -102,
62 BadOptions = -103,
64 BadIndex = -104,
66 BadIterPosition = -105,
68 BadParse = -106,
70 BadSerialize = -107,
72 BadFileFormat = -108,
74 NoFileHandler = -109,
76 TooLargeForJPEG = -110,
78
79 BadXML = -201,
82 BadRDF = -202,
84 BadXMP = -203,
86 EmptyIterator = -204,
88 BadUnicode = -205,
90 BadTIFF = -206,
92 BadJPEG = -207,
94 BadPSD = -208,
96 BadPSIR = -209,
98 BadIPTC = -210,
100 BadMPEG = -211,
102}
103
104#[derive(Clone, Copy, Eq, PartialEq, Debug)]
105#[repr(i8)]
106pub enum TzSign {
107 West = -1,
109 UTC = 0,
111 East = 1,
113}
114
115#[derive(Clone, Copy, Debug)]
117#[repr(C)]
118pub struct XmpDateTime {
119 pub year: i32,
120 pub month: i32,
121 pub day: i32,
122 pub hour: i32,
123 pub minute: i32,
124 pub second: i32,
125 pub has_date: i8,
126 pub has_time: i8,
127 pub has_tz: i8,
128 pub tz_sign: TzSign,
129 pub tz_hour: i32,
130 pub tz_minute: i32,
131 pub nano_second: i32,
132}
133
134impl Default for XmpDateTime {
135 fn default() -> Self {
136 unsafe { ::std::mem::zeroed() }
137 }
138}
139
140#[repr(C)]
141pub struct XmpPacketInfo {
142 pub offset: i64,
143 pub length: i32,
144 pub pad_size: i32,
145 pub char_form: u8,
146 pub writeable: bool,
147 pub has_wrapper: bool,
148 pub pad: u8,
149}
150
151#[derive(Clone, Copy, Debug, Eq, PartialEq)]
152#[repr(u32)]
153pub enum FileType {
155 PDF = 0x50444620u32, PS = 0x50532020u32, EPS = 0x45505320u32, JPEG = 0x4A504547u32, JPEG2K = 0x4A505820u32, TIFF = 0x54494646u32, GIF = 0x47494620u32, PNG = 0x504E4720u32, WEBP = 0x57454250u32, SWF = 0x53574620u32, FLA = 0x464C4120u32, FLV = 0x464C5620u32, MOV = 0x4D4F5620u32, AVI = 0x41564920u32, CIN = 0x43494E20u32, WAV = 0x57415620u32, MP3 = 0x4D503320u32, SES = 0x53455320u32, CEL = 0x43454C20u32, MPEG = 0x4D504547u32, MPEG2 = 0x4D503220u32, MPEG4 = 0x4D503420u32, MXF = 0x4D584620u32, WMAV = 0x574D4156u32, AIFF = 0x41494646u32, RED = 0x52454420u32, ARRI = 0x41525249u32, HEIF = 0x48454946u32, P2 = 0x50322020u32, XDCAMFam = 0x58444346u32, XDCAMSam = 0x58444353u32, XDCAMEx = 0x58444358u32, AVCHD = 0x41564844u32, SonyHDV = 0x53484456u32, CanonXF = 0x434E5846u32, AVCUltra = 0x41564355u32, HTML = 0x48544D4Cu32, XML = 0x584D4C20u32, TEXT = 0x74657874u32, SVG = 0x53564720u32, Photoshop = 0x50534420u32, Illustrator = 0x41492020u32, InDesign = 0x494E4444u32, AEProject = 0x41455020u32, AEProjTemplate = 0x41455420u32, AEFilterPreset = 0x46465820u32, EncoreProject = 0x4E434F52u32, PremiereProject = 0x5052504Au32, PremiereTitle = 0x5052544Cu32, UCFFile = 0x55434620u32, Unknown = 0x20202020u32, }
215
216#[link(name = "exempi")]
217extern "C" {
218 pub fn xmp_init() -> bool;
219 pub fn xmp_terminate();
220
221 pub fn xmp_get_error() -> c_int;
222
223 pub fn xmp_files_new() -> *mut XmpFile;
224 pub fn xmp_files_open_new(p: *const c_char, options: u32 ) -> *mut XmpFile;
225 pub fn xmp_files_open(
226 xf: *mut XmpFile,
227 p: *const c_char,
228 options: u32, ) -> bool;
230 pub fn xmp_files_close(xf: *mut XmpFile, options: u32 ) -> bool;
231
232 pub fn xmp_files_get_new_xmp(xf: *mut XmpFile) -> *mut Xmp;
233 pub fn xmp_files_get_xmp(xf: *mut XmpFile, xmp: *mut Xmp) -> bool;
234 pub fn xmp_files_get_xmp_xmpstring(
235 xf: *mut XmpFile,
236 xmp_packet: *mut XmpString,
237 packet_info: *mut XmpPacketInfo,
238 ) -> bool;
239 pub fn xmp_files_can_put_xmp(xf: *mut XmpFile, xmp: *const Xmp) -> bool;
240 pub fn xmp_files_can_put_xmp_xmpstring(xf: *mut XmpFile, xmp_packet: *const XmpString) -> bool;
241 pub fn xmp_files_can_put_xmp_cstr(
242 xf: *mut XmpFile,
243 xmp_packet: *const c_char,
244 len: size_t,
245 ) -> bool;
246
247 pub fn xmp_files_put_xmp(xf: *mut XmpFile, xmp: *const Xmp) -> bool;
248 pub fn xmp_files_put_xmp_xmpstring(xf: *mut XmpFile, xmp_packet: *const XmpString) -> bool;
249 pub fn xmp_files_put_xmp_cstr(xf: *mut XmpFile, xmp_packet: *const c_char, len: size_t)
250 -> bool;
251
252 pub fn xmp_files_free(xf: *mut XmpFile) -> bool;
253
254 pub fn xmp_files_get_file_info(
255 xf: *mut XmpFile,
256 fp: *mut XmpString,
257 options: *mut u32, format: *mut FileType,
259 handler_flags: *mut u32, ) -> bool;
261 pub fn xmp_files_check_file_format(path: *const c_char) -> FileType;
262
263 pub fn xmp_files_get_format_info(
264 format: FileType,
265 options: *mut u32, ) -> bool;
267
268 pub fn xmp_register_namespace(
269 uri: *const c_char,
270 prefix: *const c_char,
271 reg_prefix: *mut XmpString,
272 ) -> bool;
273 pub fn xmp_namespace_prefix(ns: *const c_char, prefix: *mut XmpString) -> bool;
274 pub fn xmp_prefix_namespace_uri(prefix: *const c_char, ns: *mut XmpString) -> bool;
275
276 pub fn xmp_new_empty() -> *mut Xmp;
277 pub fn xmp_new(buffer: *const c_char, len: size_t) -> *mut Xmp;
278 pub fn xmp_copy(xmp: *const Xmp) -> *mut Xmp;
279 pub fn xmp_free(xmp: *mut Xmp) -> bool;
280 pub fn xmp_parse(xmp: *mut Xmp, buffer: *const c_char, len: size_t) -> bool;
281 pub fn xmp_serialize(
282 xmp: *const Xmp,
283 buf: *mut XmpString,
284 options: u32, padding: u32,
286 ) -> bool;
287 pub fn xmp_serialize_and_format(
288 xmp: *const Xmp,
289 buf: *mut XmpString,
290 options: u32, padding: u32,
292 newline: *const c_char,
293 tab: *const c_char,
294 indent: i32,
295 ) -> bool;
296
297 pub fn xmp_get_property(
299 xmp: *const Xmp,
300 schema: *const c_char,
301 name: *const c_char,
302 property: *mut XmpString,
303 propsbits: *mut u32, ) -> bool;
305 pub fn xmp_get_property_date(
306 xmp: *const Xmp,
307 schema: *const c_char,
308 name: *const c_char,
309 property: *mut XmpDateTime,
310 propsbits: *mut u32, ) -> bool;
312 pub fn xmp_get_property_float(
313 xmp: *const Xmp,
314 schema: *const c_char,
315 name: *const c_char,
316 property: *mut f64,
317 propsbits: *mut u32, ) -> bool;
319 pub fn xmp_get_property_bool(
320 xmp: *const Xmp,
321 schema: *const c_char,
322 name: *const c_char,
323 property: *mut bool,
324 propsbits: *mut u32, ) -> bool;
326 pub fn xmp_get_property_int32(
327 xmp: *const Xmp,
328 schema: *const c_char,
329 name: *const c_char,
330 property: *mut i32,
331 propsbits: *mut u32, ) -> bool;
333 pub fn xmp_get_property_int64(
334 xmp: *const Xmp,
335 schema: *const c_char,
336 name: *const c_char,
337 property: *mut i64,
338 propsbits: *mut u32, ) -> bool;
340 pub fn xmp_get_array_item(
341 xmp: *const Xmp,
342 schema: *const c_char,
343 name: *const c_char,
344 index: i32,
345 property: *mut XmpString,
346 propsbits: *mut u32, ) -> bool;
348
349 pub fn xmp_set_property(
351 xmp: *mut Xmp,
352 schema: *const c_char,
353 name: *const c_char,
354 value: *const c_char,
355 optionbits: u32, ) -> bool;
357 pub fn xmp_set_property_date(
358 xmp: *mut Xmp,
359 schema: *const c_char,
360 name: *const c_char,
361 value: *const XmpDateTime,
362 optionbits: u32, ) -> bool;
364 pub fn xmp_set_property_float(
365 xmp: *mut Xmp,
366 schema: *const c_char,
367 name: *const c_char,
368 value: f64,
369 optionbits: u32, ) -> bool;
371 pub fn xmp_set_property_bool(
372 xmp: *mut Xmp,
373 schema: *const c_char,
374 name: *const c_char,
375 value: bool,
376 optionbits: u32, ) -> bool;
378 pub fn xmp_set_property_int32(
379 xmp: *mut Xmp,
380 schema: *const c_char,
381 name: *const c_char,
382 value: i32,
383 optionbits: u32, ) -> bool;
385 pub fn xmp_set_property_int64(
386 xmp: *mut Xmp,
387 schema: *const c_char,
388 name: *const c_char,
389 value: i64,
390 optionbits: u32, ) -> bool;
392 pub fn xmp_set_array_item(
393 xmp: *mut Xmp,
394 schema: *const c_char,
395 name: *const c_char,
396 index: i32,
397 value: *const c_char,
398 optionbits: u32, ) -> bool;
400
401 pub fn xmp_append_array_item(
402 xmp: *mut Xmp,
403 schema: *const c_char,
404 name: *const c_char,
405 array_options: u32,
406 value: *const c_char,
407 optionbits: u32, ) -> bool;
409 pub fn xmp_delete_property(xmp: *mut Xmp, schema: *const c_char, name: *const c_char) -> bool;
410 pub fn xmp_has_property(xmp: *const Xmp, schema: *const c_char, name: *const c_char) -> bool;
411
412 pub fn xmp_get_localized_text(
413 xmp: *const Xmp,
414 schema: *const c_char,
415 name: *const c_char,
416 gen_lang: *const c_char,
417 spec_lang: *const c_char,
418 actual_lang: *mut XmpString,
419 value: *mut XmpString,
420 propbits: *mut u32, ) -> bool;
422 pub fn xmp_set_localized_text(
423 xmp: *mut Xmp,
424 schema: *const c_char,
425 name: *const c_char,
426 gen_lang: *const c_char,
427 spec_lang: *const c_char,
428 value: *const c_char,
429 optionbits: u32, ) -> bool;
431 pub fn xmp_delete_localized_text(
432 xmp: *mut Xmp,
433 schema: *const c_char,
434 name: *const c_char,
435 gen_lang: *const c_char,
436 spec_lang: *const c_char,
437 ) -> bool;
438
439 pub fn xmp_string_new() -> *mut XmpString;
440 pub fn xmp_string_free(s: *mut XmpString);
441 pub fn xmp_string_cstr(s: *const XmpString) -> *const c_char;
442 pub fn xmp_string_len(s: *const XmpString) -> size_t;
443
444 pub fn xmp_iterator_new(
445 xmp: *const Xmp,
446 schema: *const c_char,
447 name: *const c_char,
448 optionbits: u32, ) -> *mut XmpIterator;
450 pub fn xmp_iterator_free(i: *mut XmpIterator) -> bool;
451 pub fn xmp_iterator_next(
452 i: *mut XmpIterator,
453 schema: *mut XmpString,
454 name: *mut XmpString,
455 value: *mut XmpString,
456 option: *mut u32, ) -> bool;
458 pub fn xmp_iterator_skip(i: *mut XmpIterator, option: u32 ) -> bool;
459
460 pub fn xmp_datetime_compare(left: *const XmpDateTime, right: *const XmpDateTime) -> c_int;
461}
462
463#[cfg(test)]
464#[test]
465fn native_call_works() {
466 let inited = unsafe { xmp_init() };
467
468 assert!(inited);
469
470 let xf = unsafe { xmp_files_new() };
471
472 assert!(!xf.is_null());
473 assert!(unsafe { xmp_files_free(xf) });
474 assert!(unsafe { xmp_get_error() } == 0);
475
476 let xmp = unsafe { xmp_new_empty() };
477 let xmpiter =
478 unsafe { xmp_iterator_new(xmp, NS_DC.as_ptr(), "keywords".as_ptr() as *const c_char, 0) };
479
480 unsafe {
481 xmp_iterator_free(xmpiter);
482 }
483 unsafe {
484 xmp_free(xmp);
485 }
486
487 let xs = unsafe { xmp_string_new() };
488 assert!(!xs.is_null());
489 let s = unsafe { xmp_string_cstr(xs) };
490 assert!(!s.is_null());
491 unsafe {
492 xmp_string_free(xs);
493 }
494
495 unsafe {
496 xmp_terminate();
497 }
498}