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 tz_sign: TzSign,
130 pub tz_hour: i32,
131 pub tz_minute: i32,
132 pub nano_second: i32,
133}
134
135impl Default for XmpDateTime {
136 fn default() -> Self {
137 unsafe { ::std::mem::zeroed() }
138 }
139}
140
141#[repr(C)]
142pub struct XmpPacketInfo {
143 pub offset: i64,
144 pub length: i32,
145 pub pad_size: i32,
146 pub char_form: u8,
147 pub writeable: bool,
148 pub has_wrapper: bool,
149 pub pad: u8,
150}
151
152#[derive(Clone, Copy, Debug, Eq, PartialEq)]
153#[repr(u32)]
154pub enum FileType {
156 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, }
216
217#[link(name = "exempi")]
218extern "C" {
219 pub fn xmp_init() -> bool;
220 pub fn xmp_terminate();
221
222 pub fn xmp_get_error() -> c_int;
223
224 pub fn xmp_files_new() -> *mut XmpFile;
225 pub fn xmp_files_open_new(p: *const c_char, options: u32 ) -> *mut XmpFile;
226 pub fn xmp_files_open(
227 xf: *mut XmpFile,
228 p: *const c_char,
229 options: u32, ) -> bool;
231 pub fn xmp_files_close(xf: *mut XmpFile, options: u32 ) -> bool;
232
233 pub fn xmp_files_get_new_xmp(xf: *mut XmpFile) -> *mut Xmp;
234 pub fn xmp_files_get_xmp(xf: *mut XmpFile, xmp: *mut Xmp) -> bool;
235 pub fn xmp_files_get_xmp_xmpstring(
236 xf: *mut XmpFile,
237 xmp_packet: *mut XmpString,
238 packet_info: *mut XmpPacketInfo,
239 ) -> bool;
240 pub fn xmp_files_can_put_xmp(xf: *mut XmpFile, xmp: *const Xmp) -> bool;
241 pub fn xmp_files_can_put_xmp_xmpstring(xf: *mut XmpFile, xmp_packet: *const XmpString) -> bool;
242 pub fn xmp_files_can_put_xmp_cstr(
243 xf: *mut XmpFile,
244 xmp_packet: *const c_char,
245 len: size_t,
246 ) -> bool;
247
248 pub fn xmp_files_put_xmp(xf: *mut XmpFile, xmp: *const Xmp) -> bool;
249 pub fn xmp_files_put_xmp_xmpstring(xf: *mut XmpFile, xmp_packet: *const XmpString) -> bool;
250 pub fn xmp_files_put_xmp_cstr(xf: *mut XmpFile, xmp_packet: *const c_char, len: size_t)
251 -> bool;
252
253 pub fn xmp_files_free(xf: *mut XmpFile) -> bool;
254
255 pub fn xmp_files_get_file_info(
256 xf: *mut XmpFile,
257 fp: *mut XmpString,
258 options: *mut u32, format: *mut FileType,
260 handler_flags: *mut u32, ) -> bool;
262 pub fn xmp_files_check_file_format(path: *const c_char) -> FileType;
263
264 pub fn xmp_files_get_format_info(
265 format: FileType,
266 options: *mut u32, ) -> bool;
268
269 pub fn xmp_register_namespace(
270 uri: *const c_char,
271 prefix: *const c_char,
272 reg_prefix: *mut XmpString,
273 ) -> bool;
274 pub fn xmp_namespace_prefix(ns: *const c_char, prefix: *mut XmpString) -> bool;
275 pub fn xmp_prefix_namespace_uri(prefix: *const c_char, ns: *mut XmpString) -> bool;
276
277 pub fn xmp_new_empty() -> *mut Xmp;
278 pub fn xmp_new(buffer: *const c_char, len: size_t) -> *mut Xmp;
279 pub fn xmp_copy(xmp: *const Xmp) -> *mut Xmp;
280 pub fn xmp_free(xmp: *mut Xmp) -> bool;
281 pub fn xmp_parse(xmp: *mut Xmp, buffer: *const c_char, len: size_t) -> bool;
282 pub fn xmp_serialize(
283 xmp: *const Xmp,
284 buf: *mut XmpString,
285 options: u32, padding: u32,
287 ) -> bool;
288 pub fn xmp_serialize_and_format(
289 xmp: *const Xmp,
290 buf: *mut XmpString,
291 options: u32, padding: u32,
293 newline: *const c_char,
294 tab: *const c_char,
295 indent: i32,
296 ) -> bool;
297
298 pub fn xmp_get_property(
300 xmp: *const Xmp,
301 schema: *const c_char,
302 name: *const c_char,
303 property: *mut XmpString,
304 propsbits: *mut u32, ) -> bool;
306 pub fn xmp_get_property_date(
307 xmp: *const Xmp,
308 schema: *const c_char,
309 name: *const c_char,
310 property: *mut XmpDateTime,
311 propsbits: *mut u32, ) -> bool;
313 pub fn xmp_get_property_float(
314 xmp: *const Xmp,
315 schema: *const c_char,
316 name: *const c_char,
317 property: *mut f64,
318 propsbits: *mut u32, ) -> bool;
320 pub fn xmp_get_property_bool(
321 xmp: *const Xmp,
322 schema: *const c_char,
323 name: *const c_char,
324 property: *mut bool,
325 propsbits: *mut u32, ) -> bool;
327 pub fn xmp_get_property_int32(
328 xmp: *const Xmp,
329 schema: *const c_char,
330 name: *const c_char,
331 property: *mut i32,
332 propsbits: *mut u32, ) -> bool;
334 pub fn xmp_get_property_int64(
335 xmp: *const Xmp,
336 schema: *const c_char,
337 name: *const c_char,
338 property: *mut i64,
339 propsbits: *mut u32, ) -> bool;
341 pub fn xmp_get_array_item(
342 xmp: *const Xmp,
343 schema: *const c_char,
344 name: *const c_char,
345 index: i32,
346 property: *mut XmpString,
347 propsbits: *mut u32, ) -> bool;
349
350 pub fn xmp_set_property(
352 xmp: *mut Xmp,
353 schema: *const c_char,
354 name: *const c_char,
355 value: *const c_char,
356 optionbits: u32, ) -> bool;
358 pub fn xmp_set_property_date(
359 xmp: *mut Xmp,
360 schema: *const c_char,
361 name: *const c_char,
362 value: *const XmpDateTime,
363 optionbits: u32, ) -> bool;
365 pub fn xmp_set_property_float(
366 xmp: *mut Xmp,
367 schema: *const c_char,
368 name: *const c_char,
369 value: f64,
370 optionbits: u32, ) -> bool;
372 pub fn xmp_set_property_bool(
373 xmp: *mut Xmp,
374 schema: *const c_char,
375 name: *const c_char,
376 value: bool,
377 optionbits: u32, ) -> bool;
379 pub fn xmp_set_property_int32(
380 xmp: *mut Xmp,
381 schema: *const c_char,
382 name: *const c_char,
383 value: i32,
384 optionbits: u32, ) -> bool;
386 pub fn xmp_set_property_int64(
387 xmp: *mut Xmp,
388 schema: *const c_char,
389 name: *const c_char,
390 value: i64,
391 optionbits: u32, ) -> bool;
393 pub fn xmp_set_array_item(
394 xmp: *mut Xmp,
395 schema: *const c_char,
396 name: *const c_char,
397 index: i32,
398 value: *const c_char,
399 optionbits: u32, ) -> bool;
401
402 pub fn xmp_append_array_item(
403 xmp: *mut Xmp,
404 schema: *const c_char,
405 name: *const c_char,
406 array_options: u32,
407 value: *const c_char,
408 optionbits: u32, ) -> bool;
410 pub fn xmp_delete_property(xmp: *mut Xmp, schema: *const c_char, name: *const c_char) -> bool;
411 pub fn xmp_has_property(xmp: *const Xmp, schema: *const c_char, name: *const c_char) -> bool;
412
413 pub fn xmp_get_localized_text(
414 xmp: *const Xmp,
415 schema: *const c_char,
416 name: *const c_char,
417 gen_lang: *const c_char,
418 spec_lang: *const c_char,
419 actual_lang: *mut XmpString,
420 value: *mut XmpString,
421 propbits: *mut u32, ) -> bool;
423 pub fn xmp_set_localized_text(
424 xmp: *mut Xmp,
425 schema: *const c_char,
426 name: *const c_char,
427 gen_lang: *const c_char,
428 spec_lang: *const c_char,
429 value: *const c_char,
430 optionbits: u32, ) -> bool;
432 pub fn xmp_delete_localized_text(
433 xmp: *mut Xmp,
434 schema: *const c_char,
435 name: *const c_char,
436 gen_lang: *const c_char,
437 spec_lang: *const c_char,
438 ) -> bool;
439
440 pub fn xmp_string_new() -> *mut XmpString;
441 pub fn xmp_string_free(s: *mut XmpString);
442 pub fn xmp_string_cstr(s: *const XmpString) -> *const c_char;
443 pub fn xmp_string_len(s: *const XmpString) -> size_t;
444
445 pub fn xmp_iterator_new(
446 xmp: *const Xmp,
447 schema: *const c_char,
448 name: *const c_char,
449 optionbits: u32, ) -> *mut XmpIterator;
451 pub fn xmp_iterator_free(i: *mut XmpIterator) -> bool;
452 pub fn xmp_iterator_next(
453 i: *mut XmpIterator,
454 schema: *mut XmpString,
455 name: *mut XmpString,
456 value: *mut XmpString,
457 option: *mut u32, ) -> bool;
459 pub fn xmp_iterator_skip(i: *mut XmpIterator, option: u32 ) -> bool;
460
461 pub fn xmp_datetime_compare(left: *const XmpDateTime, right: *const XmpDateTime) -> c_int;
462}
463
464#[cfg(test)]
465#[test]
466fn native_call_works() {
467 let inited = unsafe { xmp_init() };
468
469 assert!(inited);
470
471 let xf = unsafe { xmp_files_new() };
472
473 assert!(!xf.is_null());
474 assert!(unsafe { xmp_files_free(xf) });
475 assert!(unsafe { xmp_get_error() } == 0);
476
477 let xmp = unsafe { xmp_new_empty() };
478 let xmpiter =
479 unsafe { xmp_iterator_new(xmp, NS_DC.as_ptr(), "keywords".as_ptr() as *const c_char, 0) };
480
481 unsafe {
482 xmp_iterator_free(xmpiter);
483 }
484 unsafe {
485 xmp_free(xmp);
486 }
487
488 let xs = unsafe { xmp_string_new() };
489 assert!(!xs.is_null());
490 let s = unsafe { xmp_string_cstr(xs) };
491 assert!(!s.is_null());
492 unsafe {
493 xmp_string_free(xs);
494 }
495
496 unsafe {
497 xmp_terminate();
498 }
499}