9 Replies Latest reply on Aug 7, 2013 6:33 AM by areohbee

    Calling LrTasks.execute from within a plug in manager control

    BigRedler

      I'm working on a Lightroom post-processing-filter plug in which has most of the functionality inside an executable that resides inside the plug in folder.

       

      The executable is responsible for doing the actual photo processing but is also responsible for obtaining and verifying that there is a valid license. This means that I need to let the user eneter an activation code, pass that to the executable which will talk to our server and get a license.

       

      I would like to handle that activation part from the plug-in manager dialog so I've added a top section (see following code) with a text field and a button and I've added code to call the executable when the button is pressed, but the executalbe is never called.

       

      Is what I'm trying to do impossible? Any workarounds?

       

      Thanks in advance!

       

      Eyal

       

      function PluginManager.sectionsForTopOfDialog( f, p )

                p.my_result = 0

      return {

                -- section for the top of the dialog

                {

                          bind_to_object = p,

                          title = "MyPlug",

                          f:row {

                                    spacing = f:control_spacing(),

                                    f:static_text {

                                              title = LrView.bind( "my_result")

                                    },

                                    f:push_button {

                                              width = 150,

                                              title = 'Run Exe',

                                              enabled = true,

                                              action = function()

                                                        command = '"' .. LrPathUtils.child(LrPathUtils.child( _PLUGIN.path, "mac" ), "MyTool" ) .. '" ' .. '-action check"'

                                                        quotedCommand = command  

                                                        p.my_result = LrTasks.execute( quotedCommand )

                                              end,

                                              },

                                    },

                },

      }

      end

        • 1. Re: Calling LrTasks.execute from within a plug in manager control
          areohbee Level 5

          local buttonGuard

          action = function( button )

               LrFunctionContext.postAsyncTaskWithContext( button.title, function( context )

                    LrDialogs.attachErrorDialogToFunctionContext( context )

                    if buttonGuard == nil then

                         buttonGuard = LrRecursionGuard( button.title )

                    elseif buttonGuard.active then

                         LrDialogs.message( "cool yer jets..." )

                         return

                    end

                    buttonGuard:performWithGuard( function()

                         -- execute your commands and whatever...

                    end )

               end )

          end,

           

          Note:

          * action runs asynchronously, which you probably need to execute your command.

          * action function will display an error message instead of silently croaking, if there is an error thrown.

          * action won't run repeatedly if user keeps clicking on the button, and will give him/her a gentle scolding if so doing .

           

          For more error handling possibilities, use a cleanup handler for the function context, instead of attaching the default error dialog.

           

          Rob

          • 2. Re: Calling LrTasks.execute from within a plug in manager control
            BigRedler Level 1

            Thanks Rob,

            I'm afraid it didn't work for me. The code inside postAsyncTaskWithContext is not executed, as far as I could see. I didn't see any diagnostic messages.

             

             

            local LrView = import "LrView"

            local LrHttp = import "LrHttp"

            local bind = import "LrBinding"

            local app = import 'LrApplication'

            local LrPathUtils = import 'LrPathUtils'

            local LrTasks = import "LrTasks"

            local LrDialogs = import 'LrDialogs'

            local LrRecursionGuard = import 'LrRecursionGuard'

            PluginManager = {}

             

             

            function PluginManager.sectionsForTopOfDialog( f, p )

                      p.my_result = 0

                      local buttonGuard

             

             

            return {

                      -- section for the top of the dialog

                      {

                                bind_to_object = p,

                                title = "MyPlug",

                                f:row {

                                          spacing = f:control_spacing(),

                                          f:static_text {

                                                    title = LrView.bind( "my_result")

                                          },

                                          f:push_button {

                                                    width = 150,

                                                    title = 'Do Something',

                                                    enabled = true,

                                                    action = function(button)

                                                              LrFunctionContext.postAsyncTaskWithContext(button.title,function (context)

                                                                        p.my_result = 3

                                                              end)

                                                    end,

                                                    },

                                          },

                      },

            }

            end

            • 3. Re: Calling LrTasks.execute from within a plug in manager control
              areohbee Level 5

              You didn't import LrFunctionContext - could that be it?

               

              PS - the code snippet I posted had not been tested as typed in. I use something similar but the wrapping code comes with an object which is part of an object oriented framework (elare plugin framework).

               

              PPS - Consider using John Ellis' debugging toolkit.

               

              Rob

              • 4. Re: Calling LrTasks.execute from within a plug in manager control
                BigRedler Level 1

                Thanks, I was indeed not importing LrFunctionContext but I'm afraid the executable is still not getting executed after correcting this, instead I'm getting this error message:

                 

                An internal error has occurred.

                Yielding is not allowed within a C or metamethod call

                • 5. Re: Calling LrTasks.execute from within a plug in manager control
                  areohbee Level 5

                  BigRedler wrote:

                   

                  Yielding is not allowed within a C or metamethod call

                  This usually means something is executing synchronously which should be asynchronous (as a task).

                   

                  At the moment, I dunno why you would get that, given the posted code, - sorry.

                   

                  R

                  • 6. Re: Calling LrTasks.execute from within a plug in manager control
                    BigRedler Level 1

                    It seems that moving the execute statement out of the buttonGuard:performWithGuard block seems to make the call possible.

                    • 7. Re: Calling LrTasks.execute from within a plug in manager control
                      areohbee Level 5

                      Did you check when the app call is returning? I mean I would expect the call to work once anyway, and as long as it returned before next attempt, it would work again.

                       

                      Anyway, sorry: I don't actually use the Lr recursion guard object, so probably shouldn't have used it in the example (I use home-brewed recursion guarding).

                       

                      PS - be careful about accumulating instances of your plugin w/ tasks running... - Lr does NOT automatically kill tasks when you reload a plugin, it just loads another instance in a new environment and fires it up. I try to make sure I have a shutdown module which sets a shutdown flag, then check that in EVERY async task (in my case it's encapsulated by framework methods).

                       

                      R

                      • 8. Re: Calling LrTasks.execute from within a plug in manager control
                        BigRedler Level 1

                        I don't think the problem was that I had multiple instances of the app call. The tool wasn't called even once when the execute call was inside the performWithGuard function.

                        Anyway, I was able to make significant progress with your help and I appreciate it.

                         

                        Eyal

                        • 9. Re: Calling LrTasks.execute from within a plug in manager control
                          areohbee Level 5

                          OK, I guess (I'd like to understand that better, but since I don't use LrRecursionGuard m'self, I 'spose the point is somewhat moot).

                           

                          Glad you're moving forward...

                           

                          Rob