Speak the sidecar format every other editor already reads
FR-CAT-13 asked for standard XMP and nothing in the tree parsed or wrote a byte of it. `keywords.rs` mentioned `dc:subject` in a comment about what a keyword's text is for, `dr-export`'s metadata module said "neither is read by `dr-decode` today" about its own half, and `dr-preset-xmp` reads a different file for a different requirement. So a library imported from Lightroom could come in and never go back out: a one-way door, which is not a thing a photographer walks their archive through. `core/dr-xmp` reads and writes the properties the requirement names — `dc:subject`, `lr:hierarchicalSubject`, `xmp:Rating`, `xmp:Label` and the IPTC core fields — from whichever shape the file happens to use. A property may arrive as an attribute or as an element, inside a Bag, a Seq, an Alt or no container at all, because the specification is not what wrote the file; so one collector takes whatever is in a property and the declared shape decides only how many values survive. `xmp:Rating="-1"` is modelled as Adobe's rejection rather than folded into zero stars, since DarkRoom keeps those on two axes and the mapping belongs where both are visible. Writing is a rewrite rather than a serialisation, and that is the whole design. An XMP sidecar is a shared document: the file beside a raw carries somebody else's `crs:` settings and comments and namespaces, and rendering our record over it would be data loss on every photograph but the first. The rule is stated once, in the crate documentation and in `PROPERTIES`: DarkRoom owns exactly those properties, identified by namespace URI and never by prefix, and nothing else in the document. Everything unowned is copied through byte for byte. A `Description` left empty once our properties come out of it is withdrawn, which is what keeps a rewrite idempotent instead of adding a husk to the file on every save. Precedence is settled conservatively, because a standard XMP carries no revision and no device and there is nothing in it to order two edits by. Keywords union, following the rule `dr_catalog::merge` already makes for assignments; every other field is taken only where DarkRoom holds none, following `Version::merge`'s judgement rule, and a genuine disagreement is reported rather than resolved so a caller can offer the reload the requirement asks for. What is deliberately left open — when a reload may happen without asking — is written down in the module rather than picked silently. No new dependency: quick-xml was already in the tree for WebDAV and for Lightroom presets. Nothing above the crate calls it yet, and `outstanding.md` now says so along with the two smaller gaps, GPS and the filename convention.
This commit is contained in:
+25
-8
@@ -305,14 +305,31 @@ well optimised — ETag pruning under FR-NC-4 turns an unchanged 50k library int
|
||||
gap is narrower than it reads. It is the *first* build against a large remote library that pays, and
|
||||
that is the moment a new user meets.
|
||||
|
||||
**FR-CAT-13 — XMP interoperability, untagged and not met.** Read and write standard XMP sidecars.
|
||||
Its single tag sat on `keywords.rs`, which stores keywords in the catalog and mentions `dc:subject`
|
||||
in a comment about what a keyword's text is *for*; no XMP is parsed or written anywhere in the tree,
|
||||
and `dr-export`'s metadata module says so about its own half ("neither is read by `dr-decode`
|
||||
today"). The tag has been removed — `dr-preset-xmp` is not the counter-example it looks like, being
|
||||
a reader of Lightroom *presets* under FR-DEV-6, which is a different file and a different purpose.
|
||||
Listed here rather than silently, because a tag makes a gap invisible and this one is load-bearing
|
||||
for interoperating with the editors FR-CAT-14 imports from.
|
||||
**FR-CAT-13 — XMP interoperability, built but not yet wired.** `core/dr-xmp` now reads and writes
|
||||
standard XMP sidecars: `dc:subject` and `lr:hierarchicalSubject`, `xmp:Rating` and `xmp:Label`, and
|
||||
the IPTC core fields, in both the attribute and the element form and whatever RDF container a file
|
||||
happened to use. It states the ownership rule in one place — DarkRoom owns the properties in
|
||||
`PROPERTIES` and nothing else in the document, identified by namespace URI rather than by prefix —
|
||||
and enforces it by rewriting a packet event by event rather than serialising over it, so another
|
||||
application's `crs:` settings, comments and processing instructions survive a write byte for byte.
|
||||
|
||||
**What remains is the wiring, and it is the larger half.** Nothing above the crate calls it: no scan
|
||||
finds a `.xmp` beside a raw, no catalog row is populated from one, no edit writes one back, and the
|
||||
external-modification detection the requirement also asks for does not exist. Two smaller gaps go
|
||||
with it — GPS is not carried (`exif:GPSLatitude` is a format of its own, and `dr-decode` produces no
|
||||
location for it to carry yet, which `dr-export`'s metadata module says about its own half), and the
|
||||
filename convention is left to the caller, because Lightroom writes `IMG_0001.xmp` and darktable
|
||||
writes `IMG_0001.CR3.xmp` and finding a file is not this crate's business.
|
||||
|
||||
The precedence question is settled conservatively rather than fully: keywords union, following
|
||||
`dr_catalog::merge`, and every other field is taken only where DarkRoom holds none, following
|
||||
`Version::merge`'s judgement rule — because a standard XMP carries no revision and no device, so
|
||||
FR-NC-9's ordering cannot be performed against it. What is *not* settled, and is written down in the
|
||||
crate rather than guessed at, is when a reload may happen without asking; see the module
|
||||
documentation's "The open question".
|
||||
|
||||
`dr-preset-xmp` remains what it always was and is still not the counter-example it looks like: a
|
||||
reader of Lightroom *presets* under FR-DEV-6, a different file for a different purpose.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user