-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathWrite XMP.applescript
More file actions
295 lines (228 loc) · 11 KB
/
Write XMP.applescript
File metadata and controls
295 lines (228 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
property tempExportFolder : (POSIX file "/tmp/Aperture-XMP/")
property sqlCommand : "/usr/bin/sqlite3 "
property reasonablePathLength : 6
property apertureSidecarExtension : "XMP"
property darktableSidecarExtension : "xmp"
property exportedKeyword : "DarkTable"
--property aperturExportImageSetting : "JPEG - Fit within 640 x 640"
global apertureLibPath
tell application "System Events" to set apertureLibPath to value of property list item "LibraryPath" of property list file ((path to preferences as Unicode text) & "com.apple.aperture.plist")
assert against length of apertureLibPath < 12 given message:"Can't find aperture library. Try hard-coding its path into the script."
-- set apertureLibPath to "/Users/Chtulu/Pictures/Aperture Library.aplibrary"
log apertureLibPath
-- Main script flow --
--create temporary export folder and verify that it exists
do shell script "mkdir -p " & quoted form of (POSIX path of tempExportFolder)
set tempFolderExists to false
try
do shell script "test ! -d " & quoted form of (POSIX path of tempExportFolder)
on error errStr number errorNumber
-- test writes its output to stderr
if errorNumber = 1 then
-- 1 = folder exists
set tempFolderExists to true
else
error errStr number errorNumber
end if
end try
assert against not tempFolderExists given message:"Could not create temporary folder at " & (POSIX path of tempExportFolder)
tell application "Aperture" to set imageSel to (get selection)
if imageSel is {} then
error "Please select one or more images."
end if
set numOffline to 0
set numManaged to 0
--check if selected images are offline, or still managed, before going any further
tell application "Aperture"
repeat with i from 1 to count of imageSel
tell item i of imageSel
if online is false then
set numOffline to numOffline + 1
end if
if referenced is false then
set numManaged to numManaged + 1
end if
end tell
end repeat
end tell
if numOffline > 0 then
error (numOffline as string) & " image(s) are offline (on a storage device not connected). Please connect it and try again"
else if numManaged > 0 then
error (numManaged as string) & " image(s) are still managed by Aperture. It's a bad idea to mess around inside the Aperture library, so this script requires all selected images to be referenced to somewhere outside of the Aperture library. Relocate your originals and try again."
end if
set numFalselyTagged to 0
set numSkippedMovies to 0
set numAlreadyExported to 0
set numRemaining to count of imageSel
set numSidecarsWritten to 0
set currentImageName to "(before first image)"
-- main export loop
try
repeat with i from 1 to count of imageSel
set currentImage to item i of imageSel
set currentImageName to name of currentImage as string
set masterPath to getMasterImagePath from currentImage
set master to POSIX file masterPath as alias
assertFileExists at masterPath given message:"Master file for " & currentImageName & " at " & masterPath & " does not exist"
-- speed things up a bit by not writing sidecars for movies, because DarkTable ignores them anyway
if checkIfMovie for master then
set numSkippedMovies to numSkippedMovies + 1
else
tell application "Finder"
set exportFolder to (parent of master)
set exportFolderPath to POSIX path of (exportFolder as alias)
set fileName to name of master
end tell
-- DarkTable happens to expect image.JPG.xmp style sidecar naming
-- The standard specifies image.xmp style naming, so other apps generally expect that scheme instead
-- to put sidecars in the standard location, uncomment:
-- set fileName to item 1 of (splitFilenameAtExtension out of fileName)
set sidecarDestination to exportFolderPath & fileName & "." & darktableSidecarExtension
set sidecarAlreadyPresent to checkFileExists at sidecarDestination
if sidecarAlreadyPresent then
-- sidecar already exists
set numAlreadyExported to numAlreadyExported + 1
else
tell application "Aperture" to set hasKeyword to (exportedKeyword is in keywords of currentImage)
--has keyword with properties {name:exportedKeyword}
if hasKeyword then
set numFalselyTagged to numFalselyTagged + 1
end if
set sidecarPath to writeApertureSidecar for currentImage
--set applescript's text item delimiters to "."
--set fileNameBody to text item -2 of fileName
posixMove of sidecarPath to sidecarDestination
assertFileExists at sidecarDestination given message:"Failed moving sidecar for " & currentImageName & " to its proper destination, " & exportFolderPath
set numSidecarsWritten to numSidecarsWritten + 1
end if
tell application "Aperture"
tell currentImage
make new keyword with properties {name:exportedKeyword}
end tell
end tell
end if
set numRemaining to numRemaining - 1
end repeat
assert against not numRemaining = 0 given message:"Number of exported image sidecars does not add up"
on error errStr number errorNumber
display dialog "An error processing " & currentImageName & " stopped the script with " & numRemaining & " not yet exported. Error: " & errStr
end try
-- post-export warning checks
if numSkippedMovies > 0 then display dialog (numSkippedMovies as string) & " movies included in the selection were skipped and did not get a sidecar"
if numAlreadyExported > 0 then display dialog (numAlreadyExported as string) & " images in selection were skipped since XMP had already been exported. This might not be an error at all, if you have multiple versions for the same master, or willingly selected already exported images."
if numFalselyTagged > 0 then display dialog "Warning: " & (numFalselyTagged as string) & " versions were tagged with " & exportedKeyword & " but had no sidecar. Sidecars have been written for these files, but please check if other image versions may be incorrectly tagged as exported."
if numSkippedMovies + numAlreadyExported + numFalselyTagged = 0 then
display dialog "Done. " & (numSidecarsWritten as string) & " XMP sidecars successfully written with no errors or warnings."
end if
-- end of main script flow
-- Handlers --
to assert against condition given message:messageStr
if condition = true then error messageStr
end assert
on checkFileExists at filePath
--log "checkFileExists " & filePath
set doesExist to false
try
do shell script "test ! -f " & quoted form of filePath
on error errStr number errorNumber
-- test writes its output to stderr
if errorNumber = 1 then
-- 1 = file exists
set doesExist to true
else
-- actual error
error number errorNumber
end if
end try
--log doesExist
return doesExist
end checkFileExists
to assertFileExists at filePath given message:messageStr
set fileExists to checkFileExists at filePath
if not fileExists then error messageStr
end assertFileExists
to splitFilenameAtExtension out of posixPath
set AppleScript's text item delimiters to ""
set reversePath to reverse of characters of posixPath as text
set e to the offset of "." in reversePath
set l to length of posixPath
set pathComponent to (text 1 thru (l - e) of posixPath)
if e = 0 then
set extensionComponent to ""
else
set extensionComponent to (text (l - e + 1) thru l of posixPath)
end if
return {pathComponent, extensionComponent}
end splitFilenameAtExtension
to getMasterImagePath from imageVersion
tell application "Aperture"
set imageid to (id of imageVersion) as string
set imagename to name of imageVersion as string
end tell
assert against length of imageid < 4 given message:"Version ID for " & imagename & ": \"" & "\" is conspiciously short"
set dbPath to (apertureLibPath & "/Database/apdb/Library.apdb") as string
set dbQuery to "select RKVolume.name,imagePath from RKVersion,RKMaster,RKVolume where RKVersion.uuid=" & quoted form of imageid & " AND RKVersion.masterUuid=RKMaster.uuid AND RKVolume.uuid=RKMaster.fileVolumeUuid"
set dbQuery to "\"" & dbQuery & "\""
set dbCommandLine to sqlCommand & (quoted form of dbPath) & " " & dbQuery
set dbSuccessful to false
repeat 10 times
try
set dbOutput to do shell script dbCommandLine
set dbSuccessful to true
exit repeat
on error errStr number errorNumber
-- handle DB locked error
log errorNumber
log errStr
if errorNumber = 5 then
delay 1
else
error errStr number errorNumber
end if
end try
end repeat
assert against not dbSuccessful given message:"Could not open connection, Aperture database stays locked across repeated retries."
set AppleScript's text item delimiters to "|"
set diskName to text item 1 of dbOutput
set masterPath to text item 2 of dbOutput
set masterImagePath to "/Volumes/" & diskName & "/" & masterPath
assert against length of masterImagePath < 7 given message:"Got invalid path to master image for " & (name of imageVersion)
return masterImagePath
end getMasterImagePath
on writeApertureSidecar for imageVersion
tell application "Aperture"
set exportItems to {imageVersion}
--set exportOutput to (export exportItems using aperturExportImageSetting to (tempExportFolder) metadata sidecar)
set exportOutput to (export exportItems to tempExportFolder metadata sidecar)
end tell
set macPath to (item 1 of exportOutput) as string
set imageExportFile to file macPath as alias
set imageOutputPath to POSIX path of imageExportFile
set pathWithoutExtension to item 1 of (splitFilenameAtExtension out of imageOutputPath)
set sidecarPath to pathWithoutExtension & "." & apertureSidecarExtension
assertFileExists at sidecarPath given message:"Can't find written sidecar file for " & imageOutputPath
assertFileExists at imageOutputPath given message:"Can't find written image file at expected place (" & imageOutputPath & ")"
set deleteCommandLine to "rm " & (quoted form of imageOutputPath)
do shell script deleteCommandLine
return sidecarPath
end writeApertureSidecar
on posixMove of sourceFile to destinationFile
assert against not item 1 of sourceFile = "/" given message:"posixMove requires absolute paths as arguments; sourceFile is relative"
assert against length of sourceFile < reasonablePathLength given message:"Move file error: " & sourceFile & " is conspiciously short"
assert against not item 1 of destinationFile = "/" given message:"posixMove requires absolute paths as arguments; destinationFile is relative"
assert against length of destinationFile < reasonablePathLength given message:"Move file error: " & destinationFile & " is conspiciously short"
-- -n option prevents overwriting file
set mvCommandLine to "mv -n " & (quoted form of sourceFile) & " " & (quoted form of destinationFile)
do shell script mvCommandLine
end posixMove
on checkIfMovie for mediaFileAlias
-- is in {'mov','m4v',3gp'} then
tell application "Finder"
set fileType to kind of mediaFileAlias
end tell
-- WARNING: this file type check is language-dependent and possibly only works in english and swedish
set isMovie to fileType contains "film" or fileType contains "movie"
-- {"QuickTime-film", "Apple MPEG-4-film", "MPEG-4-film", "3GPP-film"}
--log fileType & " is movie=" & isMovie
return isMovie
end checkIfMovie