10 Replies Latest reply on Jun 14, 2017 8:42 PM by bernie west

    Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin

    bernie west Level 1

      I'm writing a Lightroom plugin using the Lightroom SDK/API in the Lua language. I'm new to Lua. I've found a situation where my script only works if a Lightroom dialog box (LrDialogs.message("random message")) is present in one function.  If the first dialog isn't included then the program flow never steps into the for line in io.lines(outputFilePath) block, despite outputFilePath being populated with the correct path string.  Any ideas what's going on?

       

      Here's the code:

      ------ read output file for exif and write to LR metadata ------
      function parseOutput(outputFilePath)

         LrDialogs
      .message("random message")

        
      local tblOutput = {}   --to hold the output exif (1 column table, i.e. an array)
        
      local tblImages = {}   --to hold the images and their relevant metadata

        
      for line in io.lines(outputFilePath) do
             line
      = removeWhitespaces(line)
             table
      .insert(tblOutput, line)
        
      end

        
      local str = table.remove(tblOutput) --remove last line in table/file (it's log info, not exif)
         tblImages
      = extractExif(tblOutput)  --pick out the exif key/value pairs and add to Image objects

      end

       

      [Moved out of the general (and dead) Coding Corner and into a product-specific SDK forum - moderator]

        • 1. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
          johnrellis Most Valuable Participant

          I don't see anything obviously wrong with the code fragment you posted. But because LR often (usually) doesn't report errors that occur in all but the main task, it's easy to get fooled about what's really going with your plugin.  I strongly recommend you use a debugger.  Another thread in this forum describes how to connect LR to a particular IDE; alternatively, you can use by Debugging Toolkit, which provides a more limited but lighter-weight debugger specifically designed for LR's Lua environment.  Either one will require an investment of an hour or two, but it will quickly pay off. 

          • 2. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
            bernie west Level 1

            Thanks John.  I'm using ZeroBraneStudio IDE which allows me to debug.  I'm not sure how to dig deeper than just stepping through the program and watching the relevant variable.  outputFilePath is populated with the correct value, but io.lines(outputFilePath) doesn't trigger.

            • 3. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
              johnrellis Most Valuable Participant

              io.lines(outputFilePath) doesn't trigger.

              Do you mean that as you single step, the debugger never reaches that line?  But when you insert the call to message() and single-step, the debugger does reach that line? 

              • 4. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                johnrellis Most Valuable Participant

                Some thoughts:

                 

                - Perhaps io.lines() is raising an error and ZeroBrane isn't trapping the error, or perhaps you've got an enclosing pcall() or error handling in some caller that is silently catching the error.   Try adding this line before the "for":

                 

                local success, value = LrTasks.pcall (io.lines, outputFilePath)

                if not success then

                    LrDialogs.message ("io.lines error: " .. value)

                    end

                 

                - When I revised my debugging toolkit last winter, I looked at the module tha ZeroBrane pretty closely.  I wasn't convinced that it properly handles LR's Lua execution environment. In particular, I wonder if it always catches errors in tasks other than the main task and in callbacks from LR API calls, and I wonder if it properly handles single-stepping and breakpoints in LR's tasks (which I'm pretty sure is not the standard Lua tasking / coroutines).   If my suspicions are right (and I'm not confident they are), try using logging ("print statements") to trace the execution. 

                • 5. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                  bernie west Level 1

                  Thanks John.  I added that code and it returned success = true.  So it didn't invoke the error LrDialog.message.

                   

                  The code reaches the for io.lines... block, but it never steps into the block (unless I add that random LrDialog before it).

                   

                  Additional info:  The parseOutput() function is called from a LrTasks.startAsyncTask() function with a LrTasks.execute() call in it.   

                  • 6. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                    bernie west Level 1

                    Here's the code of the function that calls parseOutput().

                     

                    exifToolAPI = {}

                     

                     

                    local LrMobdebug = import 'LrMobdebug'

                    local LrApplication = import 'LrApplication'

                    local LrDialogs = import 'LrDialogs'

                    local LrTasks = import 'LrTasks'

                    local LrPathUtils = import 'LrPathUtils'

                    local LrFileUtils = import 'LrFileUtils'

                    local LrDate = import 'LrDate'

                    local strErrorLogPath = ""

                      if WIN_ENV then

                      strErrorLogPath = "C:\Users\Foo\Bar\FUJI_LR_error.log"

                      elseif MAC_ENV then

                      strErrorLogPath = "/Users/foo/bar/FUJI_LR_error.log"

                      end

                    local arrImage = {} --array of Image objects holding requested exif data

                     

                     

                    function exifToolAPI.open()

                      LrMobdebug.start()

                      local photos = {} -- array to hold LrPhoto objects

                      local cat = LrApplication.activeCatalog() --active catalogue object

                      local objET = {} --handle object to hold various ExifTool related properties

                      local tmpdir = LrPathUtils.getStandardFilePath("temp") --path to system temp directory

                     

                      --create path to a unique txt file to hold commands to pass to ExifTool

                      objET.commandFilePath = LrPathUtils.child(tmpdir, "ExiftoolCmds-" .. tostring(LrDate.currentTime()) .. ".txt")

                      objET.outputFilePath = LrPathUtils.child(tmpdir, "ExiftoolOutput-" .. tostring(LrDate.currentTime()) .. ".txt")

                      objET.errorLogFilePath = strErrorLogPath

                     

                      --create empty file

                      local objFile = io.open(objET.outputFilePath, "w")

                      objFile:close()

                      local objFile = io.open(objET.errorLogFilePath, "w")

                      objFile:close()

                     

                      --get image list

                      photos = cat:getMultipleSelectedOrAllPhotos()

                     

                      LrTasks.startAsyncTask (

                           function() -- Start exiftool in listen mode

                               LrMobdebug.on()

                                strPath = nil

                                strCommand = cmdlineQuote() .. "/usr/local/bin/exiftool -iso -FilmMode -DynamicRangeSetting -AutoDynamicRange -DevelopmentDynamicRange -@ " .. objET.commandFilePath

                                strParameters = ""

                     

                                for i,v in ipairs(photos) do

                                     strPath = photos[i]:getRawMetadata("path") .. "\n" --don't need quotes when using -@ file

                                     strParameters = strParameters .. strPath

                                end

                     

                           objFile = io.open(objET.commandFilePath, "w")

                           objFile:write(strParameters)

                           objFile:close()

                     

                           strCommand = strCommand .. " > " .. objET.outputFilePath .. " 2> " .. objET.errorLogFilePath ..  cmdlineQuote()

                           local exitStatus = LrTasks.execute(strCommand)

                     

                           LrFileUtils.delete(objET.commandFilePath)

                           end

                           )

                     

                      parseOutput(objET.outputFilePath)

                      LrFileUtils.delete(objET.outputFilePath)

                    end

                    • 7. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                      johnrellis Most Valuable Participant

                      One issue is that the task running Exiftool may not run at all before parseOutput() is called, or it may only run partially.  If that happens, then the file whose name is in objET.outputFilePath hasn't been created yet.   But when you insert the call to message() in parseOutput(), the dialog will pause its calling task, allowing the Exiftool task to run to completion, creating the output file before parseOutput() attempts to read it.

                       

                      Why are you calling Exiftool in a task separate from the one calling parseOutput()?

                      • 8. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                        bernie west Level 1

                        No reason other than just separating code.  Should it be within the async call?

                        • 9. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                          johnrellis Most Valuable Participant

                          The call to parseOutput() must occur only after Exiftool has finished.  So they should be executed sequentially in the same task.

                          • 10. Re: Weird behaviour with dialog box and a variable in Lua script for Lightroom Plugin
                            bernie west Level 1

                            That's fixed it.  I moved the call to parseOutput() into the async task block and it runs correctly.  Thanks for your help with this, John.  I'm now trying to write the fuji exif data to LR metadata and have encountered another problem.  I'll start a new thread for that issue.  Cheers.