Skip to main content

⚠️ Please note that this topic or post has been archived. The information contained here may no longer be accurate or up-to-date. ⚠️

A script to add Not Visible Metadata to COP keywords

Comments

1 comment

  • Eric Valk
    The script in the post above times out at 7000 variants . Here is a better version, it still times out with a large number of selected variants, but it does not time out if you set it to check all variants in the current collections;


    ## Notes
    -- Applescript to Copy Lens ID and Digital Teleconverter settings to keywords
    -- Creates a report in Text Edit
    -- Version 1.2 !! NO SUPPORT !! Eric Valk, Ottawa, Canada

    -- *** Operation
    -- Open the compiled and saved file
    -- Open the Script Editor log window, and select the messages tab
    -- Select up to 3000 variants, from any collection

    -- Run the script
    -- Results appear first in Notifications, then the Script Editor Log and Text Edit when the search for each variant is completed, and in Display Dialog Window when all searching is completed
    -- This script adds and removes keywords from images, this results in changes to your catalog or session.
    --
    -- The user may elect to enable or disable results in Notifications, TextEdit and Script Editor by setting the "enable" variables at beginning of the script
    -- The user may change the amount of reporting by setting the "debugLogLevel" and "ResultsFileMaxDebug" variables at beginning of the script
    -- If you are having some issues, then set debugLogLevel to 3 and send me the results from Script Editors log window, or Text Edit.

    ## Values in this section are safe to change, within limits indicated. Support is likely but no commitment
    set debugLogLevel to 1 -- 0...6 Values >1 result in increasing amounts of debug data that takes longer to report
    set enableResultsFile to true -- (true/false)
    set enableResultsByDialog to false -- (true/false)
    set enableNotifications to false -- (true/false)
    set ResultsFileMaxDebug to 2 -- 1...6 suggest not more than 2
    set SearchSelectedImages to false -- If set to false, then every image in the current collection is searched, If true, only seleced images are searched
    set SearchforMakerList to {"Panasonic"}
    set SearchforFileTypeList to {"JPEG", "RW2"}
    set updateExistingKeywords to true -- If set to false, existing keywords are not updated

    ## ***** Not safe to change stuff below this line, unless you have some background in SW development.
    ## I generally won't help much if you change stuff below this line. I may explain the design intent.

    tell application "System Events" to set parent_name to name of current application

    tell application "Finder"
    set script_path to path to me
    set Script_Title to name of file script_path as text
    end tell

    set SE_Logging to (parent_name = "Script Editor")

    if enableResultsFile then
    set Result_DocName to "COP_Image_Search.txt"
    else
    set Result_DocName to "Not Enabled"
    end if

    set ResultMethod to my InitializeLoqqing(Result_DocName, Script_Title)

    loq_Results(0, false, ("Started from: " & parent_name))
    loq_Results(0, false, ("Action: Copy Lens ID and Digital Teleconverter settings to keywords"))

    set minCOPversion to "11.0.1"
    validateCOP(minCOPversion)
    set {COPDocName, COPDocKind_s, COPDocRef} to validateCOPdoc({"catalog", "session"})
    validateCOPcollections()

    set max_search_coll_index to indexInCatalog - 1

    set options_display_string to "Debug Level: " & debugLogLevel
    set options_display_string to options_display_string & return & "Search Only Selected Images: " & SearchSelectedImages
    set options_display_string to options_display_string & return & "Search for Maker: " & SearchforMakerList
    set options_display_string to options_display_string & return & "Search for File Type: " & SearchforFileTypeList
    set options_display_string to options_display_string & return & "Update Existing Keyword Sets: " & updateExistingKeywords
    set options_display_string to options_display_string & return & "Highest Debug Level in Result File: " & ResultsFileMaxDebug
    set options_display_string to options_display_string & return & "Enable Results in Text Edit: " & enableResultsFile
    set options_display_string to options_display_string & return & "Display Dialog on Image Not Found: " & enableResultsByDialog
    set options_display_string to options_display_string & return & "Enable Results in Notifications: " & enableNotifications
    set options_display_string to options_display_string & return & "Results: " & ResultMethod

    tell application "System Events" to set frontmost of process parent_name to true

    try
    set dialog_result to display dialog options_display_string with title Script_Title
    on error errmess
    my loqqed_Error_Halt("User Cancelled the Script")
    end try
    loq_Results(1, false, (return & "Options:" & return & options_display_string & return))

    if SearchSelectedImages = false then
    set Mark1 to get time of (get current date)
    tell application "Capture One 11" to set countVariants to count of every variant
    set Mark2 to get time of (get current date)

    if countVariants = 0 then
    my loqqed_Error_Halt("No images in " & kindSelectedCollection_s & " " & nameSelectedCollection)
    end if

    ## Start the search
    repeat with variantCounter from 1 to countVariants
    tell application "Capture One 11" to set thisVariant to variant variantCounter
    processVariant(thisVariant)
    end repeat
    set Mark3 to get time of (get current date)
    else
    set Mark1 to get time of (get current date)
    try
    tell application "Capture One 11" to set selectedVariantsList to selected variants
    set Mark2 to get time of (get current date)
    on error errmess
    set Mark2 to get time of (get current date)
    my loqqed_Error_Halt(errmess & " Elapsed: " & (Mark2 - Mark1) & " seconds")
    end try

    set countVariants to count of selectedVariantsList
    if countVariants = 0 then
    display alert "No images selected - select one or more images"
    my loqqed_Error_Halt("No images selected")
    end if

    ## Start the search
    tell application "System Events" to set frontmost of process "Capture One 11" to true

    repeat with thisVariant in selectedVariantsList
    processVariant(thisVariant)
    end repeat
    set Mark3 to get time of (get current date)
    end if

    tell application "System Events" to set frontmost of process "Capture One 11" to true
    tell current application to set date_string to (current date) as text
    if debugLogLevel ≥ 1 then
    set elapsedTime1 to Mark2 - Mark1
    set elapsedTime2 to Mark3 - Mark2
    set quantum to 0.01
    set timePerVariant to (round (elapsedTime2 / countVariants / quantum) rounding to nearest) * quantum
    my loq_Results(1, false, (return & "SetupTime: " & elapsedTime1 & "sec Process time: " & elapsedTime2 & "sec Per Variant: " & timePerVariant & "sec Variants: " & countVariants))
    else
    my loq_Results(1, false, (return))
    end if
    my loq_Results(0, true, ("*** Done at " & date_string & " ***"))

    --Handlers -------------------

    on processVariant(theVariant)
    global debugLogLevel, SearchforMakerList, SearchforFileTypeList, updateExistingKeywords, COPDocRef

    tell application "Capture One 11" to tell theVariant
    set the imagepath to the path of the parent image
    end tell

    tell my application "Finder"
    if not (exists imagepath as POSIX file) then
    my loq_Results(0, false, ("Unable to find image " & imagepath))
    exit repeat
    end if
    end tell

    tell current application to set Results123 to do shell script "/usr/local/bin/exiftool -s3 -FileType -Make -DigitalZoomRatio " & quoted form of imagepath
    set foundFileType to (get paragraph 1 of Results123)
    set foundFileMaker to (get paragraph 2 of Results123)

    if (SearchforFileTypeList contains foundFileType) and (SearchforMakerList contains foundFileMaker) then

    tell application "Capture One 11" to tell theVariant
    set {variantName, variantID} to {name, id}
    set {keywordNameList, keywordParentList} to {name, parent} of keywords
    set keywordcount to count of keywordNameList
    end tell

    my loq_Results(2, false, (return & "Path: " & imagepath & " ID: " & variantID & " Keywords: " & keywordcount))

    if (0 < keywordcount) and (debugLogLevel > 2) then
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    repeat with keywordcounter from 1 to keywordcount
    my loq_Results(3, false, ("Keywd_" & keywordcounter & ": " & (get name of keyword keywordcounter) & " Parent: " & (get parent of keyword keywordcounter)))
    end repeat
    end tell
    end if

    if (updateExistingKeywords = false) and (keywordParentList contains "LensID") then
    -- do nothing
    else
    -- Add or Update the keyword set
    tell current application to set LensNameList to do shell script "/usr/local/bin/exiftool -s3 -Lens -LensType -LensType2 -LensType3 -LensID -LensInfo -LensModel -LensMake " & quoted form of imagepath
    --log {"Processing", imagepath, digZoomSetting, (get count of paragraphs of LensNameList), LensNameList}

    if (get count of paragraphs of LensNameList) = 0 then
    my loq_Results(0, false, ("No LensID found:" & imagepath))
    else
    set LensName to paragraph 1 of LensNameList
    if keywordParentList contains "LensID" then
    set keywordcountOffset to 0
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    repeat with keywordcounter from 1 to keywordcount
    set keywordIndex to keywordcounter + keywordcountOffset
    if (get parent of keyword keywordIndex) = "LensID" then
    my loq_Results(4, false, ("Deleting: " & (get name of keyword keywordIndex)))
    delete keyword keywordIndex
    set keywordcountOffset to keywordcountOffset - 1
    end if
    end repeat
    end tell
    else if keywordNameList does not contain "LensID" then
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    tell theVariant to make new keyword with properties {name:"LensID"}
    my loq_Results(5, false, ("Adding: " & "LensID"))
    end tell
    end if
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    tell theVariant to make new keyword with properties {name:LensName, parent:"LensID"}
    my loq_Results(4, false, ("Adding: " & LensName))
    end tell
    end if
    tell application "Capture One 11" to tell theVariant to set {keywordNameList, keywordParentList} to {name, parent} of keywords
    set keywordcount to count of keywordNameList
    end if

    if ((updateExistingKeywords = false) and (keywordParentList contains "DigZoom")) or (foundFileType ≠ "JPEG") then
    -- do nothing
    else
    if (2 = (get count of paragraphs of Results123)) then
    set digZoomName to "NotFound"
    else
    set digZoomName to "NotFound"
    set digZoomSetting to paragraph 3 of Results123
    if digZoomSetting = "0" then
    set digZoomName to "Off"
    else if digZoomSetting = "1" then
    set digZoomName to "Off"
    else if digZoomSetting = "2" then
    set digZoomName to "DTC_2X"
    else if digZoomSetting = "4" then
    set digZoomName to "DTC_4X"
    else
    try
    set digZoomName to (digZoomSetting as real)
    set digZoomName to "Var_" & digZoomName & "X"
    end try
    end if
    end if

    if digZoomName = "NotFound" then
    my loq_Results(0, false, ("No Digital Zoom info found:" & imagepath))
    else
    if keywordParentList contains "DigZoom" then
    set keywordcountOffset to 0
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    repeat with keywordcounter from 1 to keywordcount
    set keywordIndex to keywordcounter + keywordcountOffset
    if (get parent of keyword keywordIndex) = "DigZoom" then
    my loq_Results(4, false, ("Deleting: " & (get name of keyword keywordIndex)))
    delete keyword keywordIndex
    set keywordcountOffset to keywordcountOffset - 1
    end if
    end repeat
    end tell
    else if keywordNameList does not contain "DigZoom" then
    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    tell theVariant to make new keyword with properties {name:"DigZoom"}
    my loq_Results(5, false, ("Adding: " & "DigZoom"))
    end tell
    end if

    tell application "Capture One 11" to tell COPDocRef to tell theVariant
    tell theVariant to make new keyword with properties {name:digZoomName, parent:"DigZoom"}
    my loq_Results(4, false, ("Adding: " & digZoomName))
    end tell
    end if
    end if
    end if
    end processVariant


    on validateCOP(minCOPversionstr)
    global debugLogLevel
    tell application "System Events"
    set COPProcList to every process whose name contains "Capture One" and background only is false
    if debugLogLevel ≥ 2 then
    set COPProcNameList to name of every process whose name contains "Capture One" and background only is false
    my loq_Results(2, false, ("COP Processes:" & COPProcNameList))
    end if
    end tell
    if (count of COPProcList) = 0 then my loqqed_Error_Halt("COP is not running")
    if (count of COPProcList) ≠ 1 then my loqqed_Error_Halt("Unexpected: >1 COP instances")
    set theAppRef to item 1 of COPProcList
    tell application "System Events" to set theAppName to ((get name of theAppRef) as text)
    tell application "System Events" to set copDetailedVersion to get version of my application theAppName

    tell application "Capture One 11" to set copVersion to (get app version)

    if debugLogLevel ≥ 2 then
    --properties of application "Capture One 11"
    tell application "System Events"
    my loq_Results(2, false, ("All Processes: " & (get my joinListToString((get name of every process whose background only is false), ", "))))
    end tell
    loq_Results(2, false, ("theAppName: " & theAppName))
    loq_Results(2, false, ("COP Version: " & copVersion))
    loq_Results(2, false, ("COP Detailed Version: " & copDetailedVersion))
    end if

    if the theAppName ≠ "Capture One 11" then
    display notification "Wrong COP Application"
    my loqqed_Error_Halt("Found COP Application " & theAppName & " The only supported COP application is Capture One 11")
    end if

    set numCOPversion to (splitStringToList((word -1 of copVersion), "."))
    set minCOPversion to (splitStringToList(minCOPversionstr, "."))

    set digit_mult to 1000000
    set Version_digit to 0
    repeat with dig_ctr from 1 to count of numCOPversion
    set digit_mult to digit_mult / 100
    set Version_digit to Version_digit + (get item dig_ctr of numCOPversion as integer) * digit_mult
    end repeat

    set digit_mult to 1000000
    set min_digit to 0
    repeat with dig_ctr from 1 to count of minCOPversion
    set digit_mult to digit_mult / 100
    set min_digit to min_digit + (get item dig_ctr of minCOPversion as integer) * digit_mult
    end repeat

    if Version_digit < min_digit then
    display notification "COP Version is too low"
    my loqqed_Error_Halt("This COP Version is " & (word -1 of copVersion) & " - the minimum supported COP version is " & minCOPversionstr)
    end if

    tell application "System Events" to set frontmost of process theAppName to true
    loq_Results(0, false, ("Using Capture One " & copDetailedVersion))
    end validateCOP

    on validateCOPdoc(COP_kind_list)
    global debugLogLevel
    tell application "Capture One 11"
    set {current_doc_name, current_doc_kind_p} to (get {name, kind} of current document)
    set current_doc_ref_list to (get every document whose name is current_doc_name and kind is current_doc_kind_p)
    set number_of_hits to count of current_doc_ref_list
    end tell
    set current_doc_kind_s to convertKind(current_doc_kind_p)
    loq_Results(2, false, ("Is: " & current_doc_kind_s & " was: " & (get current_doc_kind_p as text)))
    loq_Results(2, false, ("Found Documents: " & number_of_hits))

    if COP_kind_list does not contain current_doc_kind_s then loq_Results(0, false, (current_doc_name & " is a " & current_doc_kind_s & " -- unsupported type of document"))

    if number_of_hits = 0 then
    loqqed_Error_Halt("Could not find find " & current_doc_kind_s & current_doc_name)
    else if number_of_hits > 1 then
    loqqed_Error_Halt("Found more than one " & current_doc_kind_s & " with the name " & current_doc_name)
    else
    tell application "Capture One 11" to set current_doc_ref to item 1 of current_doc_ref_list
    end if

    loq_Results(0, false, ("Capture One document: " & current_doc_kind_s & " " & current_doc_name))
    return {current_doc_name, current_doc_kind_s, current_doc_ref}
    end validateCOPdoc

    on validateCOPcollections()
    global debugLogLevel, COPDocName, everyTopCollection, namesTopCollections, kindsTopCollections_p, countTopCollections, selectedCollectionRef, selectedCollectionIndex, kindSelectedCollection_s, nameSelectedCollection, selectedCollectionAtTopEnd, selectedCollectionIsUser, indexInCatalog

    tell application "Capture One 11" to tell document COPDocName
    set selectedCollectionRef to get current collection
    set {nameSelectedCollection, kindSelectedCollection_p} to {name, kind} of selectedCollectionRef
    set everyTopCollection to get every collection
    set {namesTopCollections, kindsTopCollections_p} to {name, kind} of every collection
    end tell
    set kindSelectedCollection_s to convertKind(kindSelectedCollection_p)
    set countTopCollections to count of namesTopCollections

    try
    || of {selectedCollectionRef} -- generate an error to capture error text containing the collection reference
    on error CO11_errtxt number CO11_errnbr
    end try

    loq_Results(4, false, ("***Error Message " & CO11_errtxt & "; number " & CO11_errnbr & " Current Collection: " & kindSelectedCollection_s & " " & nameSelectedCollection))

    ## extract the collection number from the error text
    if CO11_errnbr = -1728 then
    set selectedCollectionIndex to (get last word of item 2 of splitStringToList(CO11_errtxt, "of")) as integer
    else
    loq_Results(4, false, ("*****" & CO11_errtxt & "; number " & CO11_errnbr))
    loqqed_Error_Halt("Unexpected error when finding current collection index")
    end if

    if selectedCollectionIndex = countTopCollections then
    ## last collection IS the selected collection
    set selectedCollectionAtTopEnd to true
    else
    ## last collection is NOT the selected collection
    set selectedCollectionAtTopEnd to false
    end if

    if ({"project", "album", "group", "smart album"} contains kindSelectedCollection_s) then
    set selectedCollectionIsUser to true
    else
    set selectedCollectionIsUser to false
    end if

    tell application "Capture One 11" to tell document COPDocName to set countOfInCatalog to count of (get every collection whose name is "In Catalog")
    if countOfInCatalog = 1 then
    set indexInCatalog to getIndexOf("in Catalog", namesTopCollections)
    else
    loqqedexit("There is more than one collection with the name "In Catalog"")
    end if
    end validateCOPcollections

    on InitializeLoqqing(DocName_Ext, sourceTitle)
    global debugLogLevel, Script_Title, Result_Doc_ref, SE_Logging, enableResultsFile, enableResultsByDialog, DialogTextList

    tell current application to set date_string to (current date) as text
    set LogMethods to {}

    if enableResultsFile then
    set target_folder_name to "ScriptReports"
    set target_folder_p to ((POSIX path of (get path to desktop as text)) & target_folder_name)
    set target_folder_a to (POSIX file target_folder_p) as string
    set Result_Doc_Path_p to target_folder_p & "/" & DocName_Ext
    set Result_Doc_Path_a to (POSIX file Result_Doc_Path_p) as string

    tell application "System Events" to if not (exists (alias (target_folder_a))) then ¬
    tell application "Finder" to make new folder at desktop with properties {name:target_folder_name}

    tell application "System Events" to if not (exists (alias (Result_Doc_Path_a))) then
    set First_line to ("Created " & date_string & return)
    do shell script "echo " & First_line & " > " & """ & Result_Doc_Path_p & """
    if (debugLogLevel ≥ 1) and SE_Logging then log Result_Doc_Path_p & First_line
    end if

    tell application "TextEdit" to activate
    tell application "TextEdit" to set Result_Doc_ref to open Result_Doc_Path_a as alias
    set LogMethods to LogMethods & DocName_Ext
    end if

    if enableResultsByDialog then
    set DialogTextList to {}
    set LogMethods to LogMethods & "Display Dialog"
    end if

    loq_Results(0, false, (sourceTitle & " results on " & date_string))
    return joinListToString(LogMethods, ", ")
    end InitializeLoqqing

    on loq_Results(thisLogDebugLevel, MakeFront, logText)
    global Result_Doc_ref, debugLogLevel, SE_Logging, parent_name, ResultsFileMaxDebug, enableResultsFile, enableResultsByDialog, DialogTextList
    if thisLogDebugLevel > debugLogLevel then return

    set logText_class to ((get class of logText) as text)
    if logText_class ≠ "text" then
    try
    if logText_class = "list" then
    set new_logText to joinListToString(logText, ", ")
    else
    set new_logText to logText as text
    end if
    set logText to new_logText
    set logText_class to "text"
    on error errmess
    set logText to errmess
    set logText_class to "text"
    end try
    end if

    if ((thisLogDebugLevel ≤ ResultsFileMaxDebug) or not SE_Logging) then
    if enableResultsFile then
    tell application "TextEdit"
    set numPara to count paragraphs of the text of Result_Doc_ref
    set paragraph (numPara + 1) of the text of Result_Doc_ref to ((logText as text) & return)
    end tell
    tell application "System Events" to if MakeFront then set frontmost of process "TextEdit" to true
    end if
    if enableResultsByDialog then
    set DialogTextList to DialogTextList & logText
    if MakeFront then
    tell application "System Events" to set frontmost of process parent_name to true
    display dialog joinListToString(DialogTextList, return)
    end if
    end if
    end if

    if SE_Logging then log (logText as text)

    end loq_Results

    on loqqed_Error_Halt(error_text)
    global debugLogLevel, Script_Title
    tell current application to set date_string to (current date) as text
    loq_Results(0, true, ("Script "" & Script_Title & "" has exited at " & date_string & return & "Reason: " & error_text & return & return & "Halted"))
    display notification error_text
    error error_text
    end loqqed_Error_Halt

    on splitStringToList(theString, theDelim)
    set astid to AppleScript's text item delimiters
    try
    set AppleScript's text item delimiters to theDelim
    set theList to text items of theString
    on error
    set AppleScript's text item delimiters to astid
    end try
    set AppleScript's text item delimiters to astid
    return theList
    end splitStringToList

    to joinListToString(theList, theDelim)
    set theString to ""
    set astid to AppleScript's text item delimiters
    try
    set AppleScript's text item delimiters to theDelim
    set theString to theList as string
    on error
    set AppleScript's text item delimiters to astid
    end try
    set AppleScript's text item delimiters to astid
    return theString
    end joinListToString

    on getIndexOf(theItem, theList) -- credits Emmanuel Levy
    set astid to AppleScript's text item delimiters
    set AppleScript's text item delimiters to return
    set theList to return & theList & return
    set AppleScript's text item delimiters to astid
    try
    -1 + (count (paragraphs of (text 1 thru (offset of (return & theItem & return) in theList) of theList)))
    on error
    0
    end try
    end getIndexOf

    on convertKind(kind_p)
    global debugLogLevel

    set kind_s to kind_p as text
    if (get text 1 of kind_s) ≠ "«" then
    return kind_s
    else
    set code_start to (get length of kind_s) - 4
    set kind_code to get (text code_start thru (code_start + 3) of kind_s)

    if kind_code = "CCpj" then
    set kind_res to "project"
    else if kind_code = "CCgp" then
    set kind_res to "group"
    else if kind_code = "CCal" then
    set kind_res to "album"
    else if kind_code = "CCsm" then
    set kind_res to "smart album"
    else if kind_code = "CCfv" then
    set kind_res to "favorite"
    else if kind_code = "CCff" then
    set kind_res to "catalog folder"
    else if kind_code = "COct" then
    set kind_res to "catalog"
    else if kind_code = "COsd" then
    set kind_res to "session"
    else
    loqqed_Error_Halt("Unexpected Kind string: " & kind_s)
    end if
    end if
    return kind_res
    end convertKind
    0

Post is closed for comments.