Quantcast
Channel: Adobe Community : Popular Discussions - Lightroom SDK
Viewing all 53524 articles
Browse latest View live

is it possible to attach URLHandler for plugin

$
0
0

Hi, Guys.

 

I notice Facebook plugin can accept external URL protocol via web browser.

( URL : lightroom://com.adobe.lightroom.export.facebook/%23access_token=147.... )

 

Screen shot 2010-11-16 at 1.39.59 AM.png

 

 

Is it possible to attach Custrom URLHandler for my plugin ?

 

I can't find any information about it.

 

If someone know about this, please let me know.

 

Have a nice day.


Making a plugin support self updating

$
0
0

I noticed a number of plugins have the ability to update themselves.  I was wondering if there was any sample code that anyone is willing to share to implement this.  Even just a  summary of the steps that people generally use to implement this. 

Problem with autofill Export standard fields

$
0
0

Hi,

 

I'm trying to write primitive export action: I want to export photo to some folder and put it to autonaming subfolder. Basic idea is to use the same name, as photo folder:

 

local LrApplication = import 'LrApplication'

local LrPathUtils = import 'LrPathUtils'

 

local activeCatalog = LrApplication.activeCatalog()

local filmstrip = activeCatalog.targetPhotos

local parentfolder

activeCatalog:withReadAccessDo( function()

     local photo = activeCatalog.targetPhoto

     parentfolder = LrPathUtils.leafName(LrPathUtils.parent(photo.path))

end )

 

First, I tried to get .lrtemplate file, and modify it

      export_destinationPathSuffix = ...,

But it fails on either import!

 

Then I tried to create LrExportServiceProvider with preset and startDialog method: skip export_destinationPathSuffix in preset and setup propertyTable.LR_export_destinationPathSuffix in startDialog. But when I'm chosing my preset: it sets up correct value, and the blinks and sets up "Untitled Export" value! I can add an observer to LR_export_destinationPathSuffix, but it will update field, not view.

 

To reproduce:

- import attached plugin

- select export

- choose any other preset

- choose "Folder->MakeFolder" preset

You will see Subfolder name blinking, and the new value is "Untitled Export"

 

Can anybody help me with this stuff?

 

Victor.

Vista, 64bit vs. 32bit vs. XP and LrTasks

$
0
0

Hi,

I have a plugin which towards the end of the export process uses LrTasks.execute to call a helper application.

 

On OS-X this seems to work just fine as the OS indexes these applications, and so they can be installed anywhere on the user's hard drive and a simple shell command such as open -a 'myApp' will work.

 

However, on Windows, I see that the only way ( I can think of ) to launch an application is to use the START command. This works just fine, but I see that it depends on which OS I am on as it needs an explicit path to the application, which can vary depending on which version os Windows you are on.

 

here is an example of what I am trying to do.... this assumes I am either on OS-X or XP

 

if MAC_ENV == true then

     LrTasks.execute('open -a myAppr')

else

     LrTasks.execute('START "" "C:\\Program Files\\myApp\\myApp.exe"')

end

 

As I recall, this will work with Vista 32, but with Vista64 it would be installed in a slightly different location... I think it's something like Program Files\i386 or something like that....

 

Anyway, I was just wondering if anyone had any experience with this, and if there was a) a better way to call the windows app, or b) a way to detect if it's vista or xp, etc... or c) if I just will have to bundle this thing three times...?

 

thanks for any help

 

-micah

LrHttp.post and HTTP redirect

$
0
0

Hi,

 

I am writing a plugin that uses HTTP to upload images to a site. The site uses cookies to maintain a user's session. It works like this:

 

1. Browser:POST to a sigin script sending username and password

2. Server: Respond with HTTP 303 (redirect) including Set-Cookie header for session cookie and URL to redirect to

3. Browser: GET redirected URL, including sending cookie header as part of the GET request

4. Server: Respond HTTP 200 with redirected URL contents (no Set-Cookie header)

 

To allow my plugin to grab the session cookie, I need to be able to see the 303 response from step 2.

 

However, the way LrHttp.post works is to hide steps 2 and 3 from me, and return the html from the successful re-direct.

 

I understand that this is nice and correct behaviour from Lr.Http to automatically interpret the redirect, but this prevents me from seeing the Set-Cookie header and hence I cannot establish a session with the server from Lightroom.

 

Any ideas?

 

James

Is exportRendition:uploadFailed() working as intended?

$
0
0

In my export plugin, if an export fails for some reason, I call

 

exportRendition:uploadFailed( "My very informative error message" )

 

and go on to process the next image.

 

My expectation is that my error message should be displayed on Lightroom's "Export Results" dialog that lists all of the failed exports.  Instead the failed images show up under a non-senseical header like "640" (see attached screen shot).  Does anyone know how this is supposed to work?  If it matters, I'm running Lightroom 2.3 on a WinXP system.

 

-Don

programmatically getting search criterion from a smart collection

$
0
0

Hi all,

 

I would like to programmatically retrieve criterion from a smart collection. I've found in LrCollection API a "setSearchDescription" but there is no "getSearchDescription" method to retrieve the search description table. Is there a way to workaround this?

 

Cheers,

 

Benoît Pin.

getDevelopSettings().Exposure2012 returns -999999

$
0
0

In my Relative adjustments plug-in I use the getDevelopSettings() to get the original values for, for example, Exposure2012.

 

One client had a problem and diving into this I discovered that when, for example when retrieving the Exposure setting, in some cases LR returns -99999 instead of the real values. Although, when navigating to the image, the settings in de Basic panel are correct.
This client is on LR5.

 

Reproduce:

  1. Run the test plug-in below on a large folder (> 200) with RAW files
    Sometimes the error occurs direct, sometimes after applying a setting on a undeveloped image.
  2. Otherwise
    1. (Create a new catalog, Best to experiment on a new catalog)
    2. Import 200 - 300 RAW photos
    3. Select them all and apply Auto-Tone to all of them (Library module & Grid) -> Right mouse click -> Develop settings -> Auto tone.
    4. Run the code below and see what's in the log file.

On some photos this -99999 is returned and on others not. Mostly on photos not visible on screen.

When in Develop mode, I scroll through all the photos manually, then afterwards it seems fine. Caching problem??

 

Questions:

  • Any tips & tricks how to solve this issue?
  • Did I miss some thing?
  • How can I correct this behavior?

 

Info.lua

local info =
{    LrSdkVersion        = 4.0,    LrToolkitIdentifier = 'com.LightroomStatistics.lightroom.develop.test',    LrPluginName        = "Test",    LrPluginInfoUrl     = 'http://www.LightroomStatistics.com/',    LrAlsoUseBuiltInTranslations = true,       VERSION = { major=0, minor=1, revision=1, build=0, },       LrHelpMenuItems = {        {            title = "List exposure setting photos",            file = "ShowSettings.lua",        },    },
}

return info

 

ShowSettings.lua

local LrTasks = import 'LrTasks'
local catalog = import "LrApplication".activeCatalog()
local ProgressScope = import 'LrProgressScope'
local LrDialogs = import 'LrDialogs'
local LrView = import 'LrView'
local LrPathUtils = import 'LrPathUtils'
local LrFileUtils = import 'LrFileUtils'

local logFilename = 'ExposureSettings'
local myLogger = import 'LrLogger'( logFilename )
myLogger:enable( "logfile" )

--[[--------------------------------------------------------------------------
Name        emptyLogFile
Purpose        Clears the existing log file.

From cookbook: http://cookbooks.adobe.com/post_Clearing_your_logfile_automatically-19677.html
----------------------------------------------------------------------------]]
function emptyLogFile()
    --local myLogger = import 'LrLogger'( 'Stash' )    myLogger:disable()           logPath = LrPathUtils.child(LrPathUtils.getStandardFilePath('documents'), logFilename .. ".log")    if LrFileUtils.exists( logPath ) then        local success, reason = LrFileUtils.delete( logPath )        if not success then            logger:error("Error deleting existing logfile!" .. reason)        end    end    myLogger:enable( "logfile" )
end

--[[--------------------------------------------------------------------------
Main function

Name        Select images
Purpose        This plug-in will select every second photo.            The selected photo is the first photo to be selected and then every second            photo will also be selected.

Version        1.0
Developer    D. Holtman
----------------------------------------------------------------------------]]
LrTasks.startAsyncTask( function()    emptyLogFile()       --    Get all the selected photos and the active photo    local cat_photos = catalog:getTargetPhotos()    local nCountSelected = #cat_photos    myLogger:info('List table develop settings')    for i, photo in ipairs(cat_photos) do        local devSettings = photo:getDevelopSettings()        local name = photo:getFormattedMetadata( "fileName" )        myLogger:info('Photo', name, devSettings.Exposure2012)    end       LrDialogs.message('Listing exposure', 'Finished')
end)

Lightroom 6 SDK Changes

$
0
0

It seems that there are new classes with LR6:

 

LrDevelopController

LrApplicationView

LrSelection

LrSlideshow

LrSounds

LrTether

LrUndo

 

For my purposes, LrDevelopController sounds promising

 

Jarno

ftp upload plugin -hide section-how define preset?

$
0
0
Hello,
I want to hide 'fileSettings' and 'imageSettings' in the ftp upload/FTPUploadServiceProvider.lua file. I established to hide them BUT how do I define the preset settings?

I want to have them "built" into the plugin to avoid a custom preset.lrtemplate. If this is not possible then I would have a preset defined, but again, I got no idea how to "bind" it to the lua file.

I just started with lua and the LR SDK - would be great if someone could help me.
Thanks, and it is very appreciated!

Compiling plugins

$
0
0
How does one do this? The facebook plugin (http://regex.info/blog/lightroom-goodies/facebook) seems to be compiled or at least obfuscated, however, when I attempt to compile my own, it gives me an error. The error given is "Info.lua: bad header in pre-compiled chunk." and I have no idea how to fix this.

I tried compiling one of the demo plugins, specifically hello world, but it still gave me the same problem. Do I need to use a different version of Lua or do I have to do something completely different? I tried both 5.0 and 5.1.

All I'm doing is:
luac -o compiled/Info.lua Info.lua

Is that good enough, or do I need to do more?

Thanks a lot.

Detecting size of a directory

$
0
0

I'm trying to establish the size of the directory containing a photo, using LrFileUtils.fileAttributes. I can happily return a photo's file size using LrFileUtils.fileAttributes( photo.path) so I suspect the problem is specifying the folder path.

 

According to the manual, LrFileUtils.fileAttributes ( path ) "retrieves the file attributes for the file or directory at a given path." So I'm trying:

 

                            folderPath = string.gsub( photo.path,  photo:getFormattedMetadata('fileName'), '')

                            phoAttributes = LrFileUtils.fileAttributes( folderPath)
                            folderSize =  phoAttributes['fileSize']

 

Any thoughts?

 

John

Publish Service and Collection Names

$
0
0

I am creating a publish service and need some information on the naming of publish collections.

 

I want to prevent the user from naming the collections anything but the name that is on the server. This needs to happen even on creation.

 

I know I can prevent the renaming by setting disableRenamePublishedCollection = false, but that does not help on the creation.

 

The best way to do this would to prevent the user from entering a name when they are creating a collection, I have yet to see a way to do this.

 

If not then need to set the name of the collection to the name that is on the server. I have tried this with no luck. http://forums.adobe.com/thread/662683?tstart=60

I cannot get the name of the collection to change right after it is created. It may change for a second then goes right back.

 

Anyone have any suggestions?

 

I thought of maybe making a thread that would wait a time then rename the collection, but I am lost on how to do that.

Looking for Lightroom Plugin Developer for a Project

$
0
0

We are looking for a developer who can help us create a Lightroom plugin that will allow Lightroom users to upload their photos for print to our web based print and production service. Minimal user interface required. In the first stage of the project, shopping cart including pricing and shipping information will be handled by the web system. Later stages may include advertising pricing information inside Lightroom.

 

For more information respond to this thread or send an email to ks@printedart.com.

 

Klaus Sonnenleiter

http://www.printedart.com

Here is a function to read preview images from active catalog

$
0
0

--- Get a preview image corresponding to specified photo, at the specified level, if possible.

--

--  @param photo (LrPhoto or table of param, required)     specified photo or table of named parameters same as below including photo=lr-photo:

--  @param photoPath (string, optional)     photo-path if available, otherwise will be pulled from raw-metadata.

--  @param previewFile (string, default=unique-temp-path)     target path to store jpeg - if non-vil value passed and file is pre-existing, it will be overwritten.

--  @param level (number, required)      appx sizes + intended use:

--      <br>     1 - 80x60     small thumb

--      <br>     2 - 160x120   medium thumb

--      <br>     3 - 320x240   large thumb

--      <br>     4 - 640x480   small image

--      <br>     5 - 1280x960  medium image

--      <br>     6 - 2560x1920 large image

--      <br>     7 - 1:1       full-res

--  @param minLevel (number, default=1) minimum acceptable level.

--

--  @usage file, errm, level = cat:getPreview{ photo=catalog:getTargetPhoto(), level=5 }

--  @usage file, errm, level = cat:getPreview( catalog:getTargetPhoto(), nil, nil, 5 )

--

--  @return file (string, or nil) path to file containing requested preview (may be the same as preview-file passed in).

--  @return errm (string, or nil) error message if unable to obtain requested preview (includes path(s)).

--  @return level (number, or nil) actual level read, which may be different than requested level if min-level passed in.

--

function Catalog:getPreview( photo, photoPath, previewFile, level, minLevel )

    if photo == nil then

        app:callingError( "no photo" )

    end

    if not photo.catalog then -- not lr-photo

        photoPath = photo.photoPath

        previewFile = photo.previewFile

        -- assert( photo.level, "no level in param table" )

        level = photo.level

        minLevel = photo.minLevel

        photo = photo.photo

        -- assert( photo and photo.catalog, "no lr-photo in param table" )

    end

    if level == nil then

        app:callingError( "no level" )

    end

    if level > 7 then

        app:logWarning( "Max level is 7" )

        level = 7

    end

    if photoPath == nil then

        photoPath = photo:getRawMetadata( 'path' )

    end

    local photoFilename = LrPathUtils.leafName( photoPath )

    local _previewFile

    if previewFile == nil then

        _previewFile = LrPathUtils.child( LrPathUtils.getStandardFilePath( 'temp' ), str:fmt( "^1.lrPreview.jpg", photoFilename ) ) -- include extension, since there are separate previews for each file-type.

    else

        if fso:existsAsFile( previewFile ) then

            app:logVerbose( "preview path passed is to existing file to be overwritten" )

        end

        _previewFile = previewFile

    end

 

    local imageId

    local s = tostring( photo ) -- THIS IS WHAT ALLOWS IT TO WORK DESPITE LOCKED DATABASE (id is output by to-string method).

    local p1, p2 = s:find( 'id "' )

    if p1 then

        s = s:sub( p2 + 1 )

        p1, p2 = s:find( '" )' )

        if p1 then

            imageId = s:sub( 1, p1-1 )

        end

    end

    if imageId == nil then

        return nil, "bad id"

    end

 

    local cp = catalog:getPath()

    local fn = LrPathUtils.leafName( cp )

    local n = LrPathUtils.removeExtension( fn )

    local cd = LrPathUtils.parent( cp )

    local pn = n .. " Previews.lrdata"

    local d = LrPathUtils.child( cd, pn )

    local pdb = LrPathUtils.child( d, 'previews.db' )

    assert( fso:existsAsFile( pdb ), "nope" )

    --Debug.pause( pdb )

    local exe = app:getPref( 'sqlite3' )

    if not str:is( exe ) then

        if WIN_ENV then

            exe = LrPathUtils.child( _PLUGIN.path, "sqlite3.exe" )

        else

            exe = LrPathUtils.child( _PLUGIN.path, "sqlite3" )

        end

        app:logVerbose( "Using sqlite executable included with plugin: ^1", exe )

    else

        app:logVerbose( "Using custom sqlite executable: ^1", exe )

    end

    local param = '"' .. pdb .. '"'

    local targ = str:fmt( "select uuid, digest from ImageCacheEntry where imageId=^1", imageId )

    local r1, r2, r3 = app:executeCommand( exe, param, { targ }, nil, 'del' )

    local uuid -- of preview

    local digest -- of preview

    if r1 then

        if r3 then

            local c = str:split( r3, '|' )

            if #c >= 2 then

                -- good

                uuid = c[1]

                digest = c[2]

            else

                return nil, "bad split"

            end

        else

            return nil, "no content"

        end

    else

        return nil, r2

    end

 

    local previewSubdir = str:getFirstChar( uuid )

    local pDir = LrPathUtils.child( d, previewSubdir )

    if fso:existsAsDir( pDir ) then

        -- good

    else

        return nil, "preview letter dir does not exist: " .. pDir

    end

    previewSubdir = uuid:sub( 1, 4 )

    pDir = LrPathUtils.child( pDir, previewSubdir )

    if fso:existsAsDir( pDir ) then

        -- good

    else

        return nil, "preview 4-some dir does not exist: " .. pDir

    end

    local previewFilename = uuid .. '-' .. digest .. ".lrprev"

 

    local previewPath = LrPathUtils.child( pDir, previewFilename )

    if fso:existsAsFile( previewPath ) then

        app:logVerbose( "Found preview file at ^1", previewPath )

    else

        return nil, str:fmt( "No preview file corresponding to ^1 at ^2", photo:getRawMetadata( 'photoPath' ), previewPath )

    end

 

    -- this could be modified to return image data instead of file if need be.

    local content

    local function getImageFile()

        local p1, p2 = content:find( "level_" .. str:to( level ) )

        if p1 then

            local start = p2 + 2 -- jump over level_n\0

            local p3 = content:find( "AgHg", start )

            local stop

            if p3 then

                stop = start + p3 - 1

            else

                stop = content:len() - 1

            end

            local data = content:sub( start, stop )

            if previewFile ~= nil then -- user passed file

                app:logVerbose( "Writing preview into user file: ^1", _previewFile )

            else

                -- rename file to include level.

                local base = LrPathUtils.removeExtension( _previewFile ) .. '_' .. level

                _previewFile = base .. ".jpg"

                app:logVerbose( "Writing preview into default-named file: ^1", _previewFile )

            end

            local s, m = fso:writeFile( _previewFile, data )

            if s then

                app:logVerbose( "Wrote preview file: ^1", _previewFile )

                return _previewFile

            else

                return nil, m

            end

        else

            return nil -- no real error, just no preview at that level.

        end

    end   

 

    minLevel = minLevel or 1

 

    local status

    status, content = LrTasks.pcall( LrFileUtils.readFile, previewPath )

    if status and content then

        repeat

            local file, errm = getImageFile() -- at level

            if file then

                return file, nil, level

            elseif errm then

                return nil, errm

            elseif level > minLevel then

                level = level - 1

            else

                return nil, str:fmt( "No preview for ^1 at any acceptable level", photoPath )

            end

        until level <= 0

        return nil, str:fmt( "Unable to obtain preview for ^1", photoPath )

    else

        return nil, str:fmt( "Unable to read preview source file at ^1, error message: ^2", previewPath, content )

    end   

end

 

This function is working great so far, but as of 2011-09-29 it has not been rigorously tested, so it may have a bug or two...

It is based on the elare plugin framework available here (including source code): https://www.assembla.com/spaces/lrdevplugin/

 

You will need sqlite3 executable from here: http://www.sqlite.org/sqlite.html

- put it in lr(dev)plugin dir

 

Note: view-factory's picture component will accept a path as resource id, so to use:

 

local pictureFile, errm = cat:getPreview( photo, nil, nil, 4 )

if pictureFile then

   items[#items + 1] = vf:picture {

       value = pictureFile,

    }

end

 

Note: the above code is intended for "sample/example" only -

 

MUST DO:

- Handle portrait orientation properly...

 

MAYBE DO:

- Handle AdobeRGB profile assignment - not needed for thumbs, but maybe for the biggies...

- Optimize for multi-photo use.

- Change detection for sake of caching for repeated access (like scrolling thumbnails).

 

@2011-10-04, the code at Assembla.com (see link above) takes care of all these things, and then some...;-)

 

Rob


Scripts - Not plugins

$
0
0

I recently discovered a new feature in Lightroom 4 (not documented).

 

Add a Scripts directory (sibling of 'Modules' directory) and you can run lua scripts without making full-blown plugins.

 

e.g. D:\Users\{me}\AppData\Roaming\Adobe\Lightroom\Scripts\HelloWorld.lua

 

local LrDialogs = import 'LrDialogs'

LrDialogs.message( "Hello", "(World)" )

 

Appears as 'HelloWorld' in Scripts Menu (Main Lightroom Toolbar - for all modules).

 

(restart Lightroom after adding new scripts).

 

Rob

Font selection view control in Web Gallery

$
0
0

LR4.1 RC2

 

I wanted to be able to change the font type from the UI panel using a font select popup.

This control really only seems to exist in the inbuilt edit modes (eg: id plate and watermark) so I have tried a workround which seems to work OK so far. Maybe it will help someone else out working with webengines.

 

Mac/OSX only at this stage - good source file in Windows may be font.inf but would require a bit of parsing or get a folder listing somehow.

Basically I read in the contents of the fonts.list file - which appears in the OSX fonts folders - and then massage the contents to get a raw list of the fonts.

This raw list is then read into a lua table and consumed by the UI popup control.

 

Should there be an obvious way that I haven't seen then just give me time to find a banana to eat ... anyway here goes -

 

 

Changing the font type for the cell index numbers.

 

Grid cells use cellIndex to give the photo number and in my webengine the css class is .itemNumber       

 

 

Data Model references -   Note:   %s is important for select to work - if %q is used select will work but font won't change ( %q adds quotes to the string ).

 

            ["appearance.itemNumber.font"] = function() return string.format( "%s", nonCSS.itemNumberFontSize .. "px " .. nonCSS.itemNumber.font ) end,

 

            ["nonCSS.itemNumberFontSize"] = 60,

            ["nonCSS.itemNumber.font"] = "inherit", 

 

 

 

            fontlistpath = LrPathUtils.child('/Library/Fonts','')    -- OSX Default fonts

 

 

 

Code just prior to LR UI Views -

 

        deffonts = templatepath .. "/pgresources/" .. 'osxdeffont.txt'      -- templatepath is the root path of the webengine - this is the tweaked OSX fonts.list file

 

        function readFontsFile( deffonts )

 

            local fileLines = io.lines( deffonts ) 

            ff3 = {}           

            for line in io.lines(deffonts) do

--   ******************* 

Filter lines here ...

 

eg:   -

                line = string.sub(line, 17)   -- remove 1st 16 chrs        (/Library/Fonts//Osaka.ttf)

                line = string.gsub(line, "(.ttf)", "")

 

 

-- ***********************

                local kline = line

                   local vline = line

                   table.insert(ff3, { title =  kline ,value = vline })

            end

        end

 

 

LR UI View for font select -

 

            f:popup_row {

                title = "Font family :",

                bindingValue = "nonCSS.itemNumber.font",

                items =  ff3,

                bindingEnabled = "appearance.itemNumber.display",   -- control should be disabled if display checkbox false

                tooltip = "Choose wisely Dave!",

            },

 

 

Using this method is not perfect but gives a good selection of fonts - I found that to improve the success rate the default font file was copied into the webengine

resources folder and tweaked. eg:  the default file gives Brush Script.ttf but I needed Brush Script MT to work, similarly with Arial Rounded Bold which needed changing

to Arial Rounded MT Bold

 

Basically to find the correct descriptions you could do far worse than to use the ones in the edit selections used by the ID Plate/watermarking features.

 

 

            Well there you go ...

 

As an aside I did try an undocumented control which on double click popped up a system font selection dialog (the whole nine yards) but  couldn't get it to link to the css class so I didn't persist - not a good idea to use undocumented controls but can be fun to play with.

 

    f:font_picker {

        font = "Copperplate",     -- showed font as highlighted when picker opened.

        width = 80,

        value = "Arial",    -- appeared on control (title ??) - this value only changed according to the font selected after double-clicking on another hidden control (f:image_well)

        bindingValue = "nonCSS.itemNumber.font",  -- linkage didn't work

    },

 

 

Again, unless I missed it, it would be really good to have the font_picker documented and working for the web gallery views.  Fonts seem to be a murky area -

probably accounts for the hassles I am getting with the watermarking feature as well.

 

 

Update :

 

If the font doesn't work try using the PostScript name as a value which invariably works.

 

eg: Handwriting - Dakota  will not work but Handwriting-Dakota will.

     Arial Bold will not work but Arial-BoldMT will.

Localized conversion from string to number?

$
0
0

Neither the SDK nor the core Lua library appears to provide localized conversions from strings to numbers, e.g. accepting "1.23" in the US and "1,23" in other countries, as appropriate.  Of course, I can substittue "." for "," before invoking tonumber(), but have I missed a better, more robust approach?

Moving files using the Lightroom SDK

$
0
0

I've been playing with the Lightroom SDK and I'm trying to move files within Lightroom.

I can use the SDK to create a folder and move the file into it but Lightroom does not know the file has moved.

Is there a way to tell Lightroom the files has moved using the SDK?

Copy develop settings from one photo to another: having problems! photo:getDevelopSettings LrDevelopController.setValue

$
0
0

I've also attached the full code at the bottom of this message in case that helps, but, to summarize,

 

I have a lua plugin (MIDI2LR by rsjaffe) that receives MIDI messages from an application through a LrSocket. Everything has been working, but I've tried to add copy/paste develop settings without success.

 

In the following code, the copy settings is:

function copySettings()

    local photo = LrApplication.activeCatalog():getTargetPhoto()

    settings = photo:getDevelopSettings()

end

and the paste settings is:

function pasteSettings()

    applySettings(settings) 

end


function applySettings(set) --still experimental

    if LrApplicationView.getCurrentModuleName() ~= 'develop' then

            LrApplicationView.switchToModule('develop')

    end

    for x,v in pairs(set) do

--      SERVER:send(string.format('%s %d\n', x, develop_lerp_to_midi(v)))

--      PARAM_OBSERVER[x] = v

      LrDevelopController.setValue(x,v)

    end

end


The functions do get called, but nothing happens to the target photo. I've also been unable to attach a debugger (tried ZeroBrane studio as described in Debugging Adobe Lightroom plugins with ZeroBrane Studio - ZeroBranebut can't get Lightroom to load mobdebug.lrmodule.


Can someone point out where I'm going wrong?

Thanks.


 

 

 

 

require 'strict.lua' -- catch some incorrect variable names

require 'Develop_Params.lua' -- global table of develop params we need to observe

local LrApplication      = import 'LrApplication'

local LrApplicationView  = import 'LrApplicationView'

local LrDevelopController = import 'LrDevelopController'

local LrFunctionContext  = import 'LrFunctionContext'

local LrSelection        = import 'LrSelection'

local LrShell            = import 'LrShell'

local LrSocket            = import 'LrSocket'

local LrTasks            = import 'LrTasks'

local LrUndo              = import 'LrUndo'

 

 

-- File-local consts

local RECEIVE_PORT = 58763

local SEND_PORT    = 58764

local PICKUP_THRESHOLD = 4

 

 

-- File-local vars

local CopyUUID

local settings

local LAST_PARAM = ''

local PARAM_OBSERVER = {}

local PICKUP_ENABLED = true

local SERVER = {}

 

 

--File-local function declarations, advance declared to allow it to be in scope for all calls.

--When defining pre-declared function, DO NOT USE local KEYWORD again, as it will define yet another local function.

--These declaration are intended to get around some Lua gotcha's.

local applySettings

local copySettings

local develop_lerp_to_midi

local midi_lerp_to_develop

local pasteSettings

local processMessage

local sendChangedParams

local startServer

local updateParam

 

 

local ACTIONS = {

 

 

    ['DecrementLastDevelopParameter'] = function () LrDevelopController.decrement(LAST_PARAM) end,

    ['VirtualCopy']      = function () LrApplication.activeCatalog():createVirtualCopies() end,

    ['ToggleScreenTwo']  = LrApplicationView.toggleSecondaryDisplay,

    ['CopySettings']    = copySettings,

    ['PasteSettings']    = pasteSettings,

}

 

 

local TOOL_ALIASES = {

    ['Loupe']          = 'loupe',

    ['CropOverlay']    = 'crop',

    ['SpotRemoval']    = 'dust',

    ['RedEye']          = 'redeye',

    ['GraduatedFilter'] = 'gradient',

    ['RadialFilter']    = 'circularGradient',

    ['AdjustmentBrush'] = 'localized',

}

 

 

local SETTINGS = {

    ['Pickup'] = function(enabled) PICKUP_ENABLED = (enabled == 1) end,

}

 

 

function copySettings()

    local photo = LrApplication.activeCatalog():getTargetPhoto()

    settings = photo:getDevelopSettings()

end

 

 

function pasteSettings()

    applySettings(settings) 

end

 

 

function midi_lerp_to_develop(param, midi_value)

    -- map midi range to develop parameter range

    local min,max = LrDevelopController.getRange(param)

--    if(param == 'Temperature') then

--        min = 3000

--        max = 9000

--    end

   

    local result = midi_value/127 * (max-min) + min

    return result

end

 

 

function develop_lerp_to_midi(param)

    -- map develop parameter range to midi range

    local min, max = LrDevelopController.getRange(param)

--    if(param == 'Temperature') then

--        min = 3000

--        max = 9000

--    end

   

    local result = (LrDevelopController.getValue(param)-min)/(max-min) * 127

    return result

end

 

 

function updateParam(param, midi_value)

    -- this function does a 'pickup' type of check

    -- that is, it will ensure the develop parameter is close

    -- to what the inputted command value is before updating it

    if LrApplicationView.getCurrentModuleName() ~= 'develop' then

            LrApplicationView.switchToModule('develop')

    end

   

    if((not PICKUP_ENABLED) or (math.abs(midi_value - develop_lerp_to_midi(param)) <= PICKUP_THRESHOLD)) then

        PARAM_OBSERVER[param] = midi_lerp_to_develop(param, midi_value)

        LrDevelopController.setValue(param, midi_lerp_to_develop(param, midi_value))

        LAST_PARAM = param

    end

end

 

 

function applySettings(set) --still experimental

    if LrApplicationView.getCurrentModuleName() ~= 'develop' then

            LrApplicationView.switchToModule('develop')

    end

    for x,v in pairs(set) do

--      SERVER:send(string.format('%s %d\n', x, develop_lerp_to_midi(v)))

--      PARAM_OBSERVER[x] = v

      LrDevelopController.setValue(x,v)

    end

end

 

 

-- message processor

function processMessage(message)

    if type(message) == 'string' then

        -- messages are in the format 'param value'

        local _, _, param, value = string.find( message, '(%S+)%s(%d+)' )

     

        if(ACTIONS[param] ~= nil) then -- perform a one time action

            if(tonumber(value) == 127) then ACTIONS[param]() end

        elseif(param:find('Reset') == 1) then -- perform a reset other than those explicitly coded in ACTIONS array

          if(tonumber(value) == 127) then LrDevelopController.resetToDefault(param:sub(6)) end

        elseif(param:find('SwToM') == 1) then -- perform a switch to module

            if(tonumber(value) == 127) then LrApplicationView.switchToModule(param:sub(6)) end

        elseif(param:find('ShoVw') == 1) then -- change application's view mode

            if(tonumber(value) == 127) then LrApplicationView.showView(param:sub(6)) end

        elseif(param:find('ShoScndVw') == 1) then -- change application's view mode

            if(tonumber(value) == 127) then LrApplicationView.showSecondaryView(param:sub(10)) end

        elseif(TOOL_ALIASES[param] ~= nil) then -- switch to desired tool

            if(tonumber(value) == 127) then

                if(LrDevelopController.getSelectedTool() == TOOL_ALIASES[param]) then -- toggle between the tool/loupe

                    LrDevelopController.selectTool('loupe')

                else

                    LrDevelopController.selectTool(TOOL_ALIASES[param])

                end

            end

        elseif(SETTINGS[param] ~= nil) then

            SETTINGS[param](tonumber(value))

        else -- otherwise update a develop parameter

            updateParam(param, tonumber(value))

        end

    end

end

 

 

-- send changed parameters to MIDI2LR

function sendChangedParams( observer )

    for _, param in ipairs(DEVELOP_PARAMS) do

        if(observer[param] ~= LrDevelopController.getValue(param)) then

            SERVER:send(string.format('%s %d\n', param, develop_lerp_to_midi(param)))

            observer[param] = LrDevelopController.getValue(param)

            LAST_PARAM = param

        end

    end

end

 

 

function startServer(context)

    SERVER = LrSocket.bind {

          functionContext = context,

          plugin = _PLUGIN,

          port = SEND_PORT,

          mode = 'send',

          onClosed = function( socket ) -- this callback never seems to get called...

            -- MIDI2LR closed connection, allow for reconnection

            -- socket:reconnect()

          end,

          onError = function( socket, err )

            socket:reconnect()

          end,

        }

end

 

 

-- Main task

LrTasks.startAsyncTask( function()

    LrFunctionContext.callWithContext( 'socket_remote', function( context )

        LrDevelopController.revealAdjustedControls( true ) -- reveal affected parameter in panel track

       

        -- add an observer for develop param changes

        LrDevelopController.addAdjustmentChangeObserver( context, PARAM_OBSERVER, sendChangedParams )

       

        local client = LrSocket.bind {

            functionContext = context,

            plugin = _PLUGIN,

            port = RECEIVE_PORT,

            mode = 'receive',

            onMessage = function(socket, message)

                processMessage(message)

            end,

            onClosed = function( socket )

                -- MIDI2LR closed connection, allow for reconnection

                socket:reconnect()

               

                -- calling SERVER:reconnect causes LR to hang for some reason...

                SERVER:close()

                startServer(context)

            end,

            onError = function(socket, err)

                if err == 'timeout' then -- reconnect if timed out

                    socket:reconnect()

                end

            end

        }

       

        startServer(context)

       

        while true do

            LrTasks.sleep( 1/2 )

        end

       

        client:close()

        SERVER:close()

    end )

end )

 

LrTasks.startAsyncTask( function()

    if(WIN_ENV) then

        LrShell.openFilesInApp({_PLUGIN.path..'/Info.lua'}, _PLUGIN.path..'/MIDI2LR.exe')

    else

        LrShell.openFilesInApp({_PLUGIN.path..'/Info.lua'}, _PLUGIN.path..'/MIDI2LR.app') -- On Mac it seems like the files argument has to include an existing file

    end

end)

Viewing all 53524 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>