Lightroom SDK Guide

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 207 [warning: Documents this large are best viewed by clicking the View PDF Link!]

LIGHTROOM SDK 6
PROGRAMMERS GUIDE
Copyright © 201 Adobe Systems Incorporated. All rights reserved.
Adobe Photoshop Lightroom SDK Programmers Guide
If this guide is distributed with software that includes an end user agreement, this guide, as well as the software
described in it, is furnished under license and may be used or copied only in accordance with the terms of such license.
Except as permitted by any such license, no part of this guide may be reproduced, stored in a retrieval system, or
transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written
permission of 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.
The content of this guide is furnished for informational use only, is subject to change without notice, and should not be
construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or
liability for any errors or inaccuracies that may appear in the informational content contained in this guide.
Please remember that existing artwork or images that you may want to include in your project may be protected under
copyright law. The unauthorized incorporation of such material into your new work could be a violation of the rights of
the copyright owner. Please be sure to obtain any permission required from the copyright owner.
Any references to company names in sample templates are for demonstration purposes only and are not intended to
refer to any actual organization.
Adobe, the Adobe logo, Photoshop, Lightroom, and Flash are either registered trademarks or trademarks of Adobe
Systems Incorporated in the United States and/or other countries.
Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States
and/or other countries. Apple, Mac, Mac OS, and Macintosh are trademarks of Apple Computer, Incorporated, registered
in the United States and other countries. Sun and Java are trademarks or registered trademarks of Sun Microsystems,
Incorporated in the United States and other countries. UNIX is a registered trademark of The Open Group in the US and
other countries.
All other trademarks are the property of their respective owners.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users.
The Software and Documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of
“Commercial Computer Software” and “Commercial Computer Software Documentation, as such terms are used in 48
C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through
227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are
being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted
to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright
laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S.
Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the
provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act
of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR
Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding
sentence shall be incorporated by reference.
3
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
The Lightroom SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
The Lua language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
About this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Conventions used in this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1Using the Lightroom SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Writing plug-ins for Lightroom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
The Lightroom SDK scripting environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Namespaces, classes, and objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Defining function contexts and tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Including scripts with require() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Lua syntax notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2Writing a Lightroom Plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Writing standard plug-ins for Lightroom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Declaring the contents of a plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Delivering a standard plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Debugging standard plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Customizing plug-in load behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Initialization and termination functions for the Plug-in Manager . . . . . . . . . . . . . . . . . . . . . . 34
Adding custom sections to the Plug-in Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Defining menu items for a plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3Creating Export and Publish Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Creating an export or publish service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Defining an export service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Initialization and termination functions for services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Defining a publish service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Publish service options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Adding an export post-process action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Inserting and removing actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Action dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Declaring export post-process actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Defining a post-process action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Removing photos from the export operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Defining post-processing of rendered photos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
How post-process actions are executed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Final processing of rendered photos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Customizing the Export and Publishing Manager dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Customizing the export destination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Contents 4
Adding custom sections to the Export or Publishing Manager dialog . . . . . . . . . . . . . . . . . 56
Restricting existing service functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Remembering user choices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Export presets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
Settings for publish services and post-process actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Lightroom built-in property keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Export Location section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
File Naming section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
File Settings section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Image Sizing section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Output Sharpening section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Metadata section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Video section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Watermarking section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Post-Processing Filter section properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
General export properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Publish Service properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4 Working with Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Adding custom metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Declaring a Metadata Provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Defining metadata fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Adding custom metadata tagsets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Defining a metadata tagset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Searching for photos by metadata values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Combining search criteria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Creating searches interactively . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5Creating a User Interface for Your Plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Adding custom dialog views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Using dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Displaying predefined dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Creating custom dialog boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
User interface elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
View properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Binding UI values to data values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Specifying bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Creating observable property tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Bindings for selection controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Complex bindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Determining layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Relative placement of sibling nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Placement within the parent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Factory functions for obtaining layout values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Layout examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
Contents 5
6Writing a Web-engine Plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Creating a web-engine plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Folder contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
Defining the data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
GalleryInfo top-level entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Data model entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Defining a UI for your model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Creating a dynamic data model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Creating a preview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Web SDK manifest API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
LuaPage syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Environment variables available to LuaPages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
LuaPage data types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Web SDK tagsets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Defining custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Using custom tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
Lightroom built-in tagset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Web HTML Live Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Defining messages from Lightroom to a previewed page . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Defining messages from a previewed page to Lightroom . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7Using ZStrings for Localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
ZString format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
ZString characters and escape sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
The LOC function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Localization dictionary files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Localization dictionary file format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Example dictionary file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
Supported languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
8 SDK Sample Plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
The FTP Upload sample plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Bring up the FTP plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
Configure the connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Establish the connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
The Flickr plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
The Flickr API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Flickr plug-in walkthrough . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Metadata and filtering samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Custom metadata sample walkthrough . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Metadata filter sample . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Post-processing samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Post-processing actions walkthrough . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Web engine sample . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
Contents 6
9Getting Started: A Tutorial Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Creating an export plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Create the information file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Create the service scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Displaying a dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
Displaying a custom dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Create a properties table for program data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Create UI elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Run the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Transforming data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Create multiple bindings to one key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Run the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Binding to multiple keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Create multiple bindings to one key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
Run the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Adding a data observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Set up the dialog and table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Create an observer for a data property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Create the dialog contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Run the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
Debugging your plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Specifying a log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Viewing trace information using log files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Viewing trace information in a platform console . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
10 Defining Metadata: A Walkthrough . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Adding custom metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Define metadata fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Define a tagset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
Using the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Customizing the Plug-in Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
11 Web Gallery Plug-ins: A Tutorial Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Creating a Web Gallery plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Add descriptive files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Add HTML template files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Add subfolders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
Defining a data model and functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Add a grid using built-in tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Add pagination using built-in tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
Add another photo size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Customizing the Web Gallery UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Add a binding to a control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Add the title to the HTML template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Testing the plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Adding a customized tagset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Contents 7
Define the tags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
Add the tagset to the gallery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
8
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 Lightrooms export and publish
operations, define Lightroom-specific metadata for photos, and create customized HTML web galleries.
The Lightroom SDK
The Adobe Photoshop Lightroom SDK is available for download from:
http://www.adobe.com/devnet/photoshoplightroom/
The SDK contains these elements (paths are relative to the location that you choose during installation):
LR_SDK/Manual/Lightroom SDK Guide.pdf This programming guide.
LR_SDK/API Reference/index.html The home page for a complete API reference in HTML
format.
LR_SDK/Sample Plugins/ Sample code that demonstrates plug-in development.
For details of what these do and how to use them, see
Chapter 8, “SDK Sample Plug-ins.”
flickr.lrdevplugin
ftp_upload.lrdevplugin
These samples demonstrate the Service Provider
interface.
The first creates a service to upload selected photos
to Flickr using Lightroom’s Publish Manager service.
The second creates a service that uploads photos to
an FTP server, using a customized Export dialog.
custommetadatasample.lrdevplugin This sample demonstrates the creation of
Lightroom-specific metadata, and the customization of
the Plug-in Manager dialog and behavior.
The sample creates custom metadata fields for use
within Lightroom, and a dialog that displays the values
of those metadata fields for selected photos. It also
demonstrates how to add menu items.
metaexportfilter.lrdevplugin Demonstrates the Export Filter Provider by defining a
post-process action and a related section in the Export
dialog. This action offers the user a choice of metadata
values to filter on, and removes all photos that do not
match that choice from the export operation. There is a
predefined function, shouldRenderPhoto(), that helps
do this.
Preface About this document 9
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 5 uses version 5.1.4 of the Lua language.
The Lightroom SDK provides a Lua scripting environment, which extends the Lua languages with an
object-oriented infrastructure; see “The Lightroom SDK scripting environment” on page 12.
About this document
This document has the following sections:
Chapter 1, “Using the Lightroom SDK," provides an introduction to the Lightroom SDK, with the basics
of how Lua plug-ins work, and the concepts and terminology of the Lightroom SDK scripting
environment.
Chapter 2, “Writing a Lightroom Plug-in," p ro v i d e s a n ov e r v i e w o f s t an d a rd p l u g - i n ar c hi t ec t u r e, an d
explains how to customize the Plug-in Manager dialog and plug-in loading behavior.
Chapter 3, “Creating Export and Publish Services," ex pl a i ns h ow to us e t he S D K t o cre a te a n export
plug-in, which customizes the behavior of Lightroom's Export and Publishing Manager dialogs and
export processing.
Chapter 4, “Working with Metadata," e x pl ai n s how to de f ine cus to m ized public or private metadata
fields for Lightroom.
Chapter 5, “Creating a User Interface for Your Plug-in," ex pl a ins how to cr e at e a n d p o pula te a di a log
box or a custom section in the Plug-in Manager dialog or Export dialog with user-interface elements,
using the LrView and LrDialogs namespaces.
Chapter 6, “Writing a Web-engine Plug-in," exp la i ns h o w to cr e at e a L i ghtroo m p lug -i n t ha t de fi n es a
new type of web engine. This type of plug-in uses a slightly different architecture.
Chapter 7, “Using ZStrings for Localization," ex p lains how to lo ca l ize your pl ug - ins user i n ter f a ce fo r
different languages.
Chapter 8, “SDK Sample Plug-ins," w a l k s th ro u gh th e i n s ta l l at i o n a n d u s ag e o f t h e s a m pl e p l u g- i ns
provided with the SDK.
websample.lrwebengine Demonstrates the web-engine plug-in by defining a
simple HTML gallery.
helloworld.lrdevplugin This shows the finished code files produced by the
walkthrough in Chapter 9, “Getting Started: A Tutorial
Example.”
The walkthrough demonstrates the architecture of
standard plug-ins, and the basic techniques for creating
user-interface controls for Lightroom dialogs and
panels.
mymetadata.lrdevplugin
mysample.lrwebengine
These contain the finished code from the tutorial
walkthroughs in Chapter 10 and Chapter 11.
Preface About this document 10
Chapter 9, “Getting Started: A Tutorial Example," wal ks t hr o ug h a “ H ell o Wo rld ” tu to r i al t o h elp y o u
create your first plug-in.
Chapter 10, “Defining Metadata: A Walkthrough," s ho ws h o w to d ef i n e L ig h tro o m- s pe c i fi c m e ta d at a
properties for your photos.
Chapter 11, “Web Gallery Plug-ins: A Tutorial Example,” shows how to define your own HTML
web-engine plug-in.
Conventions used in this document
The following type styles are used for specific types of text:
Typeface Style Used for:
Monospace font Lua code and literal values, such as function names.
Monospace bold Points of interest in code samples.
Monospace italic Variables and placeholders.
Regular italic Introduction of terms.
11
1Using the Lightroom SDK
This chapter provides an introduction to the Lightroom SDK:
“Writing plug-ins for Lightroom” on page 11 describes the basics of how Lua plug-ins work, including
details of the information file and file-system locations.
“The Lightroom SDK scripting environment” on page 12 explains the concepts and terminology of the
Lightroom SDK scripting environment, and provides details of what tools are available to you within
the SDK scripting environment.
Writing plug-ins for Lightroom
The Lightroom SDK allows you to customize and extend certain Lightroom features by creating plug-ins.
For an overview of the plug-in architecture, see Chapter 2, “Writing a Lightroom Plug-in.”
In general, a plug-in consists of Lua-language files (scripts) that define the plug-in functionality, and an
information or manifest file that describes the contents of the plug-in. The information file must have a
specific name, and be placed in a folder with the Lua source files and resource files; the folders may need
to be in specific locations. The type of plug-in is determined by the folder and file placement, and by file
naming conventions.
In the current release these features are extensible:
Menu customization: Plug-ins can add new menu items in the Plug-in Extras menu; see Chapter 2,
“Writing a Lightroom Plug-in."
Export and publish functionality: You can create an export plug-in, which customizes the behavior of
Lightroom's Export and Publishing Manager dialogs and export processing. You can add or remove
items from the dialog, alter or augment the rendering process, and send images to locations other
than files on the local computer. See Chapter 3, “Creating Export and Publish Services."
Metadata: You can define customized public or private metadata fields for Lightroom. Public or
private metadata can be associated with individual photos. You can also define new ways of arranging
the display of metadata within the Library module’s Metadata panel. See Chapter 4, “Working with
Metadata."
Web engine functionality: You can create an HTML web-engine plug-in, which defines a new type of
HTML photo gallery. The engines you define appear in the Gallery panel at the upper right of the Web
module. See Chapter 6, “Writing a Web-engine Plug-in.”
The Lightroom SDK provides an API with which to define a user interface for your plug-in; see Chapter 5,
“Creating a User Interface for Your Plug-in."
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 12
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. This section describes the API usage and
terminology.
The API defined for the Lightroom SDK is fully documented in the Lightroom SDK API Reference, which
is part of the SDK. When you have installed the SDK, the home page is at:
LR_SDK_install_location/API Reference/index.html
Namespaces, classes, and objects
Lightroom defines a namespace as a table containing a suite of functions. This is somewhat like the Lua
module; however, Lightroom does not use or support the module system that was introduced in Lua 5.1
(see http://www.lua.org/manual/5.1/manual.html#5.3).
Lua does not have an object-oriented programming model, but it does allow Lua tables to be used in an
object-like fashion, which the Lightroom SDK does. Lightrooms object and class model is derived from the
one described in Chapter 16 of "Programming in Lua," available online at http://www.lua.org/pil/16.html.
In Lightroom terminology, object and class are used in the typical object-oriented fashion: that is, a class is
a description of a set of behaviors that are associated with a particular data structure, and an object is a
single instance of that class.
The Lightroom SDK defines a set of namespaces and a set of classes; see “Accessing namespace
functions directly” on page 12 and “Creating objects” on page 14. Plug-ins cannot define either
namespaces or classes.
The Lua language defines built-in namespaces and global functions, of which a subset are accessible
in the Lightroom SDK Lua environment. See “Using built-in Lua features” on page 19.
Accessing namespace functions directly
You can access a namespace by using the built-in function import(); it takes a single parameter, the name
of the namespace to be loaded, and returns the table of functions, which you can then access using dot
notation.
For example:
local LrMD5 = import 'LrMD5' -- assign namespace to local variable
local digest = LrMD5.digest( 'some string' ) -- call "digest()" function in namespace
This example shows the convention of assigning the namespace to a variable of the same name. This
practice is not enforced in any way, but helps avoid confusion.
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 13
The Lightroom SDK defines these namespaces; for complete details, see the Lightroom SDK API Reference.
Namespace Description
LrApplication Application-wide information; provides access to the active catalog.
LrBinding Allows you to define data relationships between UI elements and other
objects.
LrColor Both a namespace and a class. Allows access to color values, specified using
RGB or grayscale values or by name.
LrDate Allows you to create and manipulate date-time values.
LrDialogs Allows you to show messages in predefined modal dialogs.
LrErrors Allows you to format Lua error strings to be used in error dialogs.
LrExportSettings Allows you to check or set an image file format for an export operation.
LrFileUtils Allows you to manipulate files and folders in the file system in a
platform-independent manner.
LrFtp Both a namespace and a class. The namespace functions allow you to work
with the paths and settings for FTP connections created with the LrFtp class.
LrFunctionContext Both a namespace and a class. The namespace functions allows you to make
functions calls with defined methods for cleaning up resources allocated
during the execution of a function or task.
LrHttp Allows you to send and receive data using HTTP. Must be used within a task.
LrLocalization Allows you to localize your plug-in for use in multiple languages.
LrLogger Both a namespace and a class. Provides logging capability.
LrMath Provides additional basic math operations not otherwise available in the Lua
language.
LrMD5 Provides MD5 digest services.
LrPasswords Provides a mechanism to store passwords in a secure fashion.
LrPathUtils Allows you to manipulate file-system path strings in a platform-appropriate
way. (All paths are specified in platform-specific syntax.)
LrPhotoInfo Allows you to get information about individual photo files, such as their
dimensions.
LrPrefs Allows you define persistent preferences for your plug-in.
LrProgressScope Both a namespace and a class. Allows you to provide feedback to the user
about the progress of a long-running task
LrRecursionGuard Both a namespace and a class. Provides a simple recursion guard for function
execution.
LrShell Provides access to shell functions of the platform file browser (Windows
Explorer in Windows or Finder in Mac OS).
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 14
Creating objects
When you use the import() function with a class, it returns a constructor function, rather than a table. Use
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
local logger = LrLogger( 'myPlugin' )
-- Calling this function returns an instance of LrLogger, which is assigned to
-- local variable logger. Notice the lowercase naming convention for objects.
logger:enable( 'print' )
logger:warn( 'something bad happened' )
-- Method calls on the object that was just created.
There are some exceptions to this technique. You can create some objects using functions in other objects
or namespaces, such as LrApplication.activeCatalog(). Others are created and passed to you by
Lightroom.
The Lightroom SDK defines these classes; for complete details, see the Lightroom SDK API Reference.
LrStringUtils Provides string manipulation utilities.
LrSystemInfo Provides information about the environment in which Lightroom is running,
such as whether it is 32-bit or 64-bit architecture.
LrTasks Allows you to start and manage tasks that run cooperatively on Lightroom's
main UI thread.
LrView Both a namespace and a class. The namespace functions allow you to obtain
the factory object, create bindings between UI elements and data tables, and
share placement between UI elements.
LrXml Both a namespace and a class. The namespace functions allows you to create
an XML builder object, and to parse existing XML documents into read-only
XML DOM objects.
Namespace Description
Class Description Object creation
LrCatalog Provides access to a
Lightroom catalog.
Returned by LrApplication.activeCatalog()
Most classes provide a pointer back to the catalog
that contains an object, such as LrPhoto.catalog.
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 15
LrCollection Provides access to a
photo collection.
Returned by:
LrCatalog:createCollection()
LrCatalog:createSmartCollection()
LrCatalog:getActiveSources()
LrCatalog:getCollections()
LrCatalog:getCollectionByLocalIdentifier()
LrCollectionSet:getChildren()
LrCollectionSet:getChildCollections
LrPhoto:getContainedCollections()
LrCollectionSet Provides access to a
photo collection set.
Returned by:
LrCatalog:createCollectionSet()
LrCatalog:getCollectionSets()
LrCollectionSet:getChildren()
LrCollection:getParent()
LrCollectionSet:getParent()
LrCollectionSet:getChildCollectionSets()
LrColor Encapsulates a color. Import constructor:
local LrColor = import 'LrColor'
LrDevelopPreset Provides access to a
develop preset.
Returned by
LrDevelopPresetFolder:getDevelopPresets()
LrDevelopPreset
Folder
Provides access to a
develop-preset folder.
Returned by:
LrApplication.developPresetFolders()
LrDevelopPreset:getParent()
LrExportContext Encapsulates an export
context.
Object is passed to your
processRenderedPhotos() function
LrExportRendition Encapsulates a single
photo rendition
operation, generated
during an export
operation.
Returned by LrExportSession:renditions()
LrExportSession Provides access to the list
of photos and renditions
generated during an
export operation.
Import constructor:
local LrExportSession = import
'LrExportSession'
An object is also available as the value of
exportContext.exportSession.
LrFilterContext Provides access to choices
the user has made in the
Export dialog, and to the
list of photos to be
exported.
An LrFilterContext object is passed to your
plug-in as a parameter to your service script's
postProcessRenderedPhotos function. You cannot
import the namespace or access the properties and
functions in any other way.
Class Description Object creation
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 16
LrFolder Provides access to a
file-system folder that
contains photos.
Returned by:
LrCatalog:getFolders()
LrCatalog:getActiveSources()
Lrcatalog:getFolderByPath()
LrFolder:getParent()
LrFtp Both a namespace and a
class. The object
represents an FTP
connection.
Import the namespace:
local LrFtp = import 'LrFtp’
Use the factory function, LrFtp.create()
LrFunctionContext Both a namespace and a
class. Use the object to
register the cleanup
handlers for the called
function execution.
Import the namespace:
local LrFunctionContext = import
'LrFunctionContext’
Object is passed to functions called using the
namespace calling functions. For example:
LrFunctionContext.callWithContext(
"showCustomDialog",
function(contextObject)
-- body of called function
end)
LrKeyword Encapsulates a keyword. Returned by:
LrCatalog:createKeyword()
LrCatalog:getKeywords()
LrKeyword:getChildren()
LrKeyword:getParent()
LrLogger Provides a mechanism for
writing debug output
that can be viewed with
an external log-viewer
application.
Import constructor:
local LrLogger = import
'LrLogger'
LrObservableTable Implements an
observable properties
table.
Create an observable table by calling
LrBinding.makePropertyTable(). Some API
functions create observable tables for you.
LrPhoto A single photo or virtual
copy in Lightroom's active
catalog.
Returned by many functions of LrCatalog,
LrCollection, LrExportSession and so on. Many
classes provide access to the photo objects that they
are associated with, such as
LrKeyword:getPhotos().
LrPlugin Provides access to the
plug-in configuration,
including the path and
resources.
Access the object for your plug-in with the global
variable _PLUGIN.
Class Description Object creation
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 17
LrProgressScope Allows you to provide
feedback to the user
about the progress of a
long-running task.
Import constructor:
local LrProgressScope = import
'LrProgressScope'
LrPublished
Collection
Provides access to a
published-photo
collection.
Access functions are parallel to those for
LrCollection, such as:
LrCatalog:createPublishedCollection()
LrPublishedCollectionSet:getChildren()
LrPublished
CollectionSet
Provides access to a
published-photo
collection set.
Access functions are parallel to those for
LrCollectionSet, such as:
LrCatalog:getPublishedCollectionSets()
LrPublishService:getChildCollectionSets()
LrPublishedPhoto Encapsulates the
publishing information
associated with a photo
that is part of a published
collection.
Returned by
LrPublishedCollection:getPublishedPhotos()
LrPublishService Provides access to a
named publishing
service.
Returned by LrCatalog:getPublishServices()
LrRecursionGuard Provides a simple
recursion guard for
function execution.
Import constructor:
local LrRecursionGuard = import
'LrRecursionGuard'
LrVideoExportPreset Represents a single video
export preset.
Returned by
LrExportSettings.videoExportPresets.
LrView Allows you to construct
dialog box elements.
Import the namespace:
local LrView = import 'LrView’
When creating a dialog to be invoked from a
menu command, import namespace and obtain
a factory object with the namespace function
LrView.osFactory().
When extending a Lightroom dialog, a factory
object is passed to
sectionsForTopOfDialog() and
sectionsForBottomOfDialog()
LrWebViewFactory Allows you to construct
elements for panels in the
Web module.
In a web-engine plug-ins galleryInfo.lrweb file,
this object is passed to the views function. It
extends the standard view factory with additional
functions.
This object is only available within web-engine
plug-ins.
Class Description Object creation
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 18
Accessing object functions and properties
A few classes (LrFtp, LrView, LrXml, and LrFunctionContext) act as both classes and namespaces, and
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. For example:
LrFtp.appendFtpPaths() -- A namespace function
ftpConnection:path() -- An object function
Classes define both functions and properties. To access properties in objects, use the dot notation. Again,
the documentation uses the lowercase naming convention to indicate an instance of a class:
exportRendition.photo -- An object property
A property can have no value; a nil property value is not the equivalent of false, zero, or the empty string.
Setting a nil value for a property that has a default value causes the property to revert to the default.
Using function contexts for error handling
The LrFunctionContext namespace and class is a programming utility for error handling.
Use LrFunctionContext.callWithContext() to wrap a function call. This allows you to attach any
number of handler functions to the call that respond to errors that may occur during the execution of the
wrapped function, or clean up resources regardless of how the wrapped function terminates. If you attach
multiple cleanup or error handlers to the wrapped function, the handlers are called in reverse order of
attachment.
Some of the functions in LrTasks work in conjunction with LrFunctionContext to provide standardized
error reporting behavior. For instance, LrTasks.startAsyncTask() calls
LrDialogs.attachErrorDialogToFunctionContext(). This ensures that errors that occur during the
execution of the task are reported to the user and not silently forgotten. Lightroom provides predefined
error dialogs that you can customize with explanatory messages, as shown in the following example. You
can use LrTasks.startAsyncTaskWithoutErrorHandler() if you wish to provide your own error
reporting instead.
LrXml Both a namespace and a
class. There are two types
of object:
A builder object
allows you to create
and manipulate XML
documents.
A DOM object is
read-only, and allows
you to examine an
existing XML
document.
Import the namespace:
local LrXml = import 'LrXml’
Create a builder object with the namespace
function LrXml.createXmlBuilder().
Create a DOM object with the namespace
function LrXml.parseXml().
Class Description Object creation
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 19
Example: Function context with an error dialog
local LrDialogs = import 'LrDialogs'
local LrErrors = import 'LrErrors'
local LrFunctionContext = import 'LrFunctionContext'
LrFunctionContext.callWithContext( 'error handling demo', function ( context )
-- If an error is thrown during this function call context,
-- show a standard error dialog.
LrDialogs.attachErrorDialogToFunctionContext( context )
-- The code needed to perform your task goes here
-- For illustration, force an error here, throw error two different ways
if showInternalError then -- in some case
error "Example of an internal error" --call built-in error() function
else -- otherwise, use the LrErrors throw function
LrErrors.throwUserError( LOC "$$$/MyPlugin/Error/Example=Example of
a localized error message." )
end
end )
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:
assert(), dofile(), error(), getmetatable(), ipairs(), load(), loadfile(),
loadstring(), next(), pairs(), pcall(), rawequal(), rawget(), rawset(), select(),
setmetatable(), tonumber(), tostring(), type(), unpack()
Not available in Lightroom:
collectgarbage(), gcinfo(), getfenv(), module(), newproxy(), package(), setfenv()
Lua standard namespaces
Available in Lightroom: io, math, string
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 20
Not available in Lightroom: package
Partially available:
os: Contains only the functions clock(), date(), time(), and tmpname(). All other functions
removed. Use LrFileUtils, LrDate, and LrTasks instead.
table: Contains all functions except getn(), setn(), and maxn(), which are deprecated as of Lua
5.1.
coroutine: Contains only the functions canYield() and running().
debug: Contains only the function getInfo().
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 LrFunctionContext.postAsyncTaskWithContext(). Some API functions, such
as those in the LrHttp namespace, are only available when called from within a background task.
The LrFunctionContext object helps you clean up resources following the execution of a function. You
can register any number of cleanup handlers to respond to the success or failure of a function. You must
create property tables within a function context, so that Lightroom can remove notifications when the
table is no longer needed.
You do not create instances of LrFunctionContext directly. They are created by the calling functions, and
exist only for the lifetime of the function call or task. Access the calling functions, such as
LrFunctionContext.postAsyncTaskWithContext(), directly from the imported namespace. A
functionContext object is passed as the first parameter of the call, followed by any other parameters you
provide. Use the passed object to provide the cleanup handlers for the called function execution.
In general, you are responsible for creating tasks when needed. There are some exceptions, however. Many
of the plug-in callback functions in the export and publish APIs are called from within tasks that Lightroom
starts. These are marked as such in the API reference.
For details of the LrFunctionContext and LrTasks functions, see the Lightroom SDK API Reference.
Including scripts with require()
Lightroom defines a require() function that works in a similar, but more narrowly-defined, fashion from
the version that exists in Lua. The require() function takes a single parameter, which is the name of
another Lua file in the same plug-in. On the first call, this file is loaded and executed in the context of its
plug-in; the return value is saved. If the require() function is called again in the same plug-in, its saved
value is used (unless the entire plug-in has been garbage collected, in which case the required file is
loaded and executed again).
A script to be executed this way typically has the effect of defining a table containing a suite of functions.
For example:
SomeFile.lua
SomeFile = {}
-- Typically a file that is required will define a global table whose name
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 21
-- matches the file name.
-- Note that this global is defined in a special function environment for your
-- plug-in and does not affect Lightroom as a whole.
-- You can give this table any name that does not conflict with built-in names
-- and keywords from Lua and Lightroom. In general, avoid names that start with
-- Lr to avoid conflicts with future versions of Lightroom.
function SomeFile.doSomething( arg )
return tostring( arg )
end
Usage of require()
require 'SomeFile.lua'
-- Causes SomeFile.lua to be executed and the value of SomeFile defined above
-- becomes available in the scope of this file.
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"
Semicolons at the ends of statements are optional. We typically omit them.
If you call a function with a single parameter that is a string literal or a table, you can omit the
parentheses around the argument list. This is frequently done when calling the built-in functions
import() and require().
These three statements are equivalent (where func is a variable containing a valid function):
func( "foo" )
func "foo"
func 'foo'
These two statements are also equivalent; the simpler syntax is commonly used when building view
descriptions:
func( { a = 1, b = 2 } )
func{ a = 1, b = 2 }
It is useful to read the chapter on table constructors (http://www.lua.org/pil/3.6.html). There are
several shorthand formats that we use widely, especially in view descriptions. For example, these
forms are equivalent:
local t = { a = 1, b = 2 }
local t = { [ "a" ] = 1, [ "b" ] = 2 }
local t = {}; t.a = 1; t.b = 2
Lua defines an array as a table with numbered keys. Arrays in Lua are 1-based; that is, the first item in
the array is at index 1, not index 0.
The value nil evaluates to a Boolean value of false, but numbers (including 0) evaluate to true. Thus,
in a conditional, only nil and false are considered false. If you use 0 as the condition of an if or
while statement for example, the statement is executed, because the number 0 is a true value.
CHAPTER 1: Using the Lightroom SDK The Lightroom SDK scripting environment 22
Lightroom defines Boolean globals, WIN_ENV and MAC_ENV, which you can use to determine which
platform your script is running on. The LrSystemInfo namespace (first available in version 3.0 of the
Lightroom SDK) can provide additional information about the platform, including whether is 32-bit or
64-bit.
23
2Writing a L ightroom 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 Chapter 6, “Writing a Web-engine Plug-in.”
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. Your plug-in can customize the dialog by adding sections. See
“Customizing plug-in load behavior” on page 33.
Writing standard plug-ins for Lightroom
The Lightroom SDK allows you to customize the behavior of Lightroom in specific ways using a standard
plug-in (as opposed to a web-engine plug-in). The behavior implemented by your plug-in is provided by
one or more Lua scripts. An information file installed in a standard plug-in folder identifies your plug-in
scripts to Lightroom, and associates the plug-in with a unique name.
You can add items to the File, Library, or Help menus to start an operation.
Your plug-in can add a new export or publish destination with an Export Service Provider or Publish
Service Provider. Such a service can also customize the Export or Publishing Manager dialog by adding
and removing sections as appropriate for the destination when the user selects it. See “Creating an
export or publish service” on page 37.
Your plug-in can intercept the expor t process with an Export Filter Provider, which can apply further
processing to photos that the user has chosen to export. The post-process action that a filter defines is
applied after Lightrooms initial rendering, and before the photos are sent to the final destination. Each
filter can add a section to the Export dialog, in which the user can select options and set parameters.
See “Adding an export post-process action” on page 43.
In addition to or instead of defining export customizations, your plug-in can define custom metadata
fields for Lightroom. See Chapter 4, “Working with Metadata."
Declaring the contents of a plug-in
In addition to the Lua script or scripts that define your extension to Lightroom functionality, your plug-in
must contain a file named Info.lua that describes the plug-in to Lightroom, using a Lua table of
descriptive items. The table can or must include these items:
LrSdkVersion Required
number
The preferred version of the Lightroom SDK for this plug-
in. Should be set to .0 for the current release; older plug-
ins may have a value of 1.3, 1.4, 2.0, 3.0, or .0.
LrSdkMinimumVersion Optional
number
The minimum version of the SDK that this plug-in can use.
If your plug-in works with Lightroom 2.0, 3.0,or .0 but
it also provides new features specific to Lightroom , set
this value to 2.0 and LrSdkVersion to .0. Default is the
value of LrSdkVersion.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 24
LrToolkitIdentifier Required
string
A string that uniquely identifies your plug-in. Use
Java-style package names (your domain name in reversed
sequence).
You can use the Plug-in Manager to add multiple plug-ins
with the same identifier, but only one of them can be
enabled. If you enable one, any other plug-in that shares
the same plug-in ID is automatically disabled.
Note that com.adobe.*, which is used in the examples, is
reserved for plug-ins written by Adobe; your own plug-ins
will use your own domain name (com.myCompany.*).
LrPluginName Required
for 2.0 or
newer
string
A localizable string for the plug-in’s display name, which
appears in the Plug-in Manager dialog. Required for SDK
version 2.0 or newer; ignored by earlier versions.
If a plug-in defined for an earlier version is loaded in
Lightroom 2.0 or newer, the Plug-in Manager displays the
title of the first Export Service Provider, or if no Export
Service Provider is defined, the base name of the plug-in
folder.
LrPluginInfoProvider Optional
string
The name of the Lua file (service definition script) to be
executed when the plug-in is loaded. This script can define
functions that run when plug-in is selected or deselected
in the Plug-in Manager dialog, and can add sections to the
Plug-in Manager dialog that are shown when the plug-in is
selected. It See “Customizing plug-in load behavior” on
page 33.
Ignored in any Lightroom version older than 2.0.
LrInitPlugin Optional
string
The name of a Lua script that is loaded and executed when
your plug-in is loaded or reloaded. See “Customizing
plug-in load behavior” on page 33
This item is ignored if LrSdkVersion is less than 2.0.
LrForceInitPlugin Optional
Boolean
When true, forces the initialization script to run at
application startup, even for plug-ins that do not provide
export or publish services or define custom metadata, as
long as the plug-in contributes at least a menu item.
Otherwise, the initialization script does not run until the
plug-ins first use.
Ignored in any Lightroom version older than 4.0.
LrPluginInfoUrl Optional
string
The URL of your web site, or a page that provides
information about your plug-in. See “Customizing plug-in
load behavior” on page 33
Ignored in any Lightroom version older than 2.0.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 25
LrShutdownPlugin Optional
string
The name of a Lua script that is loaded and executed when
the user unloads this plug-in.
This script is executed only if the user loaded or reloaded
the plug-in through the Plug-in Manager dialog, or
approved updating of the catalog structure, during the
current Lightroom session.
Ignored in any Lightroom version older than 3.0.
LrShutdownApp Optional
string
The name of a Lua script that is loaded and executed when
Lightroom is shutting down. See “Application termination
script” on page 29.
This item is ignored if LrSdkVersion is less than 4.0.
LrEnablePlugin Optional
string
The name of a Lua script that is called when the user
enables this plug-in from the Plug-in Manager dialog.
Ignored in any Lightroom version older than 3.0.
LrDisablePlugin Optional
string
The name of a Lua script that is called when the user
disables this plug-in from the Plug-in Manager dialog.
Ignored in any Lightroom version older than 3.0.
VERSION Optional
table
Allows you to provide a version number for your plug-in
that is displayed in the Plug-in Manager dialog. The version
number is for your own use, and need not relate to
Lightroom's version number.
The table has these members:
major (number)
minor (number )
revision (number)
build (number)
display (string)
The numeric values are assembled in order to create a
version designation in the default format:
major.minor.revision.build
The build value is omitted if zero; both revision and
build are omitted if both are zero.
If you prefer to display a version number in a different
format, include the display string in the display field. You
can use LOC to localize the string; see “The LOC function”
on page 150.
Ignored in any Lightroom version older than 2.0.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 26
LrExportMenuItems
LrLibraryMenuItems
LrHelpMenuItems
Optional
table of
tables
These allow you to add new script-defined menu items to
the Plug-in Extras submenus that appear in Lightrooms
File, Library, and Help menus.
For details of the member tables, see “Defining menu items
for a plug-in” on page 35:
LrExportFilterProvider Optional
table of
tables
Adds one or more new export filters, which can process
photos before they are rendered for the export destination.
Each item is a table with these entries:
title (string): The display name of the filter.
file (string): The name of the Lua file (filter definition
script) to be executed when the filter is chosen. See
“Adding an export post-process action” on page 43.
id (string): A unique identifying string for this filter.
requiresFilter (string, optional): The identifier for
another filter that must be used with this one.
Can be combined with other services (export services,
custom metadata) or can be the only service provided by
the plug-in.
Ignored in any Lightroom version older than 2.0.
URLHandler Optional
string
Optional. The name of a file that provides custom URL
handling. The file must return a table that contains a
'URLHandler' entry. This must be a function that takes a
URL as a parameter.
Lightroom is configured to be the registered receiver of
URLs starting with 'lightroom://'. When it receives such
a URL, it checks registered handlers to find an appropriate
one. For example, the plug-in with the ID 'my.plugin.id'
can register a handler for URLs starting with
'lightroom://my.plugin.id'.
Ignored in any Lightroom version older than 4.0.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 27
LrExportServiceProvider Optional
table of
tables
Adds one or more new export destinations or publish
service providers.
Each item is a table with these entries:
title (string): The display name of this export
destination.
file (string): The name of the Lua file (service definition
script) to be executed when the export destination or
publish service is chosen. See “Defining an export
service” on page 37.
builtInPresetsDir (string, optional): The name of a
subdirectory in the plug-in directory that contains
predefined export settings values. This must be a
simple folder name; it cannot contain any
path-significant characters, such as slashes.
Lightroom preset files are identified by the
.lrtemplate extension. (Publish services are not
associated with presets.)
id (string, optional): A unique identifier for this export
service. If none is provided, a simple consecutive
number value (1, 2, 3...) is assigned.
Can be combined with other services (export filters,
custom metadata) or can be the only service provided by
the plug-in.
LrMetadataProvider Optional
table of
tables
Adds custom metadata fields, available only in Lightroom.
There can be only one such item in a plug-in. It contains a
string, the name of the Lua file (metadata definition script)
that defines the fields. See “Adding custom metadata” on
page 71.
Can be combined with other services (export services,
export filters) or can be the only service provided by the
plug-in.
Ignored in any Lightroom version older than 2.0.
LrMetadataTagsetFactory Optional
table of
tables
Adds a tagset of predefined metadata fields. The user can
select defined metadata tagsets from a menu in the
Metadata panel. Some tagsets are supplied by Lightroom;
this allows your plug-in to supply additional tagsets. See
“Adding custom metadata tagsets” on page 76.
Ignored in any Lightroom version older than 2.0.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 28
The loader environment
The Info.lua file is a special Lua environment that is much more restrictive than the general SDK Lua
environment in which other scripts run.
The standard Lua namespace string is available, and you can use the LOC function for localization of
display strings in this file (see Chapter 7, “Using ZStrings for Localization“).
You can use WIN_ENV and MAC_ENV environment variables, and the _VERSION variable that contains
most of the version information otherwise available through LrApplication.versionTable().
However, you cannot use any of the other Lua or Lightroom globals defined in the SDK scripting
environment, (see “The Lightroom SDK scripting environment” on page 12). For example, you cannot use
import or require in this context.
Here is an example of an Info.lua file for a plug-in that adds items to the Lightroom menus:
return {
LrSdkVersion = 5.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.
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",
LrAlsoUseBuiltInTransla-
tions
Optional
Boolean
Controls behavior of built-in LOC function. When true,
strings that are not found in the plug-in’s translation file are
checked against Lightrooms translation file for the current
language.
Note that string keys are not guaranteed to remain the
same across version releases.
Ignored in any Lightroom version older than 3.0.
LrLimitNumberOfTempRend-
itions
Optional
Boolean
Controls whether Lightroom will throttle the number of
temporary image files on disk waiting for the plug-in’s
processing during export. The intent of this option is to
allow protection against high disk space consumption
during large exports.
If true, the plug-in is expected to remove the temporary
rendition files when it is done with them.
Ignored in any Lightroom version older than 5.0.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 29
file = "ShowCustomDialog.lua",
},
{
title = LOC "$$$/HelloWorld/MultiBind=Hello world Custom Dialog with
MultipleBind",
file = "CustomDialogWithMultipleBind.lua",
},
{
title = LOC "$$$/HelloWorld/RadioButtons=Hello world RadioButtons",
file = "RadioButtons.lua",
},
{
title = LOC "$$$/HelloWorld/DialogObserver=Hello world Custom Dialog with
Observer",
file = "CustomDialogWithObserver.lua",
},
},
VERSION = { major=3, minor=0, revision=0, build=200000, },
}
You can find more examples in the sample plug-ins provided with the SDK.
Application termination script
LrShutdownApp specifies a script that is called at application shutdown time. This script must return a
table that contains an LrShutdownFunction member; this function takes two arguments, doneFunction
and progressFunction, in that order.
The doneFunction takes no arguments; it is called when the plug-in's shutdown tasks have been
completed (which allows the plug-in's shutdown operation to use asynchronous tasks).
The progressFunction is invoked to report progress during the execution of the plug-in's shutdown
tasks. This function takes two arguments, percent complete (number between 0 and 1) and a
descriptive display string for the progress dialog. It must return a Boolean value, true if the user clicks
Cancel in the progress dialog.
If 10 seconds pass without progress being reported by a call to the progressFunction, the shutdown task
is assumed hung or terminated, and application shutdown proceeds. The plug-in shutdown must monitor
this status and respond appropriately to it.
The LrDialogs namespace is not available in the environment of the shutdown task.
Delivering a standard plug-in
Package your Lua files (the information file, Info.lua, and all Lua scripts) in a single folder with a suffix of
.lrplugin; for example, MyPluginName.lrplugin.
NOTE: In Mac OS, the suffix .lrplugin creates a package, which looks like a single file. For convenience,
you can use the suffix .lrdevplugin during development, and change the extension to .lrplugin for
delivery. The .lrdevplugin suffix is recognized by Lightroom but does not trigger the package behavior
in the Mac OS Finder.
A plug-in folder can reside in any location on the hard drive. Users can load the plug-in using the Add
button in the Plug-in Manager. Once it is added, users can enable or disable it through the dialog, reload it
using the Plug-in Author Tools in the dialog, or unload it using the Remove button.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 30
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. They appear only when
the plug-in is selected in the list. The sections are collapsible, and you can define a descriptive string (a
synopsis) to appear on the right side when the section is closed.
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 31
For details of how to define these sections, see See “Adding custom sections to the Plug-in Manager” on
page 34.
Automatic plug-in loading
Lightroom automatically checks for plug-ins in the standard Modules folder where other Lightroom
settings are stored:
You may want to use this location if, for example, you are writing an installer that installs a Lightroom
plug-in and also installs a helper application.
Plug-ins that are installed in this location are automatically listed in the Plug-in Manager dialog. You can
use the dialog to enable or disable such a plug-in, but not to remove it. The Remove button is dimmed
when such a plug-in is selected.
In Mac OS (current user) ~/Library/Application Support/Adobe/Lightroom/Modules
In Mac OS (all users) /Library/Application Support/Adobe/Lightroom/Modules
In Windows XP C:\Documents and Users\username\Application
Data\Adobe\Lightroom\Modules
In Windows 7/Vista C:\Users\username\AppData\Roaming\Adobe\Lightroom\Modules
CHAPTER 2: Writing a Lightroom Plug-in Writing standard plug-ins for Lightroom 32
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" section, you can:
Reload a plug-in after you make code changes.
Choose to have Lightroom reload the plug-in automatically on each export or publish operation.
NOTE: Reloading a plug-in interactively or automatically after export does not reload any localization
dictionaries supplied with that plug-in. The translation dictionaries are read only when the plug-in is
first loaded or Lightroom is restarted. See Chapter 7, “Using ZStrings for Localization.”
Choose a file to which to save diagnostic messages if a plug-in fails to load, or encounters an error at
any stage of its operation.
The Lightroom SDK does not supply a development environment in which to debug your plug-ins, but it
does supply the LrLogger namespace, which allows you to configure a log file and viewer for trace
information of various kinds, and add tracing statements to your scripts. For an example, see “Debugging
your plug-in” on page 186.
Finding deprecated calls
You can add a debugging flag to your configuration file (config.lua) to help you find occurrences of calls
to deprecated functionality in your plug-in.
sdkDeprecation.action=throw|log
When you specify the action throw, Lightroom throws an exception each time a deprecated call is
executed.
To write deprecated call occurrences to a file, you must specify the action log, and also define this logger
in your config.lua file:
loggers.AgSdkDeprecation = {
logLevel = "info",
action = "logfile",
}
Lightroom writes log message to this file:
(Windows) <user_home>\My Documents\AgSdkDeprecation.log
(Mac OS) ~/Documents/AgSdkDeprecation.log.
CHAPTER 2: Writing a Lightroom Plug-in Customizing plug-in load behavior 33
Customizing plug-in load behavior
You can customize your plug-in’s behavior when it is loaded or selected in the Plug-in Manager dialog. To
do this, the Info.lua file for your plug-in can include these entries:
LrPluginInfoProvider points to a script that can return any or all of the following function
definitions which customize appearance or behavior of the Plug-in Manager dialog when the plug-in
is selected:
LrInitPlugin points to a script that runs when the plug-in is loaded or reloaded. You can use this to
initialize values in your plug-in’s global function environment, which are protected from garbage
collection. When the plug-in is reloaded, a new environment is created. All previous values are
discarded and this function is executed again.
LrShutdownPlugin and LrShutdownApp point to scripts that allow you to control the termination
procedure for your plug-in, specified by LrShutdownPlugin and LrShutdownApp.. You can use these
to clean up private data. See “Application termination script” on page 29.
LrPluginInfoUrl gives the URL of your web site, or a page that provides information about your
plug-in. This URL is displayed in the Status section of the Plug-in Manager dialog when your plug-in is
loaded and selected. The URL is also displayed as part of the error message if your plug-in fails to load
properly or cannot be found.
LrEnablePlugin and LrDisablePlugin provide functions to be called when your plug-in is enabled
or disabled in the Plug-in Manager dialog.
For example:
return {
LrSdkVersion = 5.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',
}
Item Description
startDialog
endDialog
Initialization and termination functions that run when your plug-in
is selected or deselected in the Plug-in Manager dialog.
The same items are defined slightly differently in an Export Service
Provider to run when the service is selected or deselected in the
Export dialog; see “Initialization and termination functions for the
Plug-in Manager” on page 34.
sectionsForTopOfDialog
sectionsForBottomOfDialog
Definitions for one or more new sections to display in the Plug-in
Manager dialog when your plug-in is selected in the dialog.
The same items can be defined in an Export Service Provider or
Export Filter Provider to customize the Export dialog when the
service or filter is selected or deselected there; see “Adding custom
sections to the Plug-in Manager” on page 34 for details.
CHAPTER 2: Writing a Lightroom Plug-in Customizing plug-in load behavior 34
Initialization and termination functions for the Plug-in Manager
In addition to the LrInitPlugin and LrShutdownPlugin scripts that are run on load and unload, you can
provide functions to be called when your plug-in is selected or deselected. To do so, the service definition
script for your Plug-in Info Provider should return these table entries, which contain the function
definitions:
startDialog = function( propertyTable ) ... end,
endDialog = function( propertyTable ) ... end,
When the functions are defined in a Plug-in Info Provider:
The startDialog function is called whenever your plug-in is selected in the Plug-in Manager.
The endDialog function is called when the user deselects the plug-in in the Plug-in Manager.
NOTE: These same entries can be supplied by an Export Service Provider, although the definitions are
slightly different. Functions defined in an Export Service Provider are executed only when the plug-in is
selected in the Export dialog, never from the Plug-in Manager dialog. See “Initialization and termination
functions for services” on page 40.
The propertyTable parameter for both functions is an empty, observable table which you can use to keep
private data for your plug-in. (See “Binding UI values to data values” on page 97.) This table is discarded
when your plug-in is deselected in the Plug-in Manager or when the Plug-in Manager dialog is closed. It is
not preserved across sessions. You can use LrPreferences if you want to save information across
invocations.
These are blocking calls. If you need to start a long-running task (such as network access), create a task
using the LrTasks namespace. See “Defining function contexts and tasks” on page 20.
Adding custom sections to the Plug-in Manager
Your plug-in can define one or more sections to be displayed in the Plug-in Manager dialog (when defined
in an LrPluginInfoProvider entry) or in the Export or Publishing Manager dialog (when defined in an
LrExportServiceProvider entry). The custom sections can be shown above or below the Lightroom
standard sections for the dialog.
To customize the dialog, define a function that returns a table of sections, defined using LrView objects.
The function is the value of one of these service entries:
sectionsForTopOfDialog = function( viewFactory, propertyTable ) ... end,
sectionsForBottomOfDialog = function( viewFactory, propertyTable ) ... end,
NOTE: Similar functions can be defined in an Export Service Provider, to customize the Export dialog
when the export destination is selected or the Publishing Manager dialog for a publish service, and
also in an Export Filter Provider, to add a section to the dialog when a post-process action is selected.
See “Customizing the Export and Publishing Manager dialogs” on page 55 and “Adding an export
post-process action” on page 43.
Lightroom passes your function a factory object which allows you to create the LrView objects that define
the elements of your sections; that is, UI controls, such as buttons and text, and containers that group the
controls and determine the layout. For additional details of the dialog elements you can create with
LrView, see “Adding custom dialog views” on page 85.”
CHAPTER 2: Writing a Lightroom Plug-in Defining menu items for a plug-in 35
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 ... },
...
}
}
end
A section entry table defines the contents of an implicit container, which Lightroom creates to hold your
view hierarchy.
Each section entry sets a title and synopsis for the section; the section is identified by the title
text on the left, and is collapsible. When in the collapsed state, the synopsis text is shown on the
right.
The rest of the table entry creates the UI elements that are shown when the section is expanded. To
create the UI elements, use the LrView factory passed to your top-level sectionsFor... function.
This process is explained in more detail in “Adding custom dialog views” on page 85.
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” on page 97.
Defining menu items for a plug-in
To define a menu item that starts your plug-ins UI, or performs any other script-defined operation, the
table returned by your Info.lua file must include one of these items:
CHAPTER 2: Writing a Lightroom Plug-in Defining menu items for a plug-in 36
LrExportMenuItems
LrLibraryMenuItems
LrHelpMenuItems
Items that you add in LrExportMenuItems appear in the Plug-in Extras submenu of the File menu
(immediately below the Export section).
Items that you add to the Library and Help menus appear in the Plug-in Extras submenu of those
menus.
Each item is a table of tables, and each member table defines one menu item. The member table for a
menu item should contain these entries:
In Windows, the title string can include an ampersand (&) character in the name to make the following
character a keyboard shortcut or accelerator that invokes that item. (This feature is not available in Mac OS;
on that platform, the & character is automatically removed if present.)
For example, suppose the table returned by your Info.lua file contains this item:
LrExportMenuItems = { title = 'My &Plugin', file = 'somefile.lua' }
This would create a command in the File > Plug-in Extras menu with the label “My Plugin”. The command
would execute the script found in somefile.lua.
The user can invoke this command using the keyboard accelerator sequence ALT F + U + ENTER + P.
ALT F brings up the File menu
U is the keyboard accelerator for the Plug-in Extras submenu
P is the keyboard accelerator for the new command
title (String) The display name of the menu item.
file (String) The name of the Lua file (service definition script) to be executed when the menu
item is chosen. See “Defining an export service” on page 37.
enabledWhen (String, optional) A condition under which to enable this menu item. One of:
photosAvailable: Item enabled when any photos or videos are available in the
grid.
photosSelected: Item enabled when any photos are selected. Ignores videos.
videosSelected: Item enabled when any videos are selected. Ignores still photos.
anythingSelected: Item enabled when any photos or videos are selected.
If the selection is very large (>5000 photos), menu items are enabled regardless of this
value.
37
3Creating 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.
Customize the Export and Publishing Manager dialogs by adding or removing sections.
Creating an export or publish service
Lightroom offers two customizable mechanisms for transferring photos to an external location: export and
publish.
Export is a one-time operation: the user selects some photos, the photos are rendered once and
transferred to their destination. Lightroom maintains no further record of the export (although some
plug-ins do retain such a record via custom metadata). By default, Lightroom provides export services
for a user-selected location on the local hard drive and CD/DVD drive. Plug-ins can define export
services to extend this support to other destinations (typically web services or devices). See “Defining
an export service” on page 37.
Publish is similar to export, but represents an ongoing relationship between Lightroom and the
destination. You publish a collection (or many collections) of photos to a location when you want
them to stay up to date as you change the photos. To publish, the user establishes a connection to a
destination (typically, but not necessarily, a web service) in the Publishing Manager dialog. By default,
Lightroom provides publish service support for user-selected locations on the local hard drive and
Flickr. As with export services, plug-ins can define publish services to extend this support to other
destinations. See “Defining a publish service” on page 41.
Though they are presented differently, there is a lot in common between these two mechanisms and they
share much of the same API. Export services are the simpler of the two, so well start by describing this API,
then describe additional functionality that is specific to publish services.
Defining an export service
To define the functionality of your export service, write a Lua script that returns a table; each predefined
entry in the table describes a specific type of customization. You then declare the name of your service and
associate it with the defining script, in the same way you declare any plug-in.
To declare an Export Service Provider, add the following block to your Info.lua file:
LrExportServiceProvider = {
title = "Service Name", -- this string appears as the Export destination
file = "MyExportServiceProvider.lua", -- the service definition script
builtInPresetsDir = "myPresets", -- an optional subfolder for presets
},
CHAPTER 3: Creating Export and Publish Services Defining an export service 38
The title and file entries are required. You can use the built-in function LOC and a ZString if you wish to
localize the services title; see details in Chapter 7, “Using ZStrings for Localization.”
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. These types of
customizations are defined:
Restrict the built-in services offered by the Export dialog.
Customize the Export dialog by defining new sections.
A function that defines the export operation to be performed on rendered photos (required).
Here is an example of a table returned by a service definition script:
return {
startDialog = function( propertyTable ) ... end,
endDialog = function( propertyTable, why ) ... end,
exportPresetFields = { { key = 'myPluginSetting', default = 'Initial value' } },
showSections = { 'fileNaming', 'imageSettings' },
sectionsForBottomOfDialog = function( viewFactory, propertyTable ) ... end,
processRenderedPhotos = function( functionContext, exportContext ) ... end
}
These are the specific items that can be in the table returned by the service definition script for an Export
or Publish Service Provider:
Item Description
startDialog
endDialog
Initialization and termination functions for your plug-in; see
“Initialization and termination functions for services” on page 40.
exportPresetFields A set of properties that you define for your plug-in that you want
to be persistent between sessions. See “Remembering user
choices” on page 59. These are added to the built-in settings
defined by Lightroom; see “Lightroom built-in property keys” on
page 61.
processRenderedPhotos A callback function that manages the rendering and subsequent
handling of exported photos; see “Customizing the Export and
Publishing Manager dialogs” on page 55.
CHAPTER 3: Creating Export and Publish Services Defining an export service 39
canExportToTemporaryLocation A Boolean value that indicates whether the service provider can
place files in a temporary export destination in the local file
system.
When true, an additional item, “Temporary folder (will be
discarded upon completion)” is added to the Export To pop-up
menu at the top of the Export dialog. Default is false. (This is tied
to LR_export_destinationType; see “Lightroom built-in
property keys” on page 61.)
If the user selects this option, the file naming options in the dialog
disappear and the files are written to a hidden temporary folder
on the local hard drive. When the Export Service Provider has
completed its work, this folder and its contents are deleted.
If your plug-in hides the Export Location section of the dialog, you
do not need to use this option. The temporary folder behavior
happens automatically in that case.
Optional in Lightroom SDK 2.0 and later. Ignored in earlier
versions.
showSections
hideSections
A callback function that returns a table of built-in sections to
include or exclude from those displayed in the Export dialog.
See “Restricting existing service functionality” on page 58 for
details.
allowFileFormats
disallowFileFormats
A table of file formats to include or exclude from those offered in
the Export dialog.
See “Restricting existing service functionality” on page 58 for
details.
allowColorSpaces
disallowColorSpaces
A table of color spaces to include or exclude from those offered in
the Export dialog.
See “Restricting existing service functionality” on page 58 for
details.
sectionsForTopOfDialog
sectionsForBottomOfDialog
Definitions for one or more new sections to display in the Export
dialog; see “Adding custom sections to the Export or Publishing
Manager dialog” on page 56 for details.
hidePrintResolution When true, the options for sizing in the Image Sizing section are
shown only in pixel units; all mention of print units such as inches,
centimeters, and pixels-per-inch are hidden.
additional publish service options If this is a publish service, there are a number of other options that
you can specify; see “Publish service options” on page 42.
Item Description
CHAPTER 3: Creating Export and Publish Services Defining an export service 40
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 ) ... end,
endDialog = function( propertyTable, why ) ... end,
The startDialog function is called when the user chooses a post-process action or export destination
provided by this plug-in in the Export dialog, or when the destination is already selected when the
dialog is invoked, remembered from the previous export operation.
The endDialog function is called when the user deselects the action or export destination in the
Export dialog, or dismisses the Export dialog.
NOTE: Similar entries can be supplied by a Plug-in Info Provider, although the definitions are slightly
different. Functions defined in a Plug-in Info Provider are executed only when the plug-in is selected in the
Plug-in Manager dialog, never from the Export dialog. See “Initialization and termination functions for the
Plug-in Manager” on page 34.
The propertyTable parameter for both functions is a table which contains the most recent settings for your
export plug-in, including both settings that you have defined and Lightroom-defined export settings (see
“Remembering user choices” on page 59). When your plug-in is being used as a publish service provider,
the property table contains additional values that tell you about the publishing status; see “Publish Service
properties” on page 70.
When your plug-in is deactivated, Lightroom calls your endDialog function with why set to one of the
following string values:
These are blocking calls. If you need to start a long-running task (such as network access), create a task
using the LrTasks namespace. See “Defining function contexts and tasks” on page 20.
changedServiceProvider A different Export Service Provider was chosen as the export or publish
destination. Your plug-in is no longer active.
ok The user clicked the “Export” or “Save” button. The Export or Publishing
Manager dialog has closed.
For an export service, Lightroom begins exporting images through
your plug-in. Do not attempt to start uploading photos at this point;
use the processRenderedPhotos callback function to do that. See
“Customizing the Export and Publishing Manager dialogs” on page 55.
For a publish service, Lightroom creates a new publish service in the
Publish Services panel that can be used later to publish images
through your plug-in.
cancel The user clicked the “Cancel” button and the Export or Publishing Manager
dialog has closed without initiating the operation.
CHAPTER 3: Creating Export and Publish Services Defining a publish service 41
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.
A publish service differs from an export service in these ways:
The publish service keeps information about what has been published previously, which allows you to
export only new or changed images to the same destination.
CHAPTER 3: Creating Export and Publish Services Defining a publish service 42
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.
A publish service can retrieve comment and rating information that has been added to an image after
publication.
Within each publish service, the user can create one or more collections, just like those in the Library
modules Collections panel. These are referred to as published collections. The user adds photos to
published collections (or has them added automatically if it is a published smart collection). When the user
chooses to publish (by choosing Publish Now from the published collections context menu, for example),
Lightroom brings the collection up to date, synchronizing the local photos with the remote copies.
Updating the collection may involve one or more of the following operations:
Export new photos to the collection.
Re-export existing photos to the collection (updating the rendering or metadata if they have changed
since the previous publish).
Delete photos from the collection.
Update the sorting sequence for the collection (if applicable).
Download comments and ratings (if applicable) from the remote service.
Publish service options
To define the functionality of your publish service, write a Lua script that returns a table; each predefined
entry in the table describes a specific type of customization. You then declare the name of your service and
associate it with the defining script, in the same way you declare any plug-in.
To declare a Publish service, add the following block to your Info.lua file:
LrExportServiceProvider = {
title = "Service Name", -- this string appears in the Publish Services panel
file = "MyPublishServiceProvider.lua", -- the service definition script
},
Notice that this differs from an Export service in that you do not provide a presets folder location. A plug-in
cannot control the settings in the Publishing Manager dialog using presets, although it can provide
default values for its own settings, and modify its own settings on dialog startup using the startDialog
callback.
With the exception of export presets, a publish service is a superset of an export service. The publish
service definition script can create any of the elements that an export service does, with only minor
differences. In addition, your publish service should define additional elements that control the
publication data and processes.
The API defines a number of additional items that allow you to customize the publishing experience for
the end user, and to reflect changes in the collection structure made by your plug-in. These are the
additional items that can be in the table returned by the service definition script for a Publish Service
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 43
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. A
post-process action can modify the rendered images, or can suppress the export of certain photos, based
on any criteria that you define. The script is identified by the LrExportFilterProvider entry in the
plug-ins Info.lua file.
A single SDK export plug-in can define one or more Export Filter Providers, one or more Export Service
Providers, or both. In any given export session, there must be exactly one Export Service Provider, but
there can be any number of post-process actions (or none). A single Export Filter Provider can define
multiple actions. Post-process actions are executed in a specific sequence, partly determined by user
choices. If you set up a dependency using the requiresFilter option, the sequence of execution honors
that dependency.
While Export Service Providers can add multiple sections at either the top or the bottom of the Export
dialog, each post-process action can provide only one section for the dialog, which is always inserted after
Lightroom's built-in sections, and before any "bottom" sections defined by the Export Service Provider.
Export Filter Providers cannot define presets of their own, but can be included in an Export Service preset;
see “Creating an export or publish service” on page 37.
A post-process action is inserted between Lightroom's initial rendering of photos and the writing of the
rendered image files to their destination (either the default destination, or one provided by a plug-in’s
export service). A post-process action (or set of actions) can be applied to photos that are being exported
to any destination; that is, an Export Filter Provider does not need to be part of the same plug-in that
provides the export service.
For details, see “How post-process actions are executed” on page 50
Inserting and removing actions
When any plug-in defining a post-process action is loaded, the action appears in the Post-Process Actions
section of the Export dialog, on the left below the Presets section. When you open the plug-in, the
individual actions defined by the plug-in appear as choices below it. When you select an action, the Insert
button is enabled, allowing you to insert the action into the processing queue. (You can also insert an
action by double-clicking it.)
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 44
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. You can also remove the
action from the queue by clicking the X icon in the related section.
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 45
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 filterRenderedPhotos() function.
This main action is required by the others in the set. To declare the dependency, make the ID of the main
action the value of the requiresFilter option for the dependent actions.
Each post-process action can define a single section for the Export dialog. When the user selects an action,
that actions dialog section is shown, along with that of the required filter, if there is one.
For example, suppose your plug-in has defined:
1. MyAction, the main action that performs the filtering operation
2. Color, which allows the user to choose a color to be used by MyAction
3. Lines, which allows a user to choose line widths to be used by MyAction
4. An Export Service Provider that performs an FTP upload
When the user chooses the FTP-upload export destination and clicks Export, the service provider requests
an export rendition for each photo that is active at the time. If the user does not choose any actions, the
request is satisfied directly by Lightroom using LrExportRendition.
If the user inserts Color, the dialog shows both the section for defining a border, and the section for
MyAction, which is required by Color. After making all the necessary choices for the chosen actions, the
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 46
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. MyAction performs the actual processing and makes its own
request for renditions. When there are no more actions, the requests are satisfied directly by Lightroom
using LrExportRendition.
Each action runs in its own task in Lightroom (see “Defining function contexts and tasks” on page 20),
which means that the operations performed by each action can be performed in parallel. An action task
first requests its renditions, then iterates through them making its transformations as appropriate. When
the action is done rendering each photo, it signals the downstream task which can then process the
rendered photo. For a more detailed description of the processing path, see “How post-process actions are
executed” on page 50.
Declaring export post-process actions
In the Info.lua file for a plug-in that defines an export post-process action, you must set LrSdkVersion
= 2.0 (or higher) in order for your filters to be recognized. If you set LrSdkMinimumVersion = 1.3, the
plug-in can be loaded in Lightroom 1.3, but the post-process actions are ignored.
To declare one or more post-process actions, add the following block to your Info.lua file:
LrExportFilterProvider = {
title = "Filter Name", -- this display string appears in the dialog
file = "MyExportFilterProvider.lua", -- the action definition script
id = "myFilter", -- a unique identifier for the action
requiresFilter = "mainFilter", -- optional
supportsVideo = "true" -- optional
},
There can be one or many action definitions. Each definition is a table with up to four items:
title (string): The localizable display name of the action, which appears in the Post-Process Actions
section of the Export dialog.
file (string): The name of the Lua file (action definition script) that provides more information about
the action. The script is executed when the export operation is started; that is, when the user clicks
Export in the Export dialog.
id (string): An identifying string for this action, unique within this plug-in. Required if more than one
action is defined in one plug-in.
requiresFilter (string): Optional, the identifier for the action that performs the processing.
supportsVideo (Boolean): Optional. If true, this filter has access to video files. Default is false; if not
supplied, video files are not processed by this filter. Supported in version 4.0 or higher.
For example, this defines three distinct actions, and the first is the one that actually performs the
processing. It must be present before either of the other two can run; they simply set parameters to be
used by the main action:
LrExportFilterProvider = {
{
title = "MyAction",
file = "myAction.lua",
id = "main",
},
{
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 47
title = "Color",
file = "colorAction.lua",
id = "color",
requiresFilter = "main",
},
{
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 A function that defines how this action processes the list of rendered
photos that it receives. See “Defining post-processing of rendered
photos” on page 48.
Typically, only the main action in a group defines this function.
shouldRenderPhoto A function that selects photos to be removed from the list of rendered
photos that it receives. See “Removing photos from the export
operation” on page 48.
startDialog
endDialog
Initialization and termination functions that run when the action is
selected or deselected in the Export dialog. See “Initialization and
termination functions for services” on page 40.
exportPresetFields A set of export preset settings that you define for your plug-in (in
addition to the built-in settings defined by Lightroom). If provided,
these fields are transferred from the Export dialog’s property table to
any export preset that is created when this post-process action is
selected for the current Export session. See “Remembering user
choices” on page 59.
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 48
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 shouldRenderPhoto(). This function receives two
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.
shouldRenderPhoto = function ( exportSettings, photo )...end,
The function should return true if the photo should remain in the list and be passed to the next action or
exported, or false if it should be removed from the list.
For a publish operation, if a post-process action returns false for a potentially publishable photo, that
photo is not published, but remains in the “New Photos to Publish” state.
This example is for a simple filter that removes photos that do not have a minimum star rating:
function RatingExportFilterProvider.shouldRenderPhoto( exportSettings, photo )
local minRating = exportSettings.min_rating or 1
local shouldRender
local rating = photo:getRawMetadata( 'rating' )
shouldRender = rating and rating >= minRating
return shouldRender
end
Defining post-processing of rendered photos
To specify exactly how each photo should be modified after it is rendered and passed to the action, the
action-definition script for your main action defines a function named postProcessRenderedPhotos().
postProcessRenderedPhotos = function( functionContext, filterContext ) ... end,
sectionForFilterInDialog A function that defines a new section in the Export dialog which
appears when the action is selected, allowing the user to make choices
that affect the operation. Any action in a group can define a dialog
section.
The function must conform to this prototype:
sectionForFilterInDialog = function( viewFactory,
propertyTable ) ... end,
This function is defined in the same way as sectionsForTopOfDialog
and sectionsForBottomOfDialog, except that the function returns a
single section definition, not an array of section definitions; see
“Adding custom sections to the Export or Publishing Manager dialog”
on page 56. The section is always added at the bottom of the Export
dialog, but above any “bottom” sections defined for the active Export
Service Provider.
The property table passed to this function is shared among all Export
Filter Providers and Export Service Providers defined by this plug-in.
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 49
This function takes two parameters, a function context and a filter context. It can retrieve each photo from
the filterContext.renditionsToSatisfy property, and process it as desired. The list of renditions
provides access to the export settings with which the photos were originally rendered, and can check or
modify those settings and rerender the photos as needed.
The processing is typically performed by an external application. You can build a command string and pass
it to a platform-specific shell for execution, using LrTasks.execute().
This processing function typically looks something like this:
function SimpleExternalToolFilterProvider.postProcessRenderedPhotos( functionContext,
filterContext )
-- Optional: If you want to change the render settings for each photo
-- before Lightroom renders it, write something like the following.
-- If not, omit the renditionOptions definition, and also omit
-- renditionOptions from the call to filterContext:rendition()
local renditionOptions = {
filterSettings = function( renditionToSatisfy, exportSettings )
exportSettings.LR_format = 'TIFF'
return os.tmpname()
-- ... if you wanted Lightroom to generate TIFF files
-- and override the configured filename when providing
-- input images to this post-process action.
-- 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
-- Wait for the upstream task to finish its work on this photo.
local success, pathOrMessage = sourceRendition:waitForRender()
if success then
-- Now that the photo is completed and available to this filter,
-- you can do your work on the photo here.
-- It would look somethinglike this:
local status = LrTasks.execute( 'mytool "' .. pathOrMessage .. '"' )
-- (This tool is hypothetical.)
-- You may need to use escapes in the file name so that
-- special characters are not interpreted by the OS shell
-- (cmd.exe in Windows or bash in Mac OS).
-- In Windows, enclose the whole command in double quotes.
-- If your tool cannot process the photo as intended, use
-- something like this to signal a failure for this rendition only:
if status ~= (desired status) then
renditionToSatisfy:renditionIsDone( false, "error message" )
end
-- (Replace "error message" with a user-readable string explaining why
-- the photo failed to render.)
-- It is neither necessary nor harmful to call renditionIsDone if the
-- rendition has completed successfully.
-- The iterator for filterContext:renditions calls it
-- automatically if you have not already done so.
end
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 50
end
end
How post-process actions are executed
During an export operation, rendition requests and state information are passed up a chain of processors
from the Export Service Provider to the Lightroom built-in render engine, and rendered photos are passed
back down again. The sequence is followed for each photo in the list of photos to be exported. This section
explains the sequence of calls, and what information is passed at each point.
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.
The post-process actions are always invoked in the order in which they appear in the dialog, but the export
operation traverses the stack several times, either top-to-bottom (blue arrows), or bottom-to-top (red
arrows). In this discussion, the terms upstream and downstream refer to the downward flow; for example,
when photos that have been rendered by the built-in render engine (using information passed up from
the providers) are passed back down to be modified, and finally exported:
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 51
An upstream provider means the post-process action immediately above the current one in the dialog,
which provides a rendered photo to the current action for further processing. When there are no more
actions, the final upstream provider is Lightrooms built-in rendering engine.
A downstream consumer means the post-process action immediately below the current one in the
dialog, which receives a rendered photo from the current one, its upstream provider. When there are
no more actions, the final downstream consumer is the Export Service Provider that sends the
rendered photo to the final destination.
When the user starts the export operation by clicking Export, Lightroom constructs an LrExportSession
object with the settings and photos chosen in the dialog.
It then calls exportSession:doExportOnCurrentTask(), which performs the following operations. (If
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 updateExportSettings() function, it is called. This function takes one
argument, the export-settings table, and allows the service to force certain render settings to its preferred
or required settings. For example, to force a specific size for the exported photos, you could use this
definition:
updateExportSettings = function( exportSettings )
exportSettings.LR_size_maxHeight = 400
exportSettings.LR_size_maxWidth = 400
end
The filters, if any, are not involved at this stage.
Stage 2: Deciding what photos should be rendered
The filters are invoked from top-to-bottom. For each filter:
If it is defined, the shouldRenderPhoto() function is called for each photo. If it returns false, the photo
is removed from the list of photos to export (and thus does not get passed to the downstream
consumer). If it returns true, the photo remains in the list and is passed to the downstream consumer.
If shouldRenderPhoto() is not defined for the filter, all photos are passed to the downstream
consumer.
Stage 3: Requesting renditions
1. The export session (LrExportSession) generates rendition request objects (LrExportRendition) for
every photo that was not removed in Stage 2. (The actual rendering of the photos does not start yet.)
During this stage, Lightroom can show a dialog message if a photo already exists at the proposed
destination location. You can control this behavior using the LR_collisionHandling setting in the
export settings table.
2. The service's processRenderedPhotos() function is called. If no such function exists, a default one is
provided that performs the steps described below.
CHAPTER 3: Creating Export and Publish Services Adding an export post-process action 52
IMPORTANT: Each of the providers (the export service, filters, and Lightroom's built-in rendering engine)
runs in its own task (using LrTasks), so these loops operate in parallel. It is likely that each provider will be
running simultaneously. Several photos can be in process simultaneously by different providers. This
allows the overall export operation to complete much more quickly than it would if every photo had to go
through all of the steps before the processing of the next photo could begin.
3. The processRenderedPhotos() function calls exportContext:renditions() and then waits for
each rendition to be completed by calling rendition:waitForRender(). (We will discuss the
completion of this loop in Stage 4.)
4. The service's rendition requests are sent to its upstream provider (that is, the bottom-most filter, or if
there are no filters, Lightroom's built-in render engine).
5. For each filter, if a postProcessRenderedPhotos() function is defined, it is called. The function is
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 (LrExportRendition) for each of the
renditions provided this filter.
The renditions() iterator provides two values: sourceRendition (the new rendition to be
satisfied by the upstream provider) and renditionToSatisfy (the corresponding rendition that
this filter is expected to satisfy for its downstream consumer).
ADVANCED: If the filter provider wishes to request a different file format than it is expected to satisfy, it can
do so using the renditionOptions/filterSettings code snippet shown in “Defining post-processing
of rendered photos” on page 48. This might be a good idea as a way to avoid re-encoding (and thus
degrading) JPEG files. If you do this, you are still responsible for providing an output file in the exact format
and location required by renditionToSatisfy.
The filter must wait for each rendition to be completed by its upstream provider by calling
sourceRendition:waitForRender(). (We will discuss the completion of this loop in Stage 4.)
If there is no processRenderedPhotos() function defined by this filter, the filter is simply left out of
the loop and all rendition requests instead go to the upstream provider.
IMPORTANT: Each filter must generate a photo conforming exactly to the specifications provided to it. In
particular, it must provide a suitable photo file in the specified format and at the exact path specified by
the downstream consumer. If it cannot do so, it must use renditionToSatisfy:renditionIsDone(
false, message ) to indicate why not. It must never provide a file of a different format than that
requested.
6. After all of the filters have had an opportunity to intercept the rendition requests, the requests are
finally passed to Lightroom's built-in rendering engine.
Stage 4: Processing rendered photos
As Lightroom completes each rendition request, it signals completion by allowing the corresponding
rendition:waitForRender() call to complete.
The rendering loops described in stage 3 then finish in top-to-bottom sequence for each photo. For each
filter that defines the postProcessRenderedPhotos() function:
CHAPTER 3: Creating Export and Publish Services Final processing of rendered photos 53
1. The waitForRender() call completes, meaning that the upstream provider has completed its attempt
to render the photo. If that attempt was successful, a valid photo file conforming to the specifications
requested by this filter is present at the path specified by the sourceRendition; that is, specified by
this filter when it requested the rendition from its upstream provider.
2. The filter can now do whatever processing it needs to do on that file. This typically means invoking a
third-party application using LrTasks.execute().
ADVANCED: If the filter has changed the file format or location on disk using renditionOptions, it must
now perform the appropriate operations on the file to convert it so that it now satisfies the request as
specified in renditionToSatisfy.
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 filterContext:renditions() iterator if you have not already
done so explicitly. The iterator verifies that a file exists at the expected path and signals success or
failure accordingly. If the file is missing, it uses a generic "an unknown error occurred" message. If you
want to provide a more meaningful message, make an explicit call to renditionIsDone( false,
message ). Typically, you need only call renditionIsDone() on failure.
4. The call to renditionToSatisfy:renditionIsDone() allows the downstream consumer's
waitForRender() call to complete.
5. Meanwhile, the task for this filter continues on and waits for the next rendition.
6. Once all of the filters have finished processing a photo, the waitForRender() call in the services
processRenderedPhotos loop completes. The service does whatever processing it needs to (in this
example, uploading with FTP), and then waits for the next photo to be available.
7. If the "Add to this Catalog" checkbox was selected, Lightroom adds the new photo to the catalog at
this point.
Stage 5: Error reporting and clean up
Once the service’s processRenderedPhotos loop completes, Lightroom takes the following clean-up
actions:
If the photo files were rendered into a temporary folder, Lightroom deletes the folder and its contents.
If the export was triggered through the Export dialog:
Plays the export completion sound, if any.
If any photos failed to export, shows an error dialog that summarizes all of the errors encountered
while exporting.
Creates a temporary "Previous Export" collection with the source photos that were exported.
These behaviors are not available when an export is initiated by calling LrExportSession directly.
Final processing of rendered photos
The processRenderedPhotos() service entry allows you to control what happens to each exported
photo after it is rendered by Lightroom and after all post-process actions have been applied to it. This is
CHAPTER 3: Creating Export and Publish Services Final processing of rendered photos 54
the function that is responsible for transferring the image file to its destination, as defined by your plug-in.
The function that you define is launched within a cooperative task that Lightroom provides. You do not
need to start your own task to run this function; and in general, you should not need to start another task
from within your processing function. (See “Defining function contexts and tasks” on page 20.)
processRenderedPhotos = function( functionContext, exportContext )
...
end,
The parameters functionContext and exportContext are instances of LrFunctionContext and
LrExportContext respectively, which Lightroom creates and passes to your function.
Use the function-context object to define cleanup handlers for this call.
Use the export-context object to gain access to the setting chosen by the user (in
exportContext.propertyTable), and the list of photos to be exported.
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 > 1 and
LOC( "$$$/Flickr/Publish/Progress=Publishing ^1 photos to Flickr", nPhotos )
or LOC "$$$/Flickr/Publish/Progress/One=Publishing one photo to Flickr",
}
The function that you define typically contains a loop of this form:
for i, rendition in exportContext:renditions() do
-- Wait until Lightroom has finished rendering this photo.
local success, pathOrMessage = rendition:waitForRender()
-- Do something with the rendered photo.
if success then
-- when success is true, pathOrMessage contains path of rendered file
local uploadStatus, uploadMessage = uploadToSomewhere( pathOrMessage )
if not uploadStatus then
rendition:uploadFailed( uploadMessage )
end
else
-- Report waitForRender failure
rendition:uploadFailed( pathOrMessage )
end
end
end
Lightroom renders the photos in a separate background thread, so it is likely that your upload
processing will overlap subsequent rendering operations to some extent.
The function exportContext:renditions() automatically updates the progress indicator in the
upper-left corner of the Lightroom catalog window, using a text message that you set by calling
exportContext:configureProgress().
CHAPTER 3: Creating Export and Publish Services Customizing the Export and Publishing Manager dialogs 55
Customizing the Export and Publishing Manager dialogs
Customizing the export destination
After Lightroom has completed the rendering of an individual photo for export, and also completed any
post-processing of that rendered photo by any selected actions, it completes the export operation by
sending the resulting image file to the export-service code, which handles the actual export to the
user-selected destination. By default, Lightroom provides export services for a user-selected location in
the local file system, or the CD/DVD drive.
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 expor t 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; by FTP upload, for example.
A plug-in that includes an Export Service Provider gives the user a further choice of destinations for the
export operation. For example, a plug-in can add a web service such as Flickr as the destination, so that the
export operation uploads the selected files to Flickr, using the settings that the user selects in the rest of
the dialog. When the plug-in is loaded, the user can select the new destination using the up or down arrow
at the right.
If you provide a new export destination, you typically also need to add settings that are meaningful for
your customized export operation. Your plug-in can define customizations for other parts of the Export
dialog, which are shown when the user selects your Export destination.
If your upload operation requires more complex user choices, you can add new sections to the Export
dialog, with the UI elements that the user will need to make those choices. See “Adding custom
sections to the Export or Publishing Manager dialog” on page 56.
The User Presets list at the left can include presets that you define and include with your plug-in, as
well as those defined by Lightroom for export operations; see “Remembering user choices” on
page 59.
CHAPTER 3: Creating Export and Publish Services Customizing the Export and Publishing Manager dialogs 56
Adding custom sections to the Export or Publishing Manager dialog
Your plug-in can define one or more sections to be displayed in the Export or Publishing Manager dialog.
The custom sections can be shown above or below the Lightroom standard sections for the dialog.
To customize the dialog, define a function that returns a table of sections, defined using LrView objects.
The function is the value of one of these service entries:
sectionsForTopOfDialog = function( viewFactory, propertyTable ) ... end,
sectionsForBottomOfDialog = function( viewFactory, propertyTable ) ... end,
NOTE: Similar functions can be defined in a Plug-in Info Provider, to customize the Plug-in Manager
dialog, and in an Export Filter Provider, to add a section to the Export dialog when a post-process
action is selected. See “Adding custom sections to the Plug-in Manager” on page 34 and “Adding an
export post-process action” on page 43.
Lightroom passes your function a factory object which allows you to create the LrView objects that define
the elements of your sections; that is, UI controls, such as buttons and text, and containers that group the
controls and determine the layout. For additional details of the dialog elements you can create with
LrView, see Chapter 5, “Creating a User Interface for Your Plug-in.”
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 ... },
...
}
}
end
A section entry table defines the contents of an implicit container, which Lightroom creates to hold your
view hierarchy.
Each section entry sets a title and synopsis for the section; the section is identified by the title
text on the left, and is collapsible. When in the collapsed state, the synopsis text is shown on the
right:
The rest of the table entry creates the UI elements that are shown when the section is expanded. To
create the UI elements, use the LrView factory passed to your top-level sectionsFor... function.
This process is explained in more detail in Chapter 5, “Creating a User Interface for Your Plug-in.”
When adding sections to the Export dialog, the propertyTable parameter for both functions is the property
table containing the plug-in and Lightroom-defined export settings. When your plug-in is being used as a
publish service provider, the property table contains additional values that tell you about the publishing
status; see “Publish Service properties” on page 70.
You can add your own program data values to this table (see “Remembering user choices” on page 59),
and create bindings between the UI elements and the data values, so that the UI text is dynamically tied to
your plug-in data. This is shown in the example below, and explained more fully in “Binding UI values to
data values” on page 97.
CHAPTER 3: Creating Export and Publish Services Customizing the Export and Publishing Manager dialogs 57
A custom section example
This sample code creates a section in the destination dialog with two UI controls, an editable text field and
a button. These are in a container, a row element which controls the placement of its child nodes, but is not
drawn on the screen.
The value of the edit field is tied to a data key in the property table. The enabled state of the button is also
tied to a data key, so that the button is only enabled when the user types into the edit field, thus setting
the data value.
In this example, the synopsis text is also dynamic, bound to the same data key as the edit field value.
(Currently, you cannot bind the title value.) Notice that for synopsis, you must specify the bound table
explicitly. This is because it is not part of the view hierarchy, where the propertyTable is automatically
assigned as the default bound table.
All of these concepts and techniques are explained more fully and described in more detail in Chapter 5,
“Creating a User Interface for Your Plug-in."
sectionsForTopOfDialog = function( viewFactory, propertyTable )
local LrDialogs = import "LrDialogs" -- get the namespaces we need
local LrView = import "LrView"
local bind = LrView.bind -- a local shortcut for the binding function
propertyTable.user_text = "" -- add program data, no initial value
propertyTable.buttonEnabled = false -- button starts out disabled
return { -- create section entries
{ -- first section entry
title = "Section title",
-- bind the synopsis to a variable for a dynamic description
-- of this section that appears when it is collapsed
synopsis = bind { key = 'user_text', object = propertyTable },
-- create the view hierarchy that appears in the open section
viewFactory:row { -- create root container node
spacing = viewFactory:control_spacing(), -- default spacing
viewFactory:edit_field { -- create edit field
value = bind 'user_text', -- bound to property
immediate = true, -- update value w/every keystroke
validate = function( view, value )
if #value > 0 then -- check length of entered text
-- any input, enable button
propertyTable.buttonEnabled = true
else
-- no input, disable button
propertyTable.buttonEnabled = false
end
return true, value
end
},
CHAPTER 3: Creating Export and Publish Services Customizing the Export and Publishing Manager dialogs 58
viewFactory:push_button { -- create button
enabled = bind 'buttonEnabled',-- enable when property is set
title = "My Button", -- text in button
action = function( button )
LrDialogs.message( "You typed: ", propertyTable.user_text)
end
}
}
}
}
end
This code creates this custom section at the top of the Export dialog (when defined by an
LrExportServiceProvider entry):
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.
A single toggle entry controls whether users can select measurement units:
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. If you provide neither, all default
elements in that category appear.
For example, you can choose which of the built-in sections to display in the dialog. If you use the positive
form, you list the sections to be shown:
showSections = { 'fileNaming', 'imageSettings' },
This causes the File Naming and Image Sizing sections to be visible, and hides all of the other built-in
sections. If you use negative form, you list the sections to be hidden. For example, this hides the Export
Location section, and shows all other built-in sections:
hideSections = { 'exportLocation' },
hidePrintResolution = Boolean When true, the options for sizing in the Image Sizing section
are shown only in pixel units; all mention of print units such as
inches, centimeters, and pixels-per-inch are hidden. Default is
false.
CHAPTER 3: Creating Export and Publish Services Remembering user choices 59
These are the service-table entry pairs for each type of restriction:
Remembering user choices
You typically define properties for your own expor t or publish operation, whose key names, values, and
usage are entirely defined by your plug-in.
Some of these are simply transient or local data (see “Creating observable property tables” on page 100),
but some are intended to be export settings. Export settings (both plug-in-defined and Lightroom-defined)
are persistent properties whose values are saved from one invocation of the Export or Publishing Manager
Restriction Service table entries Allowed values
File formats allowFileFormats = { format’[, ...] },
disallowFileFormats = { format’[, ...] },
These still-photo file formats
are recognized:
JPEG
PSD
TIFF
DNG
ORIGINAL
Video file formats are
determined elsewhere.
Color spaces allowColorSpaces = { colorspace’[, ...] },
disallowColorSpaces = { colorspace’[, ...] },
These color spaces are
recognized:
sRGB
AdobeRGB
ProPhotoRGB
Section display showSections = {’section’[, ...] },
hideSections = { ’section’[, ...] },
These built-in sections are
defined:
exportLocation
fileNaming
fileSettings
imageSettings
outputSharpening
metadata
video
watermarking
When you hide a section, all of the preset values set in that section are excluded
from any presets that the user creates when your plug-in is activated.
If you hide the exportLocation section (the topmost section in the default
dialog), Lightroom renders the photos into a temporary location, then deletes that
directory and its contents after your processRenderedPhotos function
terminates.
NOTE: In the Lightroom 1.3 SDK, there was an additional option, postProcessing,
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.
CHAPTER 3: Creating Export and Publish Services Remembering user choices 60
dialog to the next, and across Lightroom sessions. The most recent settings values are passed to your
initialization function when the plug-in is invoked, to various service-script functions (such as
startDialog, sectionsForTopOfDialog, and so on), and to your plug-ins termination function.
To declare persistent properties and their default values, the service definition script for an export service,
publish service, or post-process action can return this item:
For example:
exportPresetFields = {
{ key = 'privacy', default = 'public' },
{ key = 'privacy_family', default = false },
{ key = 'privacy_friends', default = false },
{ key = 'safety', default = 'safe' },
{ key = 'hideFromPublic', default = false },
{ key = 'type', default = 'photo' },
{ key = 'addTags', default = '' },
}
The settings you declare here are automatically saved along with the export settings already defined by
Lightroom (see “Lightroom built-in property keys” on page 61). The first time your plug-in is activated, the
default value is used to initialize your settings. On the second and subsequent activations, the settings
chosen by the user in previous sessions are restored.
Export presets
For an export service, the user can choose to save a particular configuration of settings values as an export
preset. A preset contains all of the current settings values, including Lightroom-defined fields,
plug-in-defined fields, and post-process action-defined fields. It does not contain any publish-specific
setting that are shown only in the Publishing Manager dialog.
If you wish to create a predefined preset for your export-service plug-in, to be loaded along with your
plug-in and appear in the Lightroom Presets list, you must:
1. Make the value selections in the Export dialog.
2. Use Add to save a User Preset.
exportPresetFields A table of keys and associated default values. These are automatically
stored in both Lightroom preferences and Export presets.
The default values are used only on the first invocation of your plug-in;
after that, the previously set values are restored.
Although export presets are not available for publish-service plug-ins, this
description is used to describe which values from the publish service are
remembered from one invocation to the next of the Publish Manager
dialog.
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 61
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 builtInPresetsDir entry for the
LrExportServiceProvider entry in the Info.lua file for your plug-in.
Settings for publish services and post-process actions
Although you can define persistent setting for a publish service using the exportPresetFields item, and
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. The settings for the Publishing Dialog cannot be loaded
from a preset, they can only be set directly by the plug-in (using defaults or a startDialog callback) or
interactively in the UI.
Similarly, post-process actions cannot have their own presets, but user choices can be remembered if you
add an exportPresetFields entry to the actions info.lua file; see “Defining a post-process action” on
page 47. If the user has chosen to activate the post-process action for a particular export operation, user
choices for that action are captured in any preset created for that export service.
Lightroom built-in property keys
Your export operation makes use of the settings that you have defined for your plug-in (see
“Remembering user choices” on page 59), and can also check any of the Lightroom-defined properties, as
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 62
set in the Export dialog. These are all in the property table passed to your initialization function (see
“Initialization and termination functions for services” on page 40).
The Lightroom built-in keys apply to specific sections of the Export dialog and Library module window, as
follows:
Export Location section properties
File Naming section properties
LR_export_destinationType String. The value of the "Export To:" pop-up. One of:
chooseLater
desktop
documents
home
pictures
sourceFolder
specificFolder
tempFolder
LR_export_destinationPathPrefix String. Destination folder.
LR_export_useSubfolder Boolean. True when the "Put in Subfolder" option is checked,
false when it is unchecked.
Cannot be used if destination type is tempFolder.
LR_export_destinationPathSuffix String. Subfolder name. Valid only if use-subfolder is true.
LR_reimportExportedPhoto Boolean. True when the "Add to This Catalog" option is checked,
false when it is unchecked.
Cannot be used if destination type is tempFolder.
LR_reimport_stackWithOriginal Boolean. True when the "Stack With Original " option is checked,
false when it is unchecked.
This is only meaningful if destination type is sourceFolder and
use-subfolder is false. Ignored otherwise.
LR_collisionHandling String. The value of the "Existing Files:" pop-up. One of:
ask
rename
overwrite
skip
LR_extensionCase String. The case to use for the file extension. One of:
One of
uppercase
lowercase
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 63
Token patterns
This is the complete list of patterns that are allowed in the LR_tokens string, as presented in the pop-up
menu in the File Naming Template dialog:
Image Name and Custom patterns
Sequence and Date patterns
LR_initialSequenceNumber Number. The initial value for the sequence number, when files
are renamed on export using a sequence number.
LR_renamingTokensOn Boolean. When true, the files are renamed on export as
described below.
LR_tokenCustomString String. A naming template to use when files are renamed on
export.
LR_tokens String. A file-naming pattern. The string is used as the file name,
but can contain a pattern within double curly braces which is
replaced by information about the photo being exported. For
example, the string {{image_name}} is replaced by the file
name. See allowed token patterns below.
Pattern Replaced by
{{image_name}} File name
{{image_filename_number_suffix}} File number suffix
{{image_folder}} Folder name
{{image_originalName}} Original file name
{{image_originalName_number_suffix}} Original number suffix
{{copy_name}} Copy name
{{custom_token}} Custom Text (the value of LR_tokenCustomString)
Pattern Replaced by
{{naming_sequenceNumber_1Digit}} Sequence # (1)
{{naming_sequenceNumber_2Digits}} Sequence # (01)
{{naming_sequenceNumber_3Digits}} Sequence # (001)
{{naming_sequenceNumber_4Digits}} Sequence # (0001)
{{naming_sequenceNumber_5Digits}} Sequence # (00001)
{{naming_operationSequence_1Digit}} Image # (1)
{{naming_operationSequence_2Digits}} Image # (01)
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 64
Metadata patterns
{{naming_operationSequence_3Digits}} Image # (001)
{{naming_operationSequence_4Digits}} Image # (0001)
{{naming_operationSequence_5Digits}} Image # (00001)
{{naming_sequenceTotal_1Digit}} Total # (1)
{{naming_sequenceTotal_2Digits}} Total # (01)
{{naming_sequenceTotal_3Digits}} Total # (001)
{{naming_sequenceTotal_4Digits}} Total # (0001)
{{naming_sequenceTotal_5Digits}} Total # (00001)
{{date_LocalEncoding}} Date (Month DD, YYYY)
{{date_YYYYMMDD}} Date (YYYYMMDD)
{{date_YYMMDD}} Date (YYMMDD)
{{date_YYYY}} Date (YYYY)
{{date_YY}} Date (YY)
{{date_Month}} Date (Month)
{{date_Mon}} Date (Mon)
{{date_MM}} Date (MM)
{{date_DD}} Date (DD)
{{date_Julian}} Julian Day of the Year
{{date_Hour}} Hour
{{date_Minute}} Minute
{{date_Second}} Second
Pattern Replaced by
{{com.adobe.title}} Title
{{com.adobe.caption}} Caption
{{com.adobe.copyright}} Copyright
{{com.adobe.keywords}} Keywords
{{com.adobe.creator}} Creator
{{com.adobe.creatorJobTitle}} Creator Job Title
{{com.adobe.creatorAddress}} Creator Address
{{com.adobe.creatorCity}} Creator City
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 65
{{com.adobe.creatorState}} Creator State / Province
{{com.adobe.creatorZip}} Creator Postal Code
{{com.adobe.creatorCountry}} Creator Country
{{com.adobe.creatorWorkPhone}} Creator Phone
{{com.adobe.creatorWorkEmail}} Creator E-Mail
{{com.adobe.creatorWorkWebsite}} Creator Website
{{com.adobe.descriptionWriter}} Description Writer
{{com.adobe.iptcSubjectCode}} IPTC Subject Code
{{com.adobe.intellectualGenre}} Intellectual Genre
{{com.adobe.scene}} Scene
{{com.adobe.location}} Location
{{com.adobe.isoCountryCode}} ISO Country Code
{{com.adobe.headline}} Headline
{{com.adobe.city}} City
{{com.adobe.state}} State / Province
{{com.adobe.country}} Country
{{com.adobe.jobIdentifier}} Job Identifier
{{com.adobe.instructions}} Instructions
{{com.adobe.provider}} Provider
{{com.adobe.source}} Source
{{com.adobe.rightsUsageTerms}} Rights Usage Terms
{{com.adobe.copyrightInfoURL}} Copyright Info URL
{{com.adobe.imageFileDimensions}} Dimensions
{{com.adobe.imageCroppedDimensions}} Cropped
{{com.adobe.exposure}} Exposure
{{com.adobe.focalLength}} Focal Length
{{com.adobe.focalLength35mm}} Focal Length 35mm
{{com.adobe.brightnessValue}} Brightness Value
{{com.adobe.exposureBiasValue}} Exposure Bias
{{com.adobe.subjectDistance}} Subject Distance
{{com.adobe.ISOSpeedRating}} ISO Speed Rating
Pattern Replaced by
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 66
File Settings section properties
{{com.adobe.flash}} Flash
{{com.adobe.exposureProgram}} Exposure Program
{{com.adobe.meteringMode}} Metering Mode
{{com.adobe.make}} Make
{{com.adobe.model}} Model
{{com.adobe.serialNumber}} Serial Number
{{com.adobe.artist}} Artist
{{com.adobe.software}} Software
{{com.adobe.lens}} Lens
{{com.adobe.GPS}} GPS
{{com.adobe.GPSAltitude}} Altitude
{{com.adobe.rating.string}} Rating
{{com.adobe.colorLabels.string}} Label
Pattern Replaced by
LR_format String. File format for still photos. One of:
JPEG
PSD
TIFF
DNG
ORIGINAL
LR_export_colorSpace String. Color space. One of
sRGB
AdobeRGB
ProPhotoRGB
LR_export_bitDepth Number. Bit depth for TIFF or PSD. Ignored for other formats.
One of:
8
16
The following apply only if LR_format = JPEG
LR_jpeg_quality Number. JPEG quality [0..1]. A percentage value where 1 is the
best quality.
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 67
Image Sizing section properties
LR_jpeg_useLimitSize Boolean. True when the “Limit File Size To:” option is checked,
false when it is unchecked.
When true, Lightroom chooses the quality setting that best
matches the desired file size.
LR_jpeg_limitSize Number. When file size is limited, the target size in kilobytes.
The following apply only if LR_format = TIFF
LRtiff_compressionMethod String. TIFF compression method. One of:
compressionMethod_None
compressionMethod_LZW
compressionMethod_ZIP
The following apply only if LR_format = DNG
LR_DNG_previewSize String. JPEG preview size. One of:
none
medium
large
LR_DNG_compatability 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)
LR_DNG_conversionMethod String. Image conversion method. One of:
preserveRAW
convertToLinear
LR_DNG_embedRAW Boolean. True to embed original raw file.
LR_size_doConstrain Boolean. True to constrain maximum size.
LR_size_doNotEnlarge Boolean. True to prevent enlargement of the image size.
LR_size_maxHeight Number. Height constraint in units specified by
LR_size_units.
LR_size_maxWidth Number. Width constraint in units specified by LR_size_units.
LR_size_megapixels Number. When resize type is megapixels, the number of
megapixels.
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 68
Output Sharpening section properties
Metadata section properties
LR_size_resizeType String. The resize method. One of:
wh (width and height)
dimensions
longEdge
shortEdge
megapixels
For the long-edge and short-edge methods, the value is
constrained by LR_size_maxHeight.
LR_size_resolution Number. Resolution, in units specified by
LR_size_resolutionUnits.
LR_size_resolutionUnits String. Resolution units. One of:
inch
cm
LR_size_units String. Size constraint units. One of
inch
cm
pixels
LR_outputSharpeningOn Boolean. True when the "Sharpen For" option is checked, false
when it is unchecked.
LR_outputSharpeningMedia String. The destination media for the sharpening operation.
One of:
screen
matte
glossy
LR_outputSharpeningLevel Number. The amount of sharpening. One of 1 (low), 2 (medium),
or 3 (high).
LR_minimizeEmbeddedMetadata Boolean. True when the "Minimize Embedded Metadata"
option is checked, false when it is unchecked. This property is
superseded by LR_embeddedMetadataOption.
LR_metadata_keywordOptions String. Corresponds to the state of the “Keywords as Lightroom
Hierarchy” checkbox. Value can be lightroomHierarchical
(checked) or flat (unchecked). Ignored when
LR_minimizeEmbeddedMetadata is true.
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 69
Video section properties
Watermarking section properties
Post-Processing Filter section properties
LR_removeLocationMetadata Boolean. True when "Remove Location Info" box is checked,
false when it is unchecked. When true, Lightroom strips all GPS
location metadata from the photo on export.
LR_embeddedMetadataOption String. Corresponds to the state of the “Include” popup menu.
Value can be copyrightOnly, copyrightAndContactOnly,
allExceptCameraInfo, or all.
LR_includeVideoFiles Boolean. True when the "Include Video Files" option is checked,
false when it is unchecked.
When true, export any video files that are selected. When false,
omit those files and show an error message when the export
operation is completed.
Considered only when the plug-in sets canExportVideo =
true in its service description script, to indicate that it can
process video. Otherwise, this is ignored and the
corresponding checkbox is not shown.
NOTE: To dynamically set the format and preset to use for video export, use the method
LrExportSettings.applyVideoExportPreset(). See the API Reference for details.
LR_useWatermark Boolean. True to enable watermarking on export.
LR_watermarking_id When watermarking is enabled, the unique identifier of the
watermark to use. Lightroom assigns this ID when the user
creates a new watermarking preset. You cannot modify it, or
create a watermarking preset programmatically.
LR_exportFiltersFromThisPlugin Table with a key that is the ID of each enabled filter, and a
corresponding value that is the index of that filter in the overall
filter stack. For example:
LR_exportFiltersFromThisPlugin.myFirstFilter.1
LR_exportFiltersFromThisPlugin.mySecondFilter.2
If your plug-in contains multiple filters, this tells you which ones
were selected by the user.
CHAPTER 3: Creating Export and Publish Services Lightroom built-in property keys 70
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.
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
endDialog
sectionsForTopOfDialog
sectionsForBottomOfDialog
LR_cantExportBecause String, optional. If present, describes why an export cannot be initiated.
Appears in the bottom of the dialog near the disabled (dimmed) Export
or Save button. When the error condition is fixed, your plug-in should
set this value to nil. In response to that change, Lightroom enables the
Export or Save button (if no other error conditions exist).
Ignored in versions earlier than 2.0.
LR_publish_connectionName String. The descriptive name of a connection, as
assigned by the user in the Publishing Manager dialog.
LR_isExportForPublish Boolean, read-only. True when the current export
operation is part of a publish service, either currently
running or being edited in the Publishing Manager.
LR_editingExistingPublishConnection Boolean. True when the user is editing an existing
publish service.
LR_publishService LrPublishService. When editing an existing publish
service, the service object.
71
4Working w ith Metadata
A plug-in can define customized metadata fields for photos by declaring a Metadata Provider in the
information file, and defining type and version information for each field. See “Adding custom
metadata” on page 71.
A plug-in can specify metadata tagsets that affect the display of custom metadata fields in the Library
modules Metadata panel. See “Adding custom metadata tagsets” on page 76.
Plug-ins can define complex searches that find photos according to metadata values. See “Searching
for photos by metadata values” on page 78.
Adding custom metadata
Your plug-in can define custom metadata fields for photos that are imported into Lightroom. These fields
can be visible and even editable in Lightroom's Metadata panel, or can be invisible and used to store
private data.
Declaring a Metadata Provider
Like an Export Service or Export Filter Provider, you declare a Metadata Provider in the information file
(Info.lua) for your plug-in. See “Writing standard plug-ins for Lightroom” on page 23.
To declare a Metadata Provider, include an LrMetadataProvider entry in the Info.lua file; for example:
return {
LrSdkVersion = 5.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 “Adding
custom metadata tagsets” on page 76), export services and/or filters, but need not do so.
Limitations of custom metadata in this release
In the current implementation, custom metadata defined by a plug-in has these limitations, which will be
addressed in future versions of the Lightroom SDK:
Values stored in custom metadata fields are stored only in Lightroom's database. In the current
release, a plug-in cannot link custom metadata fields to XMP values or save them with the image file.
A plug-in cannot specify complex data types. You can define simple fields per photo, but you cannot
define a whole spreadsheet per photo.
CHAPTER 4: Working with Metadata Adding custom metadata 72
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 table Required. Defines new data fields to be stored for
each photo.
The table is an array of field definitions. Each entry
in the metadataFieldsForPhotos array describes a
single field which can be associated with photos in
the catalog. Each field can hold only one value per
photo.
See “Metadata field entries” on page 73.
schemaVersion number Required. Allows for versioning of the property
definition schema. Typically this number starts at 1
and you increment it whenever you release a new
version of the schema or need to run the update
function.
updateFromEarlierSchemaVersion function Optional. Allows your plug-in to update data when
a new schema version is in place.
The function takes three parameters; catalog,
previousSchemaVersion, and progressScope.
When the plug-in is first installed,
previousSchemaVersion is nil.
See example below.
noAutoUpdate Boolean Optional. When false (the default), Lightroom
attempts to automatically update metadata from
old field definitions to new. If you prefer to handle
this in your own plug-in (using the
updateFromEarlierSchemaVersion callback), set
this to true.
CHAPTER 4: Working with Metadata Adding custom metadata 73
Metadata field entries
Each of the entries in the metadataFieldsForPhotos array is a table that describes one metadata field;
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:
id string Required. A unique identifier that allows a plug-in to access this field. The
name must conform to the same naming conventions as Lua variables; that is,
it must start with a letter, followed by letters or numbers, case is significant.
version number Optional. If present, defines a version number specifically for this field, distinct
from the version number defined by schemaVersion in the outer metadata
definition script.
If you make a change to a field definition that is incompatible with the
previous definition (for example, changing the value of searchable), you
must bump the field's version number. A migration script can search for
photos that contain the old version of the field and manually migrate values.
title string Optional. If this field is displayed in the Metadata panel, this is the localizable
display name. This name should be relatively short, since space in the
Metadata panel is at a premium. A name longer than about 100 pixels is likely
to be truncated on display; however, the full text is shown in the tooltip when
the cursor hovers over the name.
If this item is omitted, the field does not appear in the Metadata panel. This
can be useful for storing private, per-image plug-in information, such as the
images ID at an on-line service that is the export destination, or other
cross-reference information.
dataType string Optional. If this field is present, Lightroom disallows any other data type from
being stored in this field. Nil is always permitted. You cannot require that a
field have a value.
The value is one of these strings:
string — The field value must have a string value.
enum — The field value must have one of the allowed values specified in
the values entry. In the Metadata panel, allowed values are shown as a
pop-up menu for the field.
url — The field value must have a string value. In the Metadata panel, the
text field is acccompanied by a button that treats the text value as a URL,
opening it in the user’s preferred web browser.
CHAPTER 4: Working with Metadata Adding custom metadata 74
Custom metadata example
This sample Metadata Provider script defines three metadata fields of representative types.
return {
metadataFieldsForPhotos = {
{
id = 'siteId',
-- This field is not available in the metadata browser because
-- it does not have a title field. You might use a field like this
-- to store a photo ID from an external database or web service.
},
{
id = 'randomString',
title = LOC "$$$/Sample/Fields/RandomString=Random String",
dataType = 'string', -- Specifies the data type for this field.
},
{
id = 'modelRelease',
title = LOC "$$$/Sample/Fields/ModelRelease=Model Release",
dataType = 'enum',
values = {
{
value = nil,
values table Required when dataType = "enum", otherwise disallowed. An array of allowed
values. Each entry in the array is a table that must contain a value and a title.
The title is shown in the popup menu; the corresponding value (which must
be a string, number, or Boolean, or nil) is written to the database. The values
table can have only one entry where value = nil. If such an entry is present,
the corresponding label is used when no value has been assigned to this
property for a photo.
The values table can also have an entry allowPluginToSetOtherValues =
true.
If present, your plug-in can store values outside of the enumerated values
in this field.
If not, an attempt to set such a value triggers a Lua error and does not
change the value stored in the database.
readOnly Boolean Optional. Use only when title is provided. When true, the field is visible in the
Metadata panel, but not editable by the user. The value can still be set
programmatically, using LrPhoto:setPropertyForPlugin().
searchable Boolean Optional. Use only when title is provided. When true, this field is stored in a
separate table and indexed for faster searching; this also means that the field
can be chosen by a user as a search criterion for smart collections. Strings
stored in this field must not exceed 511 bytes. Default is false.
browsable Boolean Optional. Use only when title is provided and searchable is true. When
true, this field can be used as a filter in the Library metadata browser.
CHAPTER 4: Working with Metadata Adding custom metadata 75
title = LOC "$$$/Sample/Fields/ModelRelease/NotSure=Not Sure",
},
{
value = 'yes',
title = LOC "$$$/Sample/Fields/ModelRelease/Yes=Yes",
},
{
value = 'no',
title = LOC "$$$/Sample/Fields/ModelRelease/No=No",
},
-- optional: allowPluginToSetOtherValues = true,
},
},
},
schemaVersion = 1,
-- must be a number, preferably a positive integer
updateFromEarlierSchemaVersion = function( catalog, previousSchemaVersion,
progressScope )
-- When the plug-in is first installed, previousSchemaVersion is nil.
-- As of Lightroom version 3.0, a progress-scope variable is available; you can
-- use it to signal progress for your upgrader function.
-- 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
for i, photo in ipairs( photosToMigrate ) do
local oldSiteId = photo:getPropertyForPlugin( myPluginId, 'siteId' )
-- add property version here if used above
local newSiteId = "new:" .. oldSiteId
-- replace this with whatever data transformation you need to do
photo:setPropertyForPlugin( _PLUGIN, 'siteId', newSiteId )
end
elseif previousSchemaVersion == 2 then
-- and so on...
end
end,
}
This is how these fields appear in the Metadata panel, when the user has chosen a metadata tagset that
contains them, or one of the default metadata tagsets “All” or All Plug-in Metadata” (see “Adding custom
metadata tagsets” on page 76). The user-visible custom fields from plug-ins are shown after all of the
built-in metadata fields.
CHAPTER 4: Working with Metadata Adding custom metadata tagsets 76
Notice that the field "siteId" does not appear in the panel because no title is defined for it; it is an
invisible field, internal to the plug-in.
The field "randomString" appears with the localized title value, "Random String", as the display label.
Because it is a plain string value, it appears as an editable text field.
The field "modelRelease" also appears with the title value, "Model Release", as the display label.
Because it is an enumerated value, clicking it pops up a menu of the allowed values, each shown using
its own localized title value as the display string.
Adding custom metadata tagsets
The drop-down menu at the top left of the Metadata panel allows users to filter what is shown in the
panel, by selecting a metadata tagset to be displayed. A metadata tagset is a predefined set of metadata
fields. When you select a tagset, the Metadata panel displays only the fields included in that set.
There are predefined tagsets, and you can also create your own. Your plug-in can define a named
metadata tagset, which can include fields defined by your plug-in, by other plug-ins, or by Lightroom.
This is the Info.lua file for a minimal plug-in that defines a tagset:
return {
LrSdkVersion = 5.0,
LrToolkitIdentifier = 'com.adobe.lightroom.metadata.sample',
LrPluginName = LOC "$$$/CustomMetadata/PluginName=Metadata Sample",
LrMetadataTagsetFactory = 'SampleTagset.lua',
}
CHAPTER 4: Working with Metadata Adding custom metadata tagsets 77
The metadata-tagset provider can appear in the same plug-in with export-service and export-filter
providers, and with simple Metadata Providers.
The metadata-tagset provider is a Lua file that returns a tagset definition. You can use the
LrMetadataTagsetFactory entry to specify more than one such file in a single plug-in. For example:
LrMetadataTagsetFactory = { 'Tagset1.lua', 'Tagset2.lua', 'Tagset3.lua' },
Defining a metadata tagset
Each tagset definition file must return a table listing the fields that should appear in the Metadata panel
when that tagset is selected. The file can return an array of such tables to define multiple tagsets.
The table contains these entries:
Each entry in the items array identifies a field to be included in the Metadata menu. It can be a simple
string specifying the field name, or an array that specifies the field name and additional information about
that field:
Certain special values are defined for field names. See the API Reference documentation for metadata
plug-in-defined functions, and the metadata sample plug-in.
You can include all visible metadata from a plug-in by specifying the field name with the wild-card
character "*"; for example, "com.mycompany.uploader.*". The visible fields are included in the
sequence in which they are defined in the definition script. The fields for each plug-in are preceded by
a dividing line and the plug-ins name.
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". T h i s is t h e fi e l d n a m e us e d b y the built-in "All Plug-in Metadata"
preset.
The special name 'com.adobe.separator' inserts a dividing line in the Metadata panel before the first
field from this plug-in.
id string Required. An identifier for this tagset that is unique within this plug-in. The
name must conform to the same naming conventions as Lua variables; that is,
it must start with a letter, followed by letters or numbers. Case is significant.
title string Required. The localizable display name of the tagset, which appears in the
popup menu for the Metadata panel.
items table Required. An array of metadata fields that appear in this tagset, in order of
appearance.
fieldname string The first element in the array is the unique identifying name of the field,
or one of the special values described below.
label string Optional. When the field name is the special value 'com.adobe.label',
this is the localizable string to use as the section label.
CHAPTER 4: Working with Metadata Searching for photos by metadata values 78
The special name 'com.adobe.label' inserts a section label in the Metadata panel, specified by a
label entry in an array with this name. A label is typically used below a separator.
Custom metadata tagset example
This sample metadata-tagset provider script defines a set of metadata fields.
return {
title = 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',
},
}
Searching for photos by metadata values
The LrCatalog object provides a function, findPhotos(), that allows you to search through the catalog
for photos with particular metadata values. You pass this function a search descriptor to define the search,
which is a table containing a metadata field (the search criteria), a matching operation (which depends on
the datatype of the field), and a value to match against.
This function must be used within a background task. For example:
import "LrTasks".startAsyncTask( function()
local catalog = import "LrApplication".activeCatalog()
local photos = catalog:findPhotos {
searchDesc = {
criteria = "rating",
operation = ">",
value = 3,
CHAPTER 4: Working with Metadata Searching for photos by metadata values 79
},
}
for _, photo in ipairs( photos ) do
-- do somethingwith path
end
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 criteria correspond to choices in the Edit Smart Collection dialog:
rating (number)
pick (enum) Value must be one of: 1 (flagged), 0 (unflagged), -1 (rejected)
labelColor (enum) Value must be one of: 1 (red), 2 (yellow), 3 (green), 4 (blue), 5 (purple),
"custom" (any label not currently assigned to a color), "none"
labelText (string, can be empty) User-assigned name of color label
folder (string) Name of folder, including all parent folders shown in the Folders panel
collection (string) Name of any collection containing this photo
all (string) Any searchable text
filename (string)
copyname (string, can be empty) Copy Name assigned in Metadata panel
fileFormat (enum) Value must be one of: "DNG", "RAW", "JPG", "TIFF", "PSD"
metadata (string) Any searchable metadata
title (string, can be empty)
caption (string, can be empty)
keywords (string, plural, can be empty)
iptc (string) Any IPTC metadata; that is, any text in a field that is indexed by Lightroom.
exif (string) Any EXIF metadata; that is, any text in a field that is indexed by Lightroom.
captureTime (date)
touchTime (date) Edit Date
camera (string, with exact match)
cameraSN (string, with exact match) Camera Serial Number
lens (string, with exact match)
isoSpeedRating (number)
hasGPSData (Boolean)
CHAPTER 4: Working with Metadata Searching for photos by metadata values 80
You can search plug-in defined fields, using these special criteria values:
operation The allowed values for operation depend on value type of the criteria field, and also correspond to
selectable values the Edit Smart Collections dialog.
For string values, one of:
country (string, with exact match)
state (string, with exact match)
city (string, with exact match)
location (string, with exact match)
creator (string, with exact match)
jobIdentifier (string, with exact match)
copyrightState (enum) Value must be one of: true (Boolean, copyrighted), false (Boolean, public
domain), "unknown"
hasAdjustments (Boolean)
developPreset (enum) Value must be one of: "default", "specified", "custom"
treatment (enum) Value must be one of: "grayscale", "color"
cropped (Boolean)
aspectRatio (enum) Value must be one of: "portrait", "landscape", "square"
"allPluginMetadata" Any searchable plug-in-defined metadata.
sdktext:plugin_id.field_name A specific, searchable, plug-in-defined field (with datatype text
or enum).
sdktext:plugin_id.* All searchable fields defined by a specific plug-in (with datatype
text or enum).
any "contains"
all "contains all"
words "contains words"
noneOf "does not contain"
beginsWith "starts with"
endsWith "ends with"
empty "are empty", only valid for items that can be empty,
notEmpty "are not empty", only valid for items that can be empty,
CHAPTER 4: Working with Metadata Searching for photos by metadata values 81
For Boolean values, one of "isTrue", " isFalse"
For enumerated values, one of == (is), != (is not)
For number and rating values, one of:
For date values, one of:
== "is", only valid for items that can have an exact match,
!= "is not", only valid for items that can have an exact match
== "is"
!= "is not"
>is greater than"
<"is less than"
>= "is greater than or equal to"
<= "is less than or equal to"
in "is in range"
End value of range specified in value2 parameter.
== "is"
!= "is not"
>"is after"
<"is before"
inLast
notInLast
"is in the last"
"is not in the last"
With unit specified in value_unit parameter, one of:
hours
days
weeks
months
years
in "is in the range"
End value of range specified in value2 parameter.
today "is today"
yesterday "is yesterday"
thisWeek "is in this week"
CHAPTER 4: Working with Metadata Searching for photos by metadata values 82
value The value to match against must be of the type indicated for the criteria. Additional parameters value2
and value_unit are used with specific types and operations, as mentioned above.
Combining search criteria
You can create a more complex search descriptor by using a combine entry to specify how to combine the
results of several criterion tables:
import "LrTasks".startAsyncTask( function()
local catalog = import "LrApplication".activeCatalog()
local photos = catalog:findPhotos {
searchDesc = {
combine = "intersect",
{
criteria = "rating",
operation = ">",
value = 3,
},
{
criteria = "captureDate",
operation = ">",
value = "2007-01-01",
}
},
}
for _, photo in ipairs( photos ) do
-- do something with path
end
end )
There are three ways to combine criteria:
A combine entry is followed by an array of elements to be combined. This array can contain nested
combine entries, so the search can become quite complex. For example:
{
combine = "union",
{
combine = "intersect",
{
criteria = "rating",
thisMonth "is in this month"
thisYear "is in this year"
combine = "union" Any of the criteria match.
combine = "intersect" All of the criteria match.
combine = "exclude" None of the criteria match.
CHAPTER 4: Working with Metadata Searching for photos by metadata values 83
operation = ">=",
value = 1,
},
{
criteria = "labelColor",
operation = "==",
value = 1,
},
},
{
criteria = "rating",
operation = "==",
value = 5,
},
}
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. Construct the search as a Smart Collection in Lightroom:
2. Right click the resulting collection in the Collections panel and choose “Export Smart Collection
Settings.
3. Open the resulting .lrsmcol file in a text editor.
4. Select and copy the value entry:
CHAPTER 4: Working with Metadata Searching for photos by metadata values 84
5. Edit the resulting code to change value to searchDesc, and include it in your call to findPhotos().
6. Make any other appropriate changes in the code. In this example, for instance, you would not need
the combine element. If you remove it, you can also promote the parameter table to the top level in
searchDesc:
searchDesc = {
criteria = "captureTime",
operation = ">",
value = "2008-02-12",
}
85
5Creating 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. You define the UI elements of a custom
section using LrView objects; see “Adding custom dialog views” on page 85.
You can call the functions of the LrDialog namespace to display messages, prompts, and errors to
users in predefined dialogs. See “Displaying predefined dialog boxes” on page 86.
You can use the functions in the LrDialog and LrView namespaces to create your own dialog boxes.
You can display them when users choose your custom menu items, invoke them from tasks, or invoke
them in response to selections in controls you have added to the Export dialog. See “Creating custom
dialog boxes” on page 87.
The LrView class models a node tree, where each node is a UI element, represented by a specific type of
LrView object. A node can be a container or parent of other nodes, or a control, an individual UI element
such as a checkbox, which displays a value and can allow user input. Containers and controls are arranged
in a node tree, or view hierarchy. A view hierarchy has a top-level container node, additional child
containers if needed, and leaf nodes that are the controls.
The LrView namespace and class provides a set of interface elements, with functionality to lay out and
localize the display, and a binding mechanism that lets you tie the displayed values to your plug-in data
and settings.
“User interface elements” on page 87 introduces the UI elements you can create with LrView.
“Binding UI values to data values” on page 97 explains the binding mechanism, with examples of how
to create various relationships between your data and your display.
“Determining layout” on page 110 explains the placement options and gives examples of various
layout techniques.
Adding custom dialog views
You can create custom sections to be displayed in the Plug-in Manager or Export dialog using these
service-script entries:
sectionsForTopOfDialog = function( viewFactory, propertyTable ) ... end,
sectionsForBottomOfDialog = function( viewFactory, propertyTable ) ... end,
The function that you define here is slightly different for the two dialogs; see “Adding custom sections
to the Plug-in Manager” on page 34 and “Adding custom sections to the Export or Publishing
Manager dialog” on page 56.
For an Export Filter Provider, a very similar function, sectionForFilterInDialog, creates only one
section, rather than multiple sections. See “Defining a post-process action” on page 47.
In any case, however, the function must define the UI to be displayed when each dialog-box section is
expanded. To do so, use the viewFactory object to construct all of the elements of a view hierarchy.
CHAPTER 5: Creating a User Interface for Your Plug-in Using dialog boxes 86
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