Adobe 65007312 - Photoshop Lightroom Programmer's Manual

Mac
Hide thumbs Also See for 65007312 - Photoshop Lightroom:
Table of Contents

Advertisement

LIGHTROOM SDK 3.0
PROGRAMMERS GUIDE

Advertisement

Table of Contents
loading

Summary of Contents for Adobe 65007312 - Photoshop Lightroom

  • Page 1 LIGHTROOM SDK 3.0 PROGRAMMERS GUIDE...
  • Page 2 Adobe Systems Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license agreement.
  • Page 3: Table Of Contents

    Contents Preface ..............8 The Lightroom SDK .
  • Page 4 Contents Adding custom sections to the Export or Publishing Manager dialog ....53 Restricting existing service functionality ..........55 Remembering user choices .
  • Page 5 Contents Writing a Web-engine Plug-in ..........115 Creating a web-engine plug-in .
  • Page 6 Contents Getting Started: A Tutorial Example ........168 Creating an export plug-in .
  • Page 7 Contents Define the tags ..............203 Add the tagset to the gallery .
  • Page 8: Preface

    Preface The Adobe® Photoshop® Lightroom® Software Development Kit (SDK) is a scripting interface to Lightroom that allows you to extend and customize Lightroom functionality. Use the SDK API to write plug-ins for Lightroom. This release allows you to customize the behavior of Lightroom’s export and publish operations, define Lightroom-specific metadata for photos, and create customized HTML web galleries.
  • Page 9: The Lua Language

    Preface websample.lrwebengine helloworld.lrdevplugin mymetadata.lrdevplugin mysample.lrwebengine The Lua language The SDK defines a Lua-language scripting API. For guidance on using the Lua language, we recommend reviewing the official Lua web site, http://www.lua.org/, and the book “Programming in Lua, second edition,” by Roberto Ierusalimschy. Lightroom 3.0 uses version 5.1.2 of the Lua language. The Lightroom SDK provides a Lua scripting environment, which extends the Lua languages with an object-oriented infrastructure;...
  • Page 10: Conventions Used In This Document

    Preface Chapter 9, “Getting Started: A Tutorial create your first plug-in. Chapter 10, “Defining Metadata: A properties for your photos. Chapter 11, “Web Gallery Plug-ins: A Tutorial web-engine plug-in. Conventions used in this document The following type styles are used for specific types of text: Typeface Style Monospace font Monospace bold...
  • Page 11: Using The Lightroom Sdk

    Using the Lightroom SDK This chapter provides an introduction to the Lightroom SDK: “Writing plug-ins for Lightroom” on page 11 details of the information file and file-system locations. “The Lightroom SDK scripting environment” on page 12 Lightroom SDK scripting environment, and provides details of what tools are available to you within the SDK scripting environment.
  • Page 12: The Lightroom Sdk Scripting Environment

    1: Using the Lightroom SDK HAPTER The Lightroom SDK scripting environment The SDK defines a Lua-language scripting API. The Lua scripting language is a fast, light-weight, embeddable scripting language. For information about the language, see http://www.lua.org/. The Lightroom scripting environment provides a programming structure that includes some enhancements to the basic Lua-language constructs.
  • Page 13 1: Using the Lightroom SDK HAPTER The Lightroom SDK defines these namespaces; for complete details, see the Lightroom SDK API Reference. Namespace LrApplication LrBinding LrDate LrDialogs LrErrors LrExportSettings LrFileUtils LrFtp LrFunctionContext LrHttp LrLocalization LrMath LrMD5 LrPasswords LrPathUtils LrPhotoInfo LrPrefs LrProgressScope LrShell LrStringUtils LrSystemInfo...
  • Page 14 1: Using the Lightroom SDK HAPTER Namespace LrView LrXml Creating objects When you use the the constructor to create objects, which you can initialize with specific property values. You can then access the functions and properties through the object using colon notation. This example shows the standard way to create and use an object: local LrLogger = import 'LrLogger' -- LrLogger is a constructor function, not a table with more functions...
  • Page 15 1: Using the Lightroom SDK HAPTER Class LrCollectionSet LrColor LrDevelopPreset LrDevelopPreset Folder LrExportContext LrExportRendition LrExportSession LrFolder LrFtp Description Object creation Provides access to a Returned by: photo collection set. LrCatalog:createCollectionSet() LrCatalog:getCollectionSets() LrCollectionSet:getChildren() LrCollection:getParent() LrCollectionSet:getParent() LrCollectionSet:getChildCollectionSets() Encapsulates a color. Import constructor: local LrColor = import 'LrColor' Provides access to a Returned by...
  • Page 16 1: Using the Lightroom SDK HAPTER Class LrFunctionContext LrKeyword LrLogger LrPhoto LrPlugin LrProgressScope LrPublished Collection LrPublished CollectionSet Description Object creation Both a namespace and a Import the namespace: class. Use the object to local LrFunctionContext = import register the cleanup handlers for the called function execution.
  • Page 17 1: Using the Lightroom SDK HAPTER Class LrPublishedPhoto LrPublishService LrRecursionGuard LrView LrWebViewFactory LrXml Description Object creation Encapsulates the Returned by publishing information LrPublishedCollection:getPublishedPhotos() associated with a photo that is part of a published collection. Provides access to a Returned by named publishing service.
  • Page 18 1: Using the Lightroom SDK HAPTER Accessing object functions and properties A few classes ( LrFtp allow you to call some functions directly in the imported namespace, using dot notation. By convention, the documentation uses lowercase names, as well as colon notation, to indicate that a function is called on an instance.
  • Page 19 1: Using the Lightroom SDK HAPTER This shows the predefined error dialog with customized text, according to how the error was thrown: Using built-in Lua features The Lua language defines built-in namespaces and global functions, of which only a subset are supported in the Lightroom SDK Lua environment, as follows: Lua global functions Available in Lightroom:...
  • Page 20: Defining Function Contexts And Tasks

    1: Using the Lightroom SDK HAPTER Defining function contexts and tasks Your plug-in can use a function context to create and manage a task, which is a kind of lightweight process that runs cooperatively on Lightroom's main (user interface) thread. If your service defines a lengthy export operation that would block the main Lightroom process, you should run it as a background task, using functions such as as those in the...
  • Page 21: Lua Syntax Notes

    1: Using the Lightroom SDK HAPTER SomeFile.doSomething( 42 ) Lua syntax notes For people unfamiliar with the Lua language, here are some syntax conventions and usage notes. Literal strings can be surrounded by either single or double quotes. These two statements are equivalent: local a = 'my string' local a = "my string"...
  • Page 22: Writing A Lightroom Plug-In

    Writing a Lightroom Plug-in The Lightroom SDK allows you to create plug-ins that customize the behavior of Lightroom in specific ways. Most types of plug-in share a common architecture, which is discussed in this chapter. Web Gallery plug-ins use a different architecture; see The Plug-in Manager dialog allows a user to load plug-ins from any location, enable and disable loaded plug-ins, and remove unused plug-ins.
  • Page 23 If you enable one, any other plug-in that shares the same plug-in ID is automatically disabled. Note that com.adobe.* reserved for plug-ins written by Adobe; your own plug-ins will use your own domain name ( Required A localizable string for the plug-in’s display name, which for 2.0 or...
  • Page 24 2: Writing a Lightroom Plug-in HAPTER LrDisablePlugin VERSION LrExportMenuItems LrLibraryMenuItems LrHelpMenuItems Optional A function that is called when the user disables this plug-in from the Plug-in Manager dialog. function Ignored in any Lightroom version older than 3.0. Optional Allows you to provide a version number for your plug-in that is displayed in the Plug-in Manager dialog.
  • Page 25 2: Writing a Lightroom Plug-in HAPTER LrExportFilterProvider LrExportServiceProvider Optional Adds one or more new export filters, which can process photos before they are rendered for the export destination. table of tables Each item is a table with these entries: (string): The display name of the filter. title (string): The name of the Lua file (filter definition file...
  • Page 26: Can Be Combined With Other Services

    Here is an example of an return { LrSdkVersion = 3.0, LrSdkMinimumVersion = 1.3, -- minimum SDK version required by this plug-in LrToolkitIdentifier = 'com.adobe.lightroom.sdk.helloworld', LrPluginName = LOC "$$$/HelloWorld/PluginName=Hello World Sample", -- Add the menu item to the File menu. Optional Adds custom metadata fields, available only in Lightroom.
  • Page 27: Delivering A Standard Plug-In

    2: Writing a Lightroom Plug-in HAPTER LrExportMenuItems = { title = "Hello World Dialog", file = "ExportMenuItem.lua", -- Add the menu item to the Library menu. LrLibraryMenuItems = { title = LOC "$$$/HelloWorld/CustomDialog=Hello World Custom Dialog", file = "ShowCustomDialog.lua", title = LOC "$$$/HelloWorld/MultiBind=Hello world Custom Dialog with MultipleBind", file = "CustomDialogWithMultipleBind.lua", title = LOC "$$$/HelloWorld/RadioButtons=Hello world RadioButtons",...
  • Page 28: The Plug-In

    2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 28 HAPTER The standard Plug-in Manager dialog in Lightroom looks like this: Your plug-in can customize the Plug-in Manager, adding sections that appear when a user selects your plug-in in the dialog. For example, in the following figure, the plug-in called “Plug-in Info Sample” defines two custom sections, one above and one below the Lightroom-defined sections.
  • Page 29 The Remove button is dimmed when such a plug-in is selected. “Adding custom sections to the Plug-in Manager” on ~/Library/Application Support/Adobe/Lightroom/Modules /Library/Application Support/Adobe/Lightroom/Modules C:\Documents and Users\username\Application...
  • Page 30: Debugging Standard Plug-Ins

    2: Writing a Lightroom Plug-in HAPTER Debugging standard plug-ins The Plug-in Manager also provides access to tools for plug-in authors. This section is generally not needed by end users, and is closed by default. If you open the "Plug-in Author Tools"...
  • Page 31: Initialization And Termination Functions For The Plug-In Manager

    Plug-in Manager dialog. For example: return { LrSdkVersion = 3.0, LrSdkMinimumVersion = 2.0, -- minimum SDK version required by this plug-in LrToolkitIdentifier = 'com.adobe.lightroom.sample.plug-in-info', LrPluginName = LOC "$$$/PluginInfo/Name=Plug-in Info Sample", LrPluginInfoProvider = 'PluginInfoProvider.lua', LrInitPlugin = 'PluginInit.lua', LrPluginInfoUrl = 'http://www.mycompany.com/lrplugin_info.html',...
  • Page 32: Adding Custom Sections To The Plug-In Manager

    2: Writing a Lightroom Plug-in HAPTER selected in the Export dialog, never from the Plug-in Manager dialog. See functions for services” on page The propertyTable parameter for both functions is an empty, observable table which you can use to keep private data for your plug-in.
  • Page 33: Defining Menu Items For A Plug-In

    2: Writing a Lightroom Plug-in HAPTER When adding sections to the Plug-in Manager, the propertyTable parameter for both functions is an empty, observable table which you can use to keep private data for your plug-in for a dynamic user interface. See “Binding UI values to data values”...
  • Page 34: Defining An Export

    2: Writing a Lightroom Plug-in HAPTER (String) The name of the Lua file (service definition script) to be executed when the menu file item is chosen. See (String, optional) A condition under which to enable this menu item. One of: enabledWhen If the selection is very large (>5000 photos), menu items are enabled regardless of this value.
  • Page 35: Creating Export And Publish Services

    Creating Export and Publish Services Plug-ins can customize Lightroom's export and publish behavior. You can: Create an Export Filter that modifies a photo after Lightroom performs the initial rendering, but before it is passed to it final export destination. Alter the rendering process, or define post-processing actions for rendered photos. Send rendered images to locations other than files on the local computer.
  • Page 36 3: Creating Export and Publish Services HAPTER title file localize the service’s title; see details in The service definition script should return a table that contains: A pair of functions that initialize and terminate your export service. Settings that you define for your export service. One or more items that define the desired customizations for the Export dialog.
  • Page 37 3: Creating Export and Publish Services HAPTER Item canExportToTemporaryLocation showSections hideSections allowFileFormats disallowFileFormats allowColorSpaces disallowColorSpaces sectionsForTopOfDialog sectionsForBottomOfDialog hidePrintResolution additional publish service options Description A Boolean value that indicates whether the service provider can place files in a temporary export destination in the local file system.
  • Page 38: Initialization And Termination Functions For Services

    3: Creating Export and Publish Services HAPTER Initialization and termination functions for services You can provide functions to be called when a post-process action or export destination defined by your plug-in is selected or deselected in the Export or Publishing Manager dialog. To do so, the service definition script for your Export Filter Provider or Export Service Provider should return these table entries, which contain the function definitions: startDialog = function( propertyTable ) ...
  • Page 39: Defining A Publish Service

    3: Creating Export and Publish Services HAPTER Defining a publish service Starting with version 3.0, Lightroom allows you to send photos to a local or network destination for publication. The publication process is similar to the export process, and the Publishing Manager dialog is largely similar to the Export dialog.
  • Page 40: Publish Service Options

    3: Creating Export and Publish Services HAPTER A publish service keeps track of the locations to which items have been published, and can access those locations. A publish service can manage collections or folders on the remote export destination from within the Lightroom catalog.
  • Page 41: Adding An Export Post-Process Action

    3: Creating Export and Publish Services HAPTER Provider; for details of how to define these items and what they do, see the API Reference documentation and the Flickr plug-in. Adding an export post-process action An Export Filter Provider is a script that allows you to modify a photo after Lightroom performs the initial rendering, but before it is passed to it final export destination, by defining a post-process action.
  • Page 42 3: Creating Export and Publish Services Adding an export post-process action 42 HAPTER An action that has been inserted is flagged with a check mark; when it is selected, the Remove button is enabled, allowing you to remove it from the processing queue. When an action is inserted, the related section is shown in the Export dialog.
  • Page 43: Action Dependencies

    3: Creating Export and Publish Services Adding an export post-process action 43 HAPTER Action dependencies You can set up a dependency among a set of actions, such that one action actually performs the photo processing, and other actions in the set are used to determine the parameters for that operation. The one that performs the rendition is typically the only one that defines a function.
  • Page 44: Declaring Export Post-Process Actions

    3: Creating Export and Publish Services HAPTER user clicks Export. In this case, the request is intercepted and redirected to Color. Color receives a list of renditions that it is expected to satisfy; the action then makes its own rendition request. This request is similarly intercepted and sent to MyAction.
  • Page 45: Defining A Post-Process Action

    3: Creating Export and Publish Services HAPTER title = "Lines", file = "lineAction.lua", id = "lines", requiresFilter = "main", Defining a post-process action An action definition script must return a table which can contain these entries. All entries are optional. postProcessRenderedPhotos shouldRenderPhoto startDialog...
  • Page 46: Removing Photos From The Export Operation

    3: Creating Export and Publish Services HAPTER Removing photos from the export operation If you wish to remove photos from the list of those to be exported, based on criteria of your choosing, your action definition script can define a function named parameters, the export settings and the current photo, and is called successively on each entry in the list of rendered photos passed to the action.
  • Page 47: How Post-Process Actions Are Executed

    3: Creating Export and Publish Services HAPTER -- By doing so, you assume responsibility for creating -- the file type that was originally requested and placing it -- in the location that was originally requested in your -- filter loop below. end, for sourceRendition, renditionToSatisfy in filterContext:renditions( renditionOptions ) do...
  • Page 48 3: Creating Export and Publish Services HAPTER This Export Dialog shows three Export Filter Providers, whose actions have all been inserted in the processing queue. The Export Service Provider for FTP Upload (one of the sample plug-ins included in the SDK) has been selected.
  • Page 49 3: Creating Export and Publish Services HAPTER It then calls exportSession:doExportOnCurrentTask() you wish to start an export without using the export dialog, you can make the same calls yourself.) In this discussion, an Export Service Provider is called a service, and an Export Filter Provider is called a filter. Stage 1: Deciding how the photos should be rendered If the service has defined an argument, the export-settings table, and allows the service to force certain render settings to its preferred...
  • Page 50 3: Creating Export and Publish Services HAPTER 5. For each filter, if a called only once, regardless of the number of photos being exported. This function should enter into a loop of the form: for sourceRendition, renditionToSatisfy in filterContext:renditions() do ... end The filter context object generates a new rendition request ( renditions provided this filter.
  • Page 51: Final Processing Of Rendered Photos

    3: Creating Export and Publish Services HAPTER 3. When the processing operation is finished, the filter must report its status on the rendition by calling renditionToSatisfy:renditionIsDone( success, message ) This is done automatically by the done so explicitly. The iterator verifies that a file exists at the expected path and signals success or failure accordingly.
  • Page 52: Customizing The Export And Publishing Manager Dialogs

    3: Creating Export and Publish Services HAPTER Use the export-context object to gain access to the setting chosen by the user (in exportContext.propertyTable Use the export-context object to configure the progress indicator to update as photos are displayed. This would look like this example adapted from the Flickr plug-in: local progressScope = exportContext:configureProgress { title = nPhotos >...
  • Page 53: Adding Custom Sections To The Export Or Publishing Manager Dialog

    3: Creating Export and Publish Services HAPTER The drop-down menu at the top of the Export dialog, labeled “Export To, ” gives you a choice of destinations: Your plug-in can provide an export service that allows the user to choose a different destination, such a remote site, and define how the image files are sent to that destination;...
  • Page 54 3: Creating Export and Publish Services HAPTER The function that you define here returns a table of tables, where each table defines one dialog section: sectionsForTopOfDialog = function( viewFactory, propertyTable ) return { { ...section entry ... }, { ...section entry ... }, A section entry table defines the contents of an implicit container, which Lightroom creates to hold your view hierarchy.
  • Page 55: Restricting Existing Service Functionality

    3: Creating Export and Publish Services HAPTER return { -- create section entries { -- first section entry This code creates this custom section at the top of the Export dialog (when defined by an LrExportServiceProvider Restricting existing service functionality Your service can restrict the built-in services offered by the Export and Publishing Manager dialogs, by hiding some of the built-in sections that are normally displayed, or by limiting the options offered by the dialog.
  • Page 56 3: Creating Export and Publish Services HAPTER A single toggle entry controls whether users can select measurement units: hidePrintResolution = Boolean The rest of the service table entries that restrict existing functionality in the dialog come in positive and negative forms; that is, you can list the features to be included, or you can list the features to be excluded. For each such pair, you can provide only one of the entries, not both.
  • Page 57: Remembering User Choices

    3: Creating Export and Publish Services HAPTER Restriction Service table entries Section display showSections = {’section’[, ...] }, hideSections = { ’section’[, ...] }, which was removed in Lightroom 2.0. This section is now only available with the built-in “Export to Files on Disk” service. If specified, it is ignored by Lightroom 2.0 or newer.
  • Page 58: Export Presets

    3: Creating Export and Publish Services HAPTER For example: exportPresetFields = { { key = 'privacy', { key = 'privacy_family', { key = 'privacy_friends', default = false { key = 'safety', { key = 'hideFromPublic', { key = 'type', { key = 'addTags', The settings you declare here are automatically saved along with the export settings already defined by Lightroom (see “Lightroom built-in property keys”...
  • Page 59: Settings For Publish Services And Post-Process Actions

    3: Creating Export and Publish Services HAPTER 3. Right-click (control-click in Mac OS) on the newly-created Preset to find the preset file. Move the preset file from that folder to the subfolder that you specified using the LrExportServiceProvider Settings for publish services and post-process actions Although you can define persistent setting for a publish service using the those values are saved as part of any publish service the user creates in the Publishing Manager dialog, you cannot associate a preset with a publish service.
  • Page 60: File Naming Section Properties

    3: Creating Export and Publish Services HAPTER LR_reimport_stackWithOriginal LR_collisionHandling File Naming section properties LR_extensionCase LR_initialSequenceNumber LR_renamingTokensOn LR_tokenCustomString LR_tokens Token patterns This is the complete list of patterns that are allowed in the menu in the File Naming Template dialog: Image Name and Custom patterns Pattern {{image_name}} {{image_filename_number_suffix}}...
  • Page 61 3: Creating Export and Publish Services HAPTER Pattern {{image_originalName_number_suffix}} {{copy_name}} {{custom_token}} Sequence and Date patterns Pattern {{naming_sequenceNumber_1Digit}} {{naming_sequenceNumber_2Digits}} {{naming_sequenceNumber_3Digits}} {{naming_sequenceNumber_4Digits}} {{naming_sequenceNumber_5Digits}} {{naming_operationSequence_1Digit}} {{naming_operationSequence_2Digits}} {{naming_operationSequence_3Digits}} {{naming_operationSequence_4Digits}} {{naming_operationSequence_5Digits}} {{naming_sequenceTotal_1Digit}} {{naming_sequenceTotal_2Digits}} {{naming_sequenceTotal_3Digits}} {{naming_sequenceTotal_4Digits}} {{naming_sequenceTotal_5Digits}} {{date_LocalEncoding}} {{date_YYYYMMDD}} {{date_YYMMDD}} {{date_YYYY}} {{date_YY}} {{date_Month}} {{date_Mon}} {{date_MM}} {{date_DD}} {{date_Julian}} Lightroom built-in property keys 61 Replaced by...
  • Page 62 3: Creating Export and Publish Services HAPTER {{date_Hour}} {{date_Minute}} {{date_Second}} Metadata patterns Pattern {{com.adobe.title}} {{com.adobe.caption}} {{com.adobe.copyright}} {{com.adobe.keywords}} {{com.adobe.creator}} {{com.adobe.creatorJobTitle}} {{com.adobe.creatorAddress}} {{com.adobe.creatorCity}} {{com.adobe.creatorState}} {{com.adobe.creatorZip}} {{com.adobe.creatorCountry}} {{com.adobe.creatorWorkPhone}} {{com.adobe.creatorWorkEmail}} {{com.adobe.creatorWorkWebsite}} {{com.adobe.descriptionWriter}} {{com.adobe.iptcSubjectCode}} {{com.adobe.intellectualGenre}} {{com.adobe.scene}} {{com.adobe.location}} {{com.adobe.isoCountryCode}} {{com.adobe.headline}} {{com.adobe.city}} {{com.adobe.state}} {{com.adobe.country}} {{com.adobe.jobIdentifier}} {{com.adobe.instructions}} Lightroom built-in property keys 62...
  • Page 63 3: Creating Export and Publish Services HAPTER Pattern {{com.adobe.provider}} {{com.adobe.source}} {{com.adobe.rightsUsageTerms}} {{com.adobe.copyrightInfoURL}} {{com.adobe.imageFileDimensions}} {{com.adobe.imageCroppedDimensions}} {{com.adobe.exposure}} {{com.adobe.focalLength}} {{com.adobe.focalLength35mm}} {{com.adobe.brightnessValue}} {{com.adobe.exposureBiasValue}} {{com.adobe.subjectDistance}} {{com.adobe.ISOSpeedRating}} {{com.adobe.flash}} {{com.adobe.exposureProgram}} {{com.adobe.meteringMode}} {{com.adobe.make}} {{com.adobe.model}} {{com.adobe.serialNumber}} {{com.adobe.artist}} {{com.adobe.software}} {{com.adobe.lens}} {{com.adobe.GPS}} {{com.adobe.GPSAltitude}} {{com.adobe.rating.string}} {{com.adobe.colorLabels.string}} Lightroom built-in property keys 63 Replaced by...
  • Page 64: File Settings Section Properties

    3: Creating Export and Publish Services HAPTER File Settings section properties LR_format LR_export_colorSpace LR_export_bitDepth LR_includeVideoFiles The following apply only if LR_jpeg_quality LR_jpeg_useLimitSize LR_jpeg_limitSize The following apply only if LRtiff_compressionMethod String. File format for still photos. One of: JPEG TIFF ORIGINAL String.
  • Page 65: Image Sizing Section Properties

    String. JPEG preview size. One of: none medium large Number. The oldest version of Adobe Camera Raw/Photoshop that can read these files. One of: 33816576 (Camera Raw 2.4 and later) 67174400 (Camera Raw 4.1 and later) 67502080 (Camera Raw 4.6 and later) 84148224 (Camera Raw 5.4 and later)
  • Page 66: Output Sharpening Section Properties

    3: Creating Export and Publish Services HAPTER LR_size_units Output Sharpening section properties LR_outputSharpeningOn LR_outputSharpeningMedia LR_outputSharpeningLevel Metadata section properties LR_minimizeEmbeddedMetadata LR_metadata_keywordOptions Watermarking section properties LR_useWatermark LR_watermarking_id String. Size constraint units. One of inch pixels Boolean. True when the "Sharpen For" option is checked, false when it is unchecked.
  • Page 67: Post-Processing Filter Section Properties

    3: Creating Export and Publish Services HAPTER Post-Processing Filter section properties LR_exportFiltersFromThisPlugin General export properties This property allows your plug-in to disable the Export button in the Export dialog, or the Save button in the Publishing Manager dialog. LR_cantExportBecause Publish Service properties These properties are part of the settings table passed to the following callbacks, when they are defined as part of a publish service provider: startDialog...
  • Page 68: Working With Metadata

    Info.lua To declare a Metadata Provider, include an return { LrSdkVersion = 3.0, LrToolkitIdentifier = 'com.adobe.lightroom.metadata.sample', LrPluginName = LOC "$$$/CustomMetadata/PluginName=Metadata Sample", LrMetadataProvider = 'SampleMetadataDefinition.lua', The information file that declares a Metadata Provider can also declare metadata tagsets (see custom metadata tagsets” on page...
  • Page 69: Defining Metadata Fields

    4: Working with Metadata HAPTER Defining metadata fields The script for your Metadata Provider defines specific metadata fields. The metadata definition script returns a table that describes the fields to be added to Lightroom's metadata schema. It contains the following fields: metadataFieldsForPhotos schemaVersion updateFromEarlierSchemaVersion...
  • Page 70 4: Working with Metadata HAPTER Metadata field entries Each of the entries in the each metadata field describes a photo in the catalog. Each field can have only one value per photo. The following entries are recognized within each table: string number Optional.
  • Page 71 4: Working with Metadata HAPTER table values Boolean Optional. Use only when readOnly Boolean Optional. Use only when searchable Boolean Optional. Use only when browsable Custom metadata example This sample Metadata Provider script defines three metadata fields of representative types. return { metadataFieldsForPhotos = { id = 'siteId',...
  • Page 72 -- Note: This function is called from within a catalog:withPrivateWriteAccessDo -- block. You should not call any of the with___Do functions yourself. catalog:assertHasPrivateWriteAccess( "SampleMetadataDefinition.updateFromEarlierSchemaVersion" ) local myPluginId = 'com.adobe.lightroom.metadata.sample' if previousSchemaVersion == 1 then local photosToMigrate = catalog:findPhotosWithProperty( myPluginId,'siteId') -- optional: can add property version number here...
  • Page 73: Adding Custom Metadata Tagsets

    Lightroom. This is the Info.lua return { LrSdkVersion = 3.0, LrToolkitIdentifier = 'com.adobe.lightroom.metadata.sample', LrPluginName = LOC "$$$/CustomMetadata/PluginName=Metadata Sample", LrMetadataTagsetFactory = 'SampleTagset.lua', title value as the display string.
  • Page 74: Defining A Metadata Tagset

    If you refer to a plug-in that is missing or that defines no visible metadata, it is not an error; the block and separator for that plug-in are simply not displayed. You can include all visible metadata from a plug-in by specifying the special field name " com.adobe.allPluginMetadata preset. The special name ' field from this plug-in.
  • Page 75: Searching For Photos By Metadata Values

    = LOC "$$$/SampleTagset/Title=Sample Tagset from Plug-in", id = 'sampleTagset', items = { 'com.adobe.filename', 'com.adobe.copyname', 'com.adobe.folder', 'com.adobe.separator', 'com.adobe.title', { 'com.adobe.caption', height_in_lines = 3 }, 'com.adobe.separator', { 'com.adobe.label', label = LOC "$$$/Metadata/SampleLabel=Section Label" }, 'com.adobe.dateCreated', 'com.adobe.location', 'com.adobe.city', 'com.adobe.state', 'com.adobe.country', 'com.adobe.isoCountryCode', 'com.adobe.GPS', 'com.adobe.GPSAltitude', 'com.adobe.lightroom.metadata.sample.randomString',...
  • Page 76 4: Working with Metadata HAPTER for _, photo in ipairs( photos ) do -- do somethingwith path end ) This simple usage is straightforward, although the function allows many matching operations, depending on the datatype of the metadata field to be considered. criteria The allowed values for rating...
  • Page 77 4: Working with Metadata HAPTER country state city location creator jobIdentifier copyrightState hasAdjustments developPreset treatment cropped aspectRatio You can search plug-in defined fields, using these special "allPluginMetadata" sdktext:plugin_id.field_name sdktext:plugin_id.* operation The allowed values for selectable values the Edit Smart Collections dialog. For string values, one of: words noneOf...
  • Page 78 4: Working with Metadata HAPTER For Boolean values, one of " For enumerated values, one of For number and rating values, one of: > < >= <= For date values, one of: > < inLast notInLast today yesterday thisWeek "is", only valid for items that can have an exact match, "is not", only valid for items that can have an exact match ", "...
  • Page 79: Combining Search Criteria

    4: Working with Metadata HAPTER thisMonth thisYear value The value to match against must be of the type indicated for the criteria. Additional parameters are used with specific types and operations, as mentioned above. value_unit Combining search criteria You can create a more complex search descriptor by using a results of several criterion tables: import "LrTasks".startAsyncTask( function() local catalog = import "LrApplication".activeCatalog()
  • Page 80: Creating Searches Interactively

    4: Working with Metadata HAPTER This renders the following statement of Boolean logic: photos where ( rating >= 1 AND labelColor == 1 ) OR ( rating == 5 ) Creating searches interactively If you are unsure how to construct a particular search, you can make Lightroom build it for you. To do this: 1.
  • Page 81 4: Working with Metadata HAPTER 5. Edit the resulting code to change 6. Make any other appropriate changes in the code. In this example, for instance, you would not need element. If you remove it, you can also promote the parameter table to the top level in combine searchDesc searchDesc = {...
  • Page 82: Creating A User Interface For Your Plug-In

    Creating a User Interface for Your Plug-in You can define a user interface to your plug-in with these tools: Your plug-in can define one or more custom sections to be displayed in the Plug-in Manager dialog or Export dialog, above and/or below the Lightroom standard sections. The custom sections are displayed when the user chooses your export destination.
  • Page 83: Using Dialog Boxes

    5: Creating a User Interface for Your Plug-in HAPTER To create the containment hierarchy, use the view factory to create a container, and within that call, use it to create the child containers and controls: viewFactory:group_box { ...initial property settings... viewFactory:row {-- a row of controls within the box ...initial property settings...
  • Page 84: Creating Custom Dialog Boxes

    5: Creating a User Interface for Your Plug-in HAPTER Confirmations and prompts In addition to your text message, these dialogs have configurable OK and Cancel buttons. These return different values to the invocation function, which you use to decide on the action to be taken. Again, there is a "Don’t show again"...
  • Page 85: Controls

    5: Creating a User Interface for Your Plug-in HAPTER Types of containers are: Container type view group_box tab_view tab_view_item column spacer Controls You can use the LrView interface systems. If the creation function is called within the creation of a container, the control is a child of that container.
  • Page 86 5: Creating a User Interface for Your Plug-in HAPTER Control type checkbox color_well combo_box edit_field Description Displays the text with a title platform-style checkbox button. A checkbox is checked (selected) when its is equal to its value checked_value unchecked (deselected) when its equal to its .
  • Page 87 5: Creating a User Interface for Your Plug-in HAPTER Control type password_field picture popup_menu push_button radio_button Description An editable text field that obscures the entered text, displaying only bullet characters. A static image or icon. : you can typically get the path to the image file using this function: _PLUGIN:resourceId(’myPic.png’) A pop-up menu of choices, each with a...
  • Page 88 5: Creating a User Interface for Your Plug-in HAPTER Control type slider static_text separator The following figures show examples of the various control and container types. The appearance is appropriate to the platform; these examples show some of each. Description A draggable “bug”...
  • Page 89 5: Creating a User Interface for Your Plug-in User interface elements 89 HAPTER Containers placement controls Buttons. selection, edit and text controls...
  • Page 90: View Properties

    5: Creating a User Interface for Your Plug-in HAPTER Other controls View properties Properties in container and control nodes affect the layout of the controls, and their appearance. Layout properties, and certain view properties, are available to all nodes, both containers and controls. Other view properties are available only in control nodes.
  • Page 91 5: Creating a User Interface for Your Plug-in HAPTER General view properties Of the properties that are available in both containers and controls, many are connected with layout behavior; these are discussed separately in properties are available in all containers and controls except the layout containers, View property bind_to_object —or—...
  • Page 92 5: Creating a User Interface for Your Plug-in HAPTER Control node view properties These properties are available in control nodes of all types, but not in containers. Control node property enabled font size Edit-field view properties These properties are available in control nodes that contain editable text; these include , and combo_box password_field...
  • Page 93 5: Creating a User Interface for Your Plug-in HAPTER Property alignment text_color immediate auto_completion completion increment large_increment validate value_to_string string_to_value wraps Datatype Description string Alignment of text in frame, center The color of displayed text. Default is black. LrColor Boolean If true, the field commits its value as the user is typing, and the validate function is called for every change.
  • Page 94: Binding Ui Values To Data Values

    5: Creating a User Interface for Your Plug-in HAPTER Text view properties These properties apply to any control that displays text, including , as well as the editable text controls. push_button Property width_in_chars width_in_digits height_in_lines Binding UI values to data values Bindings allow you to make your UI dynamic by specifying a relationship between an and current values in an observable table (see be the export-settings property table provided by the API, or a table that you create for local program data...
  • Page 95: Specifying Bindings

    5: Creating a User Interface for Your Plug-in HAPTER 2. For each specific UI element, set the value of each dynamic property using the function to associate that value with a specific key in the bound table. The simplest binding simply mirrors the key value and the property value; for instance, setting one value to true sets the other value to true.
  • Page 96 5: Creating a User Interface for Your Plug-in HAPTER You can then use the shortcut to specify dynamic property values: viewFactory:static_text { The required argument of bound to the UI element; that is, the value of the view hierarchy, but can be overridden at any level. You can override the bound table for a specific binding by passing the containing both the key and the table it comes from: visible = LrView.bind { key = "mySetting", bind_to_object = "myTable"...
  • Page 97: Creating Observable Property Tables

    LrFunctionContext.callWithContext("showCustomDialog", function( context ) local properties = LrBinding.makePropertyTable( context ) properties.url = "http://www.adobe.com" -- create a settings value -- add code to take create dialog contents end) When you create a new table, it is initially empty. You can explicitly add keys and values, as in the example.
  • Page 98: Bindings For Selection Controls

    5: Creating a User Interface for Your Plug-in HAPTER For example: LrFunctionContext.callWithContext("showCustomDialog", function( context ) local myPropTable = LrBinding.makePropertyTable( context ) mypropTable:addObserver( 'mySetting', function( properties, key, newValue ) -- do something when this value changes end ) -- add code to create dialog contents end) The handler function you specify for your observer takes as arguments the observed table (so you can access other data values), the key whose value change triggered the notification (in case you are using the...
  • Page 99 5: Creating a User Interface for Your Plug-in HAPTER f:checkbox { title = "Value will be string", value = bind 'checkbox_state', -- bind to the key value checked_value = 'checked', -- this is the initial state unchecked_value = 'unchecked', -- when the user unchecks the box, f:static_text { fill_horizontal = 1, title = bind 'checkbox_state', -- bound to same key as checkbox value...
  • Page 100 5: Creating a User Interface for Your Plug-in HAPTER Binding pop-up menu selections The pop-up menu and the menu component of a combo box allow you to specify a set of choices, using an table; each item entry is a table containing a items that appears in the menu (see items = { { title = "First item",...
  • Page 101 5: Creating a User Interface for Your Plug-in HAPTER local LrFunctionContext = import "LrFunctionContext" local LrStringUtils = import "LrStringUtils" local LrView = import "LrView" LrFunctionContext.callWithContext( 'bindingExample', function( context ) local f = LrView.osFactory() local properties = LrBinding.makePropertyTable( context ) properties.format = "jpeg" local contents = f:column { spacing = f:control_spacing(), bind_to_object = properties,...
  • Page 102 5: Creating a User Interface for Your Plug-in HAPTER local LrView = import "LrView" -- Create an observable table within a function context. LrFunctionContext.callWithContext( 'bindingExample', function( context ) -- Obtain the view factory. local f = LrView.osFactory() -- Create the observable table. local properties = LrBinding.makePropertyTable( context ) -- Add an observer of the storeValue property.
  • Page 103: Complex Bindings

    5: Creating a User Interface for Your Plug-in HAPTER Complex bindings functions provide a particular, limited set of value transformations. To specify more LrBinding complex bindings, the argument to bind_to_object —or— object transform Here is an example of binding to keys in two different tables in a single view object: visible = LrView.bind("myBooleanSetting"), -- simple binding between two enabled = LrView.bind( { key = "mySetting", -- a single key...
  • Page 104 5: Creating a User Interface for Your Plug-in HAPTER max = 110, value = LrView.bind "slider_value", title = "slider title", viewFactory:static_text { title = "You’re over a hundred", visible = LrView.bind { key = "slider_value", transform = function(value, fromTable) Transformations can work in both directions; changes in the bound property affect the bound table key, and changes in the table key affect the property.
  • Page 105 5: Creating a User Interface for Your Plug-in HAPTER transform = function( value, fromTable ) end, local result = LrDialogs.presentModalDialog( -- invoke the dialog title = "Binding Example", contents = contents, end ) Binding multiple keys To specify even more complex bindings, between a property in a view object and multiple keys in one or more bound tables, the value part of a keys bind_to_object...
  • Page 106 5: Creating a User Interface for Your Plug-in HAPTER operation transform This example shows multiple binding. The dialog contains two edit fields, each with its different key. A static text box below them has its makes it true only when both values are equal (meaning that the same text has been typed into both edit fields, or they are both empty).
  • Page 107: Determining Layout

    5: Creating a User Interface for Your Plug-in HAPTER spacing = f:label_spacing(), f:static_text { title = "Type more:", alignment = 'right', width = LrView.share( 'label_width' ), f:edit_field { fill_horizonal = 1, width_in_chars = 20, immediate = true, value = LrView.bind( 'text2' ), -- bind to the second key f:static_text { place_horizontal = 0.5, title = "This is only visible when the text in the two fields are equal",...
  • Page 108: Relative Placement Of Sibling Nodes

    5: Creating a User Interface for Your Plug-in HAPTER Relative placement of sibling nodes These properties determine how child nodes are placed relative to one another. They apply only to containers. A margin is the interior margin of a container, the distance between the edge of the container and its children;...
  • Page 109: Factory Functions For Obtaining Layout Values

    5: Creating a User Interface for Your Plug-in HAPTER Layout property fill place_horizontal place_vertical width height Factory functions for obtaining layout values factory object defines a set of functions that you can use to obtain appropriate values for the LrView layout properties of individual containers and controls.
  • Page 110: Layout Examples

    LrFunctionContext.callWithContext( 'dialogExample', function( context ) local f = LrView.osFactory() --obtain a view factory local properties = LrBinding.makePropertyTable( context ) -- make a table properties.url = "http://www.adobe.com" -- initialize setting local contents = f:row { spacing = f:label_spacing(), bind_to_object = properties, -- default bound table is the one we made f:static_text { title = "URL",...
  • Page 111 5: Creating a User Interface for Your Plug-in HAPTER actionVerb = "Go", if result == 'ok' then -- action button was clicked LrHttp.openUrlInBrowser( properties.url ) end ) Making labels line up Typically, a dialog contains vertical sets of controls and their labels. The following code demonstrates how make right-aligned labels on the left side of the dialog, with matching left-aligned controls on the right side.
  • Page 112 5: Creating a User Interface for Your Plug-in HAPTER spacing = f:label_spacing(), f:static_text { title = "Occupation:", alignment = "right", width = LrView.share "label_width", -- the shared binding f:edit_field { width_in_chars = 20, local result = LrDialogs.presentModalDialog( -- invoke the dialog title = "Dialog Example", contents = contents, end )
  • Page 113 5: Creating a User Interface for Your Plug-in HAPTER This example creates the overlapping views shown in the figure, where the controls shown below the format pop-up depend on the selection in the pop-up menu. local LrBinding = import "LrBinding" local LrDialogs = import "LrDialogs"...
  • Page 114 5: Creating a User Interface for Your Plug-in HAPTER local result = LrDialogs.presentModalDialog( -- invoke the dialog title = "Dialog Example", contents = contents, end ) title = "Compression:", f:popup_menu { items = { { title = "None", value = 'none' }, { title = "LZW", value = 'lzw' }, { title = "ZIP", value = 'zip' }, value = LrView.bind 'tiff_compression',-- sets a TIFF value...
  • Page 115: Writing A Web-Engine Plug-In

    Collect these files into a single folder, which you must place in the following directory according to your operating system: userhome/Library/Application Support/Adobe/Lightroom/Web Galleries/ INDOWS LightroomRoot\shared\webengines The name of the plug-in folder must end with...
  • Page 116: Defining The Data Model

    6: Writing a Web-engine Plug-in HAPTER LuaPage templates Resources style sheets JavaScript images Localization dictionaries Iconic preview source files (not needed for delivery) Defining the data model The folder that defines your gallery type must define the data model in an information file named galleryInfo.lrweb format: return {...
  • Page 117: Galleryinfo Top-Level Entries

    6: Writing a Web-engine Plug-in HAPTER GalleryInfo top-level entries The following top-level properties are defined in the title galleryType maximumGallerySize model views iconicPreview aboutBoxFile supportsLiveUpdate This example shows the top-level entries from the return { LrSdkVersion = 3.0, LrSdkMinimumVersion = 2.0, -- minimum SDK version required by this plugin galleryInfo.lrweb A localizable title string for the gallery type, which appears in the Web module’s Engine list.
  • Page 118: Data Model Entries

    6: Writing a Web-engine Plug-in HAPTER title = LOC "$$$/AgWPG/Templates/HTML/Title=Lightroom HTML Gallery", id = "com.adobe.wpg.templates.jardinePro", galleryType = "lua", maximumGallerySize = 50000, aboutBoxFile = "about.html", supportsLiveUpdate = true, model = {...} Here is the About box for the built-in HTML Web Gallery:...
  • Page 119 6: Writing a Web-engine Plug-in HAPTER Within the predefined defined by the plug-in. Within each size class, however, there are a set of predefined properties such as width height Model properties can have simple number, string or color values, but to make a property dynamic, you can make the value a function definition.
  • Page 120: Defining A Ui For Your Model

    6: Writing a Web-engine Plug-in HAPTER lightroomApplication.property identityPlateExport jpegQuality useWatermark outputSharpeningOn outputSharpening perImageSetting.property setting_names plug-in-defined properties Defining a UI for your model entry in the table returned by the views web engine. It is a function that is passed two arguments, a contains your model data) and a elements (as described in These properties control how Lightroom behaves when creating...
  • Page 121 6: Writing a Web-engine Plug-in HAPTER The function returns a table of view descriptions by name, with entries that correspond to the control panels at the right of the Web module. labels colorPalette appearanceConfiguration outputSettings Within each entry, you can use the view factory object to create UI controls. Set the bound table to be the table, and bind control values to data values you have defined in your model.
  • Page 122 6: Writing a Web-engine Plug-in HAPTER Here is an example of the format of the return { views = function( controller, f ) local LrView = import "LrView" local bind = LrView.bind local multibind = viewFactory.multibind return { labels = f:panel_content { -- returned item identifies panel bind_to_object = controller, -- bound table is passed controller f:subdivided_sections { ...additional content...
  • Page 123 6: Writing a Web-engine Plug-in HAPTER content_column slider_content_column checkbox_and_color_row color_content_column content_section header_section popup_row slider_row checkbox_and_color_row label_and_color_row checkbox_row labeled_text_input metadataModeControl warning_icon identity_plate row_column_picker Customizing per-image text The Image Info panel allows the user to specify text for use in gallery pages. Each text label is named with a label, such as Caption or Title, and can be enabled with a checkbox.
  • Page 124: Creating A Dynamic Data Model

    6: Writing a Web-engine Plug-in HAPTER This definition creates these controls in the Image Info panel: The localized title supplied by Lightroom. The value of the preset choice. To incorporate the user’s choice of text in the image-detail template page, use code like this: <html>...
  • Page 125: Creating A Preview

    6: Writing a Web-engine Plug-in HAPTER A typical use of dynamic data is to tie two properties together, so that changing one changes the other. For example, you might want to control the aspect ratio by making photoSizes.mySize.height properties. For example: ["photoSizes.large.height"] = function() return photoSizes.large.width end, ["photoSizes.large.width"] = 450, This function simply accesses and returns the value of another property.
  • Page 126 6: Writing a Web-engine Plug-in HAPTER Creating the Flash movie Your web-engine folder must include a simple Flash movie that renders the "iconic" representation of each web page. The ActionScript file that defines your movie can access the global variables provided by the entry in flashvar Your Flash movie should do these things:...
  • Page 127: Web Sdk Manifest Api

    6: Writing a Web-engine Plug-in HAPTER Web SDK manifest API The manifest is a Lua file in your plug-in’s root directory named files and template files to web-engine HTML output files using a set of commands for different kinds of pages and resource files.
  • Page 128 6: Writing a Web-engine Plug-in HAPTER Inputs source destination Example AddResource { source = "image.png", destination = "content/resources/image.png", AddResources Copies a set of resource files from the gallery template directly into the published gallery. A resource is not interpreted, but is simply copied directly. Inputs source destination...
  • Page 129 6: Writing a Web-engine Plug-in HAPTER LuaPages environment variables When executing the LuaPages for filename root gridPageLink pageType index Example AddPhotoPages { template = 'detail.html', variant = '_large', destination = "content", AddGridPages Uses a LuaPage template to build a page for each grid of photos in the current Lightroom selection. Inputs filetype destination...
  • Page 130 6: Writing a Web-engine Plug-in HAPTER In addition, if you use environment variables: numGridPages filenameOfGridPage( pageNumber ) gridPageForPhotoAtIndex( photoIndex ) rows columns Example AddGridPages { destination='content', template='grid.html', rows=model.nonDynamic.numRows, columns=model.nonDynamic.numCols, AddCustomCSS Generates a CSS file using the When you declare your data model in the entries that begin with "...
  • Page 131 6: Writing a Web-engine Plug-in HAPTER model = { ["appearance.body.background-color"] = "#ff0000", ["appearance.body.cssID"] = "body", 3. To make this something the user can edit, add a corresponding control to one of the panel descriptions in the return { views = { myViewFactory.label_and_color_row { bindingValue = "appearance.body.background-color", title = "Background",...
  • Page 132 (string) A short prefix used to identify tags belonging to this tagset. For example, "lr". (string) A path to the tagset definition file. The special path "com.adobe.lightroom.default" loads the default tagset. myTags.lrweb file, import the tagset definition file by name:...
  • Page 133: Luapage Syntax

    6: Writing a Web-engine Plug-in HAPTER LuaPage syntax A LuaPage is a Lua-language source file that is evaluated to produce one destination web page in your published gallery. In the manifest, use the destination file location. Environment variables available to LuaPages A LuaPage is evaluated in a context that provides many of the Lua functions of a default Lua installation, and also some special functions that are specific to the web photo gallery templating language.
  • Page 134: Luapage Data Types

    6: Writing a Web-engine Plug-in HAPTER Variable includeFile() LuaPage data types These data types are defined: imageProxy exportFilename rating imageID renditions metadata colorLabel imageRendition width height relPath Description An execution-time function that allows a page to include another file using runtime logic to specify which file.
  • Page 135: Web Sdk Tagsets

    6: Writing a Web-engine Plug-in HAPTER cropMode metadataExportMode Web SDK tagsets A tagset is an external file containing macro-like definitions that can be loaded by your web pages. These are similar to JSP Tag Libraries, but simpler. They allow you to extract common content and logic that appears on multiple pages into a custom set of tags.
  • Page 136: Using Custom Tags

    You can use any namespace for your own tags. 3. To load the built-in default tagset, substitute the special value "com.adobe.lightroom.default" for the path: importTags( "lr", "com.adobe.lightroom.default" ) By convention, the built-in tags are imported into the 4.
  • Page 137: Lightroom Built-In Tagset

    SDK manifest. As for all imported tags, you must reference tag is a container for the other tags, which define cells within the grid. For example: Web SDK tagsets 137 ) to import this into the manifest.lrweb "com.adobe.lightroom.default" tagset.
  • Page 138 6: Writing a Web-engine Plug-in HAPTER This defines a simple grid with only one cell, which displays a photo from the referenced file. It uses a variable, , which is evaluated at run time as a reference to the currently selected photo. image The following local variables are available in the context of the Variables available for grids...
  • Page 139: Web Html Live Update

    6: Writing a Web-engine Plug-in HAPTER </lr:OtherPages> <lr:PreviousEnabled> </lr:PreviousEnabled> <lr:PreviousDisabled> </lr:PreviousDisabled> <lr:NextEnabled> </lr:NextEnabled> <lr:NextDisabled> </lr:NextDisabled> </lr:Pagination> </ul> </div> <% end %> The following local variables are available in the context of the Variables available for pagination page link The following pagination tags are defined: Pagination tags Pagination CurrentPage...
  • Page 140: Defining Messages From Lightroom To A Previewed Page

    6: Writing a Web-engine Plug-in HAPTER While a page from your gallery is being previewed in Lightroom, a user might change a model variable using the control panel. In order to reflect the change in the previewed page, the Lightroom browser normally needs to reload the page.
  • Page 141 6: Writing a Web-engine Plug-in HAPTER which may need to be cleared. Your live-update function signals Lightroom about what behavior to use by returning one of these strings: invalidateOldHTML cache are cleared. The exported JPEGs remain unchanged. The reload is deferred until the user navigates away from the currently previewed page.
  • Page 142: Defining Messages From A Previewed Page To Lightroom

    6: Writing a Web-engine Plug-in HAPTER This function must locate the image using appropriate DOM methods. The function has this prototype: document.liveUpdateImageSize = function( imageID, width, height ) { // your code here return "invalidateAllContent"; imageID width height If unable to perform the live update, return as it can while the mouse is dragged.
  • Page 143 6: Writing a Web-engine Plug-in HAPTER To call from JavaScript into Lightroom, invoke the using this syntax: callCallback( "callback_name", param1, param2, ... ); For example, to call the in-place-edit callback defined in the sample implementation, the JavaScript makes this call: callCallback( 'inPlaceEdit', target, bounds.x, bounds.y, bounds.width, bounds.height, font.fontFamily, font.fontSize, imageID ) Lightroom provides these callback functions that can be invoked from JavaScript using...
  • Page 144 6: Writing a Web-engine Plug-in HAPTER You can add in-place editing functionality to any node containing text by adding code like this to your HTML: onclick="clickTarget( this, 'target_property' );" For example: <p onclick="clickTarget( this, 'metadata.groupDescription.value' );" id="metadata.groupDescription.value" class="textColor"> $model.metadata.groupDescription.value </p> Notice that the target ID sent to all match.
  • Page 145: Using Zstrings For Localization

    Using ZStrings for Localization ZStrings are an Adobe convention for defining localization strings. You identify a string according to its usage in the user interface, and specify it in the language-specific versions of the string to display to the user.
  • Page 146: Zstring Characters And Escape Sequences

    7: Using ZStrings for Localization HAPTER Like any Lua string, ZStrings can be enclosed in single or double quotes. For example: LOC "$$$/MyPlugin/Dialogs/Description/sectionName=Description" LOC '$$$/MyPlugin/Dialogs/Description/Title=Document Title:' ZString characters and escape sequences ZStrings in code should consist entirely of low-ASCII characters. The key should only contain characters in the set "a-ZA-Z0-9/".
  • Page 147: The Loc Function

    7: Using ZStrings for Localization HAPTER Sequence ^0 - ^9 ^U+xxxx The LOC function The global function takes a ZString argument, and automatically performs the table lookup to resolve the display string for the current locale. If it cannot find a matching string in a dictionary for the current locale, or if there is no dictionary for the current locale, it returns the default string provided with the ZString.
  • Page 148: Localization Dictionary Files

    7: Using ZStrings for Localization HAPTER Localization dictionary files To localize your plug-in’s user interface, you must provide a localization dictionary file for each language, named and located as follows: Each translation dictionary must be in a file named two-letter ISO code for the language, such as Japanese, and so on.
  • Page 149: Example Dictionary File

    7: Using ZStrings for Localization HAPTER Example dictionary file Here is a small example of a German translation dictionary: "$$$/MyPlugin/Size/Small=Klein" "$$$/MyPlugin/Size/Medium=Mittel" "$$$/MyPlugin/Size/Large=Groß" "$$$/MyPlugin/Size/Large/Extra=Sehr groß" "$$$/MyPlugin/Image/Title=Titel" "$$$/MyPlugin/Image/Quality=Qualität" "$$$/MyPlugin/Image/View=Ansicht" "$$$/MyPlugin/Enabled=Aktiviert" Supported languages These languages are supported: Language German English Spanish French Italian Japanese Korean Dutch...
  • Page 150: Sdk Sample Plug-Ins

    SDK Sample Plug-ins The Lightroom SDK includes some complete sample plug-ins that you can examine and use to familiarize yourself with the plug-in architecture, and with API and Lua usage in the Lightroom SDK. The plug-in samples are packaged with the Lightroom SDK, in the folder “The Lightroom SDK”...
  • Page 151: The Ftp Upload Sample Plug-In

    8: SDK Sample Plug-ins HAPTER The FTP Upload sample plug-in The FTP sample plug-in demonstrates how to customize the Export dialog with an Export Service Provider that exports images to a remote export destination. The plug-in allows you to upload images directly to an FTP Server.
  • Page 152: Configure The Connection

    8: SDK Sample Plug-ins The FTP Upload sample plug-in 152 HAPTER Configure the connection 1. In the FTP Server section of the Export dialog, bring up the Destination pop-up menu and choose Edit. This displays the configuration dialog for the FTP server settings.
  • Page 153 Server: Enter the name of the FTP server you wish to connect to, for example: . You do not need to enter the protocol. myftpserver.adobe.com Username: Enter the username you use to log into your FTP Server. Password: Enter the password you use to log into your FTP Server. If you wish, check the ‘Store password in preset’...
  • Page 154: Establish The Connection

    8: SDK Sample Plug-ins HAPTER 3. To store this configuration in a preset, bring up the Preset popup and select Save Current Settings as new Preset. In the resulting dialog, enter a name for your preset and click Create. Lightroom connects to your FTP server and displays a Browse dialog.
  • Page 155: The Flickr Plug-In

    8: SDK Sample Plug-ins HAPTER The Flickr plug-in This is more than a sample; it is most of the source code to the plug-in that Lightroom uses to implement its built-in Flickr support. The source code demonstrates how to customize the Publish experience with a Publish Service Provider that uploads photos to the Flickr web service.
  • Page 156 8: SDK Sample Plug-ins HAPTER 3. If it is not already selected, select the Flickr publish services at the left. The plug-in’s Publish Service Provider defines text for the top section that shows when the service is selected, and adds new sections to the dialog. Notice that is also adds a status message at the bottom, next to the Plug-in Manager button.
  • Page 157 8: SDK Sample Plug-ins HAPTER When you have finished logging into Flickr and agreed to allow Lightroom access, it shows a web page stating that the application is authorized. 6. Return to Lightroom and click Done. This returns you to the Publishing Manager dialog. Once you have logged in, notice that the Log In button in the Flickr Account section has changed to Switch User.
  • Page 158 8: SDK Sample Plug-ins HAPTER 2. Click on the Photostream collection to display those photos in a section called “New Photos to Publish.” 3. Notice that these photos are not published until you explicitly ask Lightroom to publish them. To do this, click Publish at the bottom left corner of the screen. 4.
  • Page 159 8: SDK Sample Plug-ins HAPTER Publish modified photos A publish service differs from an export service in that it maintains an ongoing relationship between Lightroom and the service (in this case, Flickr). If you make changes to photos that have already been published or delete them, Lightroom attempts to mirror those changes on the service.
  • Page 160 8: SDK Sample Plug-ins HAPTER Get feedback from viewers Lightroom's Publish feature allows you to retrieve selected feedback from a web service and display it in Lightroom's Comments panel. To see this: 1. Select one of your photos that has been published. 2.
  • Page 161: Metadata And Filtering Samples

    8: SDK Sample Plug-ins HAPTER Metadata and filtering samples These related samples include the following: custommetadatasample.lrdevplugin Files: Info.lua CustomMetadataDefinition.lua CustomMetadataTagset.lua AllMetadataTagset.lua DisplayMetadata.lua PluginInfoProvider.lua PluginInit.lua strings/en/TranslatedString.txt metaexportfilter.lrdevplugin Files: Info.lua Metadata.lua MetadataExportFilterProvider Custom metadata sample walkthrough 1. Use the Plug-in Manager to add the plug-in, found in the Lightroom SDK samples folder: LR_SDK/Sample Plugins/custommetadatasample.lrdevplugin 2.
  • Page 162: Metadata Filter Sample

    8: SDK Sample Plug-ins HAPTER 4. Select a photo. 5. Change the Display Image value to Yes, and the Random String value to Test. These values are used by the following sample. 6. Select several photos in the Library module, including the one that you modified in the step 7.
  • Page 163 8: SDK Sample Plug-ins Metadata and filtering samples 163 HAPTER 3. Open the Export dialog by choosing File > Export. 4. Notice the entry for this plug-in, Metadata Post Process, in the Post-Process Actions panel. 5. Open the entry by clicking the gray arrow at the left, select the action, click Insert. 6.
  • Page 164: Post-Processing Samples

    8: SDK Sample Plug-ins HAPTER 7. In the new Metadata Export Filter dialog section, choose Title from the drop-down menu, and enter the title of one of your selected photos in the edit text field. 8. Click Export to start the export operation. Only the single picture whose Title value matches the one you entered is exported;...
  • Page 165 8: SDK Sample Plug-ins HAPTER 2. Select some photos in the Library module. 3. Open the Export dialog by choosing File > Export. Notice the entry for these plug-ins, Creator External Tool and Language External Tool, in the Post-Process Actions panel. Each plug-in defines one action. 4.
  • Page 166: Web Engine Sample

    8: SDK Sample Plug-ins HAPTER 5. Select and insert the action under Language External Tool; the section for that action is added, allowing the user to select a language and new value for that language’s translation value of the XMP Title property.
  • Page 167 8: SDK Sample Plug-ins Web engine sample 167 HAPTER 3. Select the web engine defined by this plug-in that appears in the Engine list: 4. The gallery preview appears, showing a filmstrip of small images on one side and a larger version of the selected image on the right.
  • Page 168: Getting Started: A Tutorial Example

    Add the following code to the return { LrSdkVersion = 3.0, LrToolkitIdentifier = 'com.adobe.lightroom.sdk.helloworld', 3. Add another entry to the returned table to create a menu item in the Lightroom File menu. Place the following code after the LrExportMenuItems = { title = "Hello World Dialog", -- The display text for the menu item...
  • Page 169: Create The Service Scripts

    9: Getting Started: A Tutorial Example HAPTER Place the following code after the LrLibraryMenuItems = { title = "Hello World Custom Dialog", -- The display text for the menu item file = "LibraryMenuItem.lua", -- The script that runs when the item is selected 5.
  • Page 170: Displaying A Custom Dialog

    9: Getting Started: A Tutorial Example HAPTER Place this line of code in the body of the function: -- body of function LrDialogs.message( "ExportMenuItem Selected", "Hello World!", "info" ) 4. To call the function when the script runs, place this line at the end of the script: MyHWExportItem.showModalDialog() 5.
  • Page 171: Create Ui Elements

    9: Getting Started: A Tutorial Example HAPTER 5. Add a key to the observable table called -- body of called function local props = LrBinding.makePropertyTable( context ) -- create bound table props.isChecked = false -- add a property key and initial value -- create view hierarchy Create UI elements The Lightroom SDK also provides the...
  • Page 172: Run The Plug-In

    9: Getting Started: A Tutorial Example HAPTER 10. Use LrDialogs.presentModalDialog() entries for the dialog local result = LrDialogs.presentModalDialog( title = "Custom Dialog", contents = c, -- the view hierarchy we defined 11. To call the function when the script runs, add this at the bottom of the script: MyHWLibraryItem.showCustomDialog() 12.
  • Page 173: Transforming Data

    9: Getting Started: A Tutorial Example HAPTER Transforming data The very simple binding we created for the checkbox allows you to set and clear a data value by selected or deselecting the checkbox button. To show a more complex relationship between the UI and the data, we will add two radio buttons and a static text field.
  • Page 174 9: Getting Started: A Tutorial Example HAPTER f:row { -- second row shows a static text box 5. For both buttons, add the following to bind the current value of both to the same key: Now this key will reflect the user’s choice of buttons; selecting a button will set the key value to "one" or "two".
  • Page 175: Run The Plug-In

    9: Getting Started: A Tutorial Example HAPTER Run the plug-in Use these steps to run the plug-in and test the dialog: 1. Reload the plug-in, as described in step 2. Choose Library > Plug-in Extras > Hello World Custom Dialog to show the custom modal dialog created by the 3.
  • Page 176 9: Getting Started: A Tutorial Example HAPTER 2. In the body of this function, add code to create the function-context call you need for the property table: -- body of show-dialog function LrFunctionContext.callWithContext( "showCustomDialogWithMultipleBind", -- body of called function end ) 3.
  • Page 177 9: Getting Started: A Tutorial Example HAPTER f:group_box { fill_horizontal = 1, title = "Both Values", font = "<system>", f:edit_field{ place_horizontal = 0.5, value = LrView.bind { width_in_digits = 7 6. For the value default bound table for that control: f:slider { 7.
  • Page 178: Run The Plug-In

    9: Getting Started: A Tutorial Example HAPTER f:edit_field { 9. You must also supply the function that operates on the multiple key values to supply a single result for the binding. In this case, we will simply add the two numeric values, and return the result: Notice how you use the key.
  • Page 179 9: Getting Started: A Tutorial Example Binding to multiple keys 179 HAPTER 3. Move the sliders and notice how the text below them changes, reflecting the current value for each numeric property, and how the sum of the two values is displayed in the "Both Values" box. 4.
  • Page 180: Adding A Data Observer

    9: Getting Started: A Tutorial Example HAPTER Adding a data observer The most flexible way of connecting to your data is to create an observer for the property table; this is an independent object that is notified of changes in the table, and can take any action in response to the change, including setting UI values in any way you want.
  • Page 181: Create An Observer For A Data Property

    9: Getting Started: A Tutorial Example HAPTER Create an observer for a data property To make the text dynamic, we are going to add an observer for the observer is notified whenever the observed property changes; we will tell it to update the text in showValue_st 6.
  • Page 182: Run The Plug-In

    9: Getting Started: A Tutorial Example HAPTER button action resets the observed property value to the value entered by the user in the edit box. It also resets the color of the static text to black, so that we will be able to tell whether the observer function fired.
  • Page 183: Debugging Your Plug-In

    9: Getting Started: A Tutorial Example HAPTER 7. Click Update again, without changing the text in the “New value” field. Notice how the text turns black. This is because the observer is only notified when the bound value changes. 8. Dismiss the dialog with OK or Cancel. Debugging your plug-in The Lightroom SDK does not supply a development environment for you to debug your plug-ins.
  • Page 184: Viewing Trace Information Using Log Files

    9: Getting Started: A Tutorial Example HAPTER 6. Save your changes, and reload your plug-in if necessary. Viewing trace information using log files These steps describe how to view debugging trace information using a text editor: 1. Start Lightroom. 2. Make sure your plug-in is configured to write debugging information to a log file, as described above: local LrLogger = import 'LrLogger' local myLogger = LrLogger( 'libraryLogger' ) -- the log file name myLogger:enable( "logfile"...
  • Page 185 9: Getting Started: A Tutorial Example Debugging your plug-in 185 HAPTER 4. In the Attach to Process dialog, scroll through the processes and look for lightroom.exe 5. Select and click OK. lightroom.exe A console window appears in WinDbg, and the Lightroom application is blocked. 6.
  • Page 186 9: Getting Started: A Tutorial Example HAPTER 7. In Lightroom, run the Hello World plug-in (see 8. In WinDbg, view the console to see the trace information being written as you use the plug-in. Debugging in Mac OS Console 1. Start Lightroom 2.
  • Page 187: Defining Metadata: A Walkthrough

    Defining Metadata: A Walkthrough This chapter shows how a plug-in can define metadata fields that Lightroom can display along with standard metadata for photos, and which you can use as a private data model for plug-in processing. It also illustrates how the private data can be used to customize the Plug-in Manager. These concepts and techniques are introduced and explained in more detail in and Publish Services.
  • Page 188 10: Defining Metadata: A Walkthrough HAPTER 5. The metadataFieldsForPhotos Add this first entry to the table: metadataFieldsForPhotos = { id = 'siteId', This is the simplest type of field. It does not have any of the properties that make it visible in the Metadata panel, or modifiable by users.
  • Page 189: Define A Tagset

    10: Defining Metadata: A Walkthrough HAPTER Setting searchable 9. Add another entry to the table to define a Boolean field. To do this, we will use the enumerated-value data type. id = 'myboolean', title = LOC "$$$/MyMetadataSample/Fields/Display=My Boolean", dataType = 'enum', values = { 10.
  • Page 190: Using The Plug-In

    'com.adobe.filename', 'com.adobe.folder', 'com.adobe.separator', { 'com.adobe.label', label = LOC "$$$/Metadata/CusLabel=My Metadata" }, 'sample.metadata.mymetadatasample.*', The asterisk wild-card character in the field-name part of the path matches all fields defined by this plug-in. The asterisk can appear only at the end of the field name.
  • Page 191 10: Defining Metadata: A Walkthrough HAPTER 6. Select the My Metadata tagset. The Metadata panel should display the Metadata, and your custom with separators between the sections. The fields are shown with their display labels, and an edit or selection control. 7.
  • Page 192: Customizing The Plug-In Manager

    10: Defining Metadata: A Walkthrough HAPTER Customizing the Plug-in Manager You plug-in can define a customized section for the Plug-in Manager dialog, which is displayed on the right when the user selects your plug-in in the list on the left. This section can make use of private data values that you make globally available within the plug-in by defining them in an initialization script.
  • Page 193 UI content of the new section. title = "Custom Metadata Sample", f:row { spacing = f:control_spacing(), f:static_text { title = 'Click the button to find out more about Adobe', alignment = 'left', fill_horizontal = 1, f:push_button { width = 150,...
  • Page 194 10: Defining Metadata: A Walkthrough HAPTER 8. Reload and run the plug-in again, as described in When you select the plug-in, the new section appears above the standard Lightroom sections: title = _G.currentDisplayImage, fill_horizontal = 1, Customizing the Plug-in Manager 194 “Using the plug-in”...
  • Page 195: Web Gallery Plug-Ins: A Tutorial Example

    Add this initial Lua code to the file: return { LrSdkVersion = 3.0, LrSdkMinimumVersion = 2.0, -- minimum SDK version required by this plug-in title = "My Sample Plug-in", id = "com.adobe.wpg.templates.mysample", galleryType = "lua", maximumGallerySize = 50000, 2. In the myWebPlugin manifest.lrweb...
  • Page 196: Add Html Template Files

    The content of <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="generator" content="Adobe Photoshop Lightroom" /> <title>My Sample Plug-in</title> <link rel="stylesheet" type="text/css" media="screen" title="Custom Settings" href="$others/custom.css" > </head> <body> The content of </body>...
  • Page 197: Defining A Data Model And Functionality

    { LrSdkVersion = 3.0, LrSdkMinimumVersion = 2.0, -- minimum SDK version required by this plug-in title = "My Sample Plug-in", id = "com.adobe.wpg.templates.mysample", galleryType = "lua", maximumGallerySize = 50000, model = { ["nonDynamic.imageBase"] = "content", ["photoSizes.thumb.height"] = 150, ["photoSizes.thumb.width"] = 150,...
  • Page 198: Add A Grid Using Built-In Tags

    Lightroom built-in tagset. First, we need to import this tagset into the “ ” namespace. 4. In the manifest.lrweb importTags( "lr", "com.adobe.lightroom.default" ) AddCustomCSS { filename = 'content/custom.css', 5. Now we can define the contents of image grid and its contents. Add this code to <lr:ThumbnailGrid>...
  • Page 199: Add Another Photo Size

    11: Web Gallery Plug-ins: A Tutorial Example HAPTER </lr:NextEnabled> <lr:NextDisabled> </lr:NextDisabled> </lr:Pagination> </ul> </div> <% end %> The pages make use of the predefined navigation buttons (using the with the text “Previous” and “Next”. This code makes sure that the “Previous” button is disabled on the first page, and the “Next”...
  • Page 200 11: Web Gallery Plug-ins: A Tutorial Example HAPTER Add link functionality 3. In the grid.html page corresponding to the thumbnail in that cell: <lr:GridPhotoCell> <a href="$others/<%= image.exportFilename %>_large.html"> <img src="$others/bin/images/thumb/<%= image.exportFilename %>.jpg" id="<%= image.imageID %>" class="thumb" /> </a> </lr:GridPhotoCell> Notice that the reference to the filename includes the appended text, Define the large-image frame template 4.
  • Page 201: Customizing The Web Gallery Ui

    11: Web Gallery Plug-ins: A Tutorial Example HAPTER </lr:NextDisabled> </lr:Pagination> </ul> </div> 6. After the pagination code, add the link that actually retrieves the large image to be shown: <a href="$gridPageLink"> <img src="bin/images/large/<%= image.exportFilename %>.jpg" /> </a> Customizing the Web Gallery UI The next step is to customize the control panel of the Web Gallery page so that users can adjust values in the model data that we have defined, and allow changes that the user makes to be shown immediately in the Web Gallery browser using Live Update.
  • Page 202: Add The Title To The Html Template

    11: Web Gallery Plug-ins: A Tutorial Example HAPTER Add the title to the HTML template The title will be shown on all pages, so it should be part of the boilerplate HTML used at the front of all pages, as defined by the 3.
  • Page 203 11: Web Gallery Plug-ins: A Tutorial Example HAPTER Define the tags 1. Create a file in the plug-in folder named sayings: local sayings = { "A dish fit for the gods - Julius Caesar, Shakespeare", "Oh, that way madness lies - King Lear, Shakespeare", "A multitude of sins - James 5:20", "A knight in shining armour - The Ancient Ballad of Prince Baldwin", "Blood is thicker than water - Guy Mannering;...
  • Page 204 11: Web Gallery Plug-ins: A Tutorial Example HAPTER This associates the prefix <xmpl:aQuote> <xmpl:saying>...</xmpl:saying> </xmpl:aQuote> 6. Finally, we need to use the tags in one of the template pages. Edit the file just before the footer: <xmpl:aQuote>You know what they say:<br> <xmpl:saying>...

This manual is also suitable for:

Photoshop lightroom sdk 3.0

Table of Contents