• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

LrCatalog withWriteAccessDo - How to determine if the write to catalog has completed?

Community Beginner ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

I'm in the midst of developing a plugin for Lightroom Classic, and was wondering if anyone had any tips on how to wait for a withWriteAccessDo() block to complete before proceeding with the code beyond it.

 

Essentially, I am writing to the catalog [via photo:applyDevelopSettings() method] and later need to access these updated settings from the stored photo in the catalog [via photo:getDevelopSettings() method]. 

 

Referencing the API documentation for withWriteAccessDo() in the Lightroom Classic SDK, it would seem that it is no longer designed to be update immediately:

As of version 3.0, changes you make to the database within this call do not have immediate effect, but are written to the database upon successful completion of the callback function. This means, in general, that if you create a new item (for instance, by calling catalog:createCollection()), you cannot retrieve information about that item until the with___AccessDo has finished. There are some special cases where you can reference the newly-created item; for instance, after creating a collection set, you can create a collection within that set. These cases are noted in the API documentation.

 

Does anyone have a suggestion as to how to wait until this block has completed execution? I wonder if it's possible to set up a polling function on a variable...though I've not yet been able to implement such a solution successfully.

 

The one way I've gotten it to work thus far is by adding a manual delay [via LrTasks.sleep(1.0) method] immediately after the withWriteAccessDo() block. This delays the timing of things and the later code runs correctly - however I worry that the required delay would vary based on a user's hardware, and am sure there is a better way to do this.

 

Any advice would be appreciated.

TOPICS
SDK

Views

571

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , Feb 22, 2023 Feb 22, 2023

Hi.

 

Delay is not needed at all - when withWriteAccessDo() returns, data have already been written to the catalog.

SDK may be not very clear, but what is really meant there:

- callback is the function you wrap with withWriteAccessDo()

- if this function makes number of changes, you should not expect that they are written until function returns (in general, there are some exceptions to this listed in SDK)

 

So in short, with your example:

withWriteAccessDo("Apply develop settings", function(context)

    

...

Votes

Translate

Translate
LEGEND ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

When the call to catalog:withWriteAccessDo() returns with result "executed", any changes made by the passed function should be visible via all calls to the SDK.

 

If you're not observing that, post a small script demonstrating the anomalous behavior.

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 24, 2023 Feb 24, 2023

Copy link to clipboard

Copied

Thanks for replying John. This was very useful in debugging my specific problem - I was able to monitor the return value of withWriteAccessDo and build out my logic following the form of this pseudocode: 

local executionStatus = catalog:withWriteAccessDo(progressActionTitle, function(context)
    -- some logic here...
    currentPhoto:applyDevelopSettings({ SomeSetting = "SomeValue" })
end

if executionStatus == 'executed' then
    -- followup logic here...
elseif executionStatus == 'queued' then
    -- queued logic here...
elseif executionStatus == 'aborted' then
    -- aborted logic here...
end

 

Just elaborating on this for anyone else who stumbles upon this thread!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 02, 2023 Mar 02, 2023

Copy link to clipboard

Copied

LATEST

Hey John, just following up on this as I hit an odd roadblock.

 

An exception I'm running into following with the logic we've outlined is that when using applyDevelopSettings to specify the 'WhiteBalance' value to 'As Shot', it seems to trigger an asyncronous background routine that further loads the initial white balance values for 'Temperature' and 'Tint' after the function returns 'executed'. 

 

This is causing me some grief, as I want to operate on the initial values for 'Temperature' and 'Tint'. With a polling routine, I'm able to check for nil on these develop values for a photo and continue onwards in logic when they're updated - which works fine for about 20 selected photos (with very small delays under .01 seconds in most cases). However, operating beyond the 20 selected photo mark I get an indefinite timeout where the values are never updated (or, at least not for the 3 hours my code run).

 

Here's some simplified code for what I'm describing - trying to apply a relative offset to the current temperature.

-- Pass 1: Detect uninitialized white balances and trigger load
local executionStatus = catalog:withWriteAccessDo(writeActionTitle, function(context)
	for index, currentPhoto in pairs(selectedPhotos) do
		local currentDevelopSettings = currentPhoto:getDevelopSettings()
		local currentTemp = currentDevelopSettings["Temperature"]
		if currentTemp == nil then
            currentPhoto:applyDevelopSettings({ WhiteBalance = "As Shot" })
        end -- end if
    end -- end for
end ) -- end withWriteAccessDo - all selected photos should be initialized here

-- Debugging check
if executionStatus == 'executed' then
  logger:debug( "CHECK: Executed successfully!" )
else
  logger:debug( "CHECK: Execute failed!" )
end   

-- Pass 2: 
local executionStatus = catalog:withWriteAccessDo(writeActionTitle, function(context)
	for index, currentPhoto in pairs(selectedPhotos) do
		local currentDevelopSettings = currentPhoto:getDevelopSettings()
		local currentTemp = currentDevelopSettings["Temperature"]
		while currentTemp == nil do -- polling routine (works great for first 20 selected photos)
			LrTasks.sleep(0.01)
			currentDevelopSettings = currentPhoto:getDevelopSettings()
            currentTemp = currentDevelopSettings["Temperature"]  
		end -- end while
		local newTemp = currentTemp + 10
		currentPhoto:applyDevelopSettings({ Temperature = newTemp })
	end -- end for
end ) -- end withWriteAccessDo

 

Might you have any insight as to why it's behaving this way? Or, how I might otherwise go about initializing Lightroom's 'Temperature' and 'Tint' values if they are not yet so?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

Hi.

 

Delay is not needed at all - when withWriteAccessDo() returns, data have already been written to the catalog.

SDK may be not very clear, but what is really meant there:

- callback is the function you wrap with withWriteAccessDo()

- if this function makes number of changes, you should not expect that they are written until function returns (in general, there are some exceptions to this listed in SDK)

 

So in short, with your example:

withWriteAccessDo("Apply develop settings", function(context)

    photo:applyDevelopPreset()

    photo:getDevelopSettings()

end)

is NOT ok, because it is not guaranteed that develop settings will be written immediately. They are guaranteed to be written when function returns.

So it should be like this:

withWriteAccessDo("Apply develop settings", function(context)

    photo:applyDevelopPreset()

end)

photo:getDevelopSettings()

 

Exceptions that I mentioned is that for example you can create collection and then put photos in that collection inside of the same withWriteAccessDo(), but those are explicitly stated in SDK.

 

Hope this makes things a bit clearer.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 24, 2023 Feb 24, 2023

Copy link to clipboard

Copied

Thanks for the clarification FSt0p - it definitely helped me interpret the API and what my code was doing better. Much appreciated.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines