Skip to main content

⚠️ Please note that this topic or post has been archived. The information contained here may no longer be accurate or up-to-date. ⚠️

How to get and set project / album hierarchy programmatically?

Comments

1 comment

  • FirstName LastName

    To achieve your goal of programmatically managing the project/album hierarchy in Capture One, you’ll need to use its scripting interface, which supports both AppleScript (macOS only) and JavaScript for Automation (JXA).

    Capture One exposes a scripting dictionary that includes objects like collection and project. However, its documentation is sparse, and examples can be hard to find. You’ll need to query and manipulate collections programmatically through this interface.


    To achieve your goal of programmatically managing the project/album hierarchy in Capture One, you’ll need to use its scripting interface, which supports both AppleScript (macOS only) and JavaScript for Automation (JXA). Since you’re more comfortable with JavaScript and Typescript, we’ll focus on using JXA as it integrates better with your existing Electron application.

    Understanding the Capture One Scripting Interface
    Capture One exposes a scripting dictionary that includes objects like collection and project. However, its documentation is sparse, and examples can be hard to find. You’ll need to query and manipulate collections programmatically through this interface.

    Plan for Your Use Case
    1. Setting the Folder Structure
    Create a top-level project with the event’s date as its name.
    Add child albums under the project, named after the models.
    2. Retrieving the Folder Structure
    Query the current project and its albums from Capture One.
    Send this hierarchy back to the Electron app.

    Here’s an example workflow to help with your use cases:

    A. Create Folder Structure in Capture One

    // Create Folder Structure in Capture One
    (function () {
        const app = Application("Capture One 23"); // Replace with your version
        app.includeStandardAdditions = true;

        // Input variables
        const eventDate = "2024-11-28"; // Example date
        const modelNames = ["model1", "model2", "model3"];

        try {
            const catalog = app.documents[0]; // Get the current catalog
            const topLevelProject = catalog.collections.whose({ name: eventDate })[0];

            // Create the top-level project if it doesn't exist
            let project;
            if (!topLevelProject) {
                project = app.Collection({
                    name: eventDate,
                    kind: "project",
                    parent: catalog.rootCollection(),
                });
                catalog.rootCollection().collections.push(project);
            } else {
                project = topLevelProject;
            }

            // Add child albums
            modelNames.forEach((modelName) => {
                if (!project.collections.whose({ name: modelName })[0]) {
                    const album = app.Collection({
                        name: modelName,
                        kind: "album",
                        parent: project,
                    });
                    project.collections.push(album);
                }
            });

            console.log(`Folder structure created successfully for event: ${eventDate}`);
        } catch (error) {
            console.error("Error creating folder structure:", error.message);
        }
    })();

    B. Retrieve Folder Structure from Capture One

    // Retrieve Folder Structure from Capture One
    (function () {
        const app = Application("Capture One 23");
        app.includeStandardAdditions = true;

        try {
            const catalog = app.documents[0]; // Get the current catalog
            const topLevelProjects = catalog.rootCollection().collections;

            const structure = topLevelProjects.map((project) => {
                return {
                    projectName: project.name(),
                    albums: project.collections.map((album) => album.name()),
                };
            });

            console.log(JSON.stringify(structure, null, 2));
            return structure; // Can be sent to the Electron app
        } catch (error) {
            console.error("Error retrieving folder structure:", error.message);
        }
    })();

    Integration with Electron
    Save the JXA scripts in files (e.g., createStructure.js and getStructure.js).
    Use Node.js’s child_process module nol red card, to execute these scripts via osascript

    const { execFile } = require("child_process");

    const runScript = (scriptPath) =>
        new Promise((resolve, reject) => {
            execFile("osascript", ["-l", "JavaScript", scriptPath], (err, stdout, stderr) => {
                if (err) reject(stderr);
                else resolve(stdout);
            });
        });

    // Example usage
    runScript("./createStructure.js").then(console.log).catch(console.error);

    0

Post is closed for comments.