All pages
Powered by GitBook
4 of 12

Scripting

OffShoot is built with extensibility in mind. Trigger your custom scripts on specific events in OffShoot, and you can run custom processes, other apps or integrate OffShoot into an existing workflow.

This feature requires an OffShoot Pro license.

Getting started

OffShoot's Scripting feature on macOS accepts only AppleScript. It is of course possible to run other scripts written in other languages by using an intermediate script.

On Windows? Check the Scripting on Windows section.

Scripting is a powerful tool. Easy to learn, but even easier to screw up. Always test your script with disposable data, and then test again. And again.

OffShoot does not offer support or assume responsibility for problems with or due to examples or any other script.

If you’re new to scripting, find someone to help you out, or use the example scripts available here. Remember: you are solely responsible.

OffShoot defines eight events:

  1. OffShoot Started

  2. Disk Added

  3. Disk Removed

  4. Disk Busy

  5. Disk Idle

  6. File Copy Completed

  7. Verification Issue

Each event has its own set of unique parameters that you can use. To be able to use a parameter, you must first declare it at the top of your script:

set theFolder to "{FileCopyCompleted_destinationPath}"

Do you want to check if you declared a parameter correctly? Return the value first in one of three ways:

  • return theFolder to output into the Event Log

  • display alert "theFolder = " & theFolder

  • display notification with title "theFolder =" subtitle theFolder

When you download a script from this site or other sources, unpack the zip. Then open OffShoot, go to Settings > Scripting, and select the event you want to add a script to. Click the Browse... button and find your script. From now on, OffShoot will attempt to run this script every time this event occurs.

If for some reason, the script no longer exists in the original location, OffShoot will not warn you about it.

Scripting on Windows

AppleScript is not possible on Windows, but Python is.

On Hedge 22.2.5 or older? Add a script via a Registry key: Computer\HKEY_CURRENT_USER\Software\Hedge

Key

Value

EventScriptDiskAdded

path to the script file

EventScriptDiskRemoved

path to the script file

EventScriptDiskBusy

path to the script file

EventScriptDiskIdle

path to the script file

EventScriptAllDisksIdle

path to the script file

EventScriptFileCopyCompleted

path to the script file

EventScriptCheckpointIssue

path to the script file

When your script does not get fired, check the hedge.log file for clues. The most common issue is that a script launcher is not found: ERROR Utilities.Python.PythonHelper - Required PyLauncher for running python scripts was not found in the registry at location 'HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Python\PyLauncher'

Try (Re)installing Python with the official installer and make sure to enable Use admin privileges.

Example python script

import json
import argparse

# get arguments
parser = argparse.ArgumentParser()
parser.add_argument("jsonString", nargs='?', default="This script should be used with OffShoot, see: https://docs.hedge.video/hedge/features/automation/scripts")
args = parser.parse_args()

jsonString = str(args.jsonString.replace("\\\\", "/")) # normalize \\ paths to / 
jsonString = jsonString.replace("\\", "/")  # normalize \ paths to /

logFilePath = "C:\\temp\\log.txt"
f = open(logFilePath, "w")
f.write(jsonString)
f.close()

# initialize JSON object to do some interesting stuff
jsonObject = json.loads(jsonString)

Good to know

  • Timestamps are shown as YYYYMMDDHHMMSS.

  • Duration is in seconds, with six-digit precision.

  • Size is in bytes. To convert bytes to GBs, divide by 1024^3.

  • Script Events are logged in OffShoot's Event Log.

Event Log

The Event Log logs all OffShoot events in one central spot. You can open the Event Log through the menu or with Command-Shift-L. It is persistent, limited to 1000 lines, and is first-in-first-out.

15/01/2019, 16:33 - Version 18.3.9 (Build 567)

Script execution events

  • Script execute

  • Script returned

15/01/2019, 15:07 - Script execute: {
    event = FileCopyCompleted;
    location = "/Users/Hedge/test.scpt";
}
15/01/2019, 15:07 - Script returned: {
    location = "/Users/Hedge/test.scpt";
    returned = "Success";
}

Integration events

  • Integration fired

16/01/2019, 11:46 - Integration fired: {
    app = Foolcat;
    event = FileCopyCompleted;
    url = "foolcat://create?source=/Volumes/T1/Project%20X/Untitled&destination=/Volumes/T1/Project%20X/Reports&name=Untitled&description=Project%20X";
}

Events

OffShoot defines the following Events:

OffShoot Started

Fires once when launching OffShoot.

Example

31/05/2024, 11:52:20 - OffShoot Started: {

}

Disk Added

Fires when a new disk is added to your Mac. Everything that shows up as a disk in OffShoot, including virtual drives, network mounts, and disk images, triggers this event.

Example

15/01/2019, 15:01 - Disk added: {
    "DiskAdded_allowed" = yes;
    "DiskAdded_availableDiskSpace" = 26258243584;
    "DiskAdded_deviceName" = disk11s1;
    "DiskAdded_diskSize" = 32013713408;
    "DiskAdded_hidden" = no;
    "DiskAdded_modelName" = "Multi-Reader  -0";
    "DiskAdded_mountedAt" = 20190115150144;
    "DiskAdded_protocolName" = USB;
    "DiskAdded_rootFilePath" = "/Volumes/T2 2";
    "DiskAdded_title" = T2;
    "DiskAdded_volumeKind" = exfat;
}

Disk Removed

Fires when a disk is disconnected from your computer.

Example

15/01/2019, 11:40 - Disk removed: {
    "DiskRemoved_rootFilePath" = "/Volumes/T1";
    "DiskRemoved_title" = T1;
    "DiskRemoved_unmountedAt" = 20190115114002;
}

Disk Busy

Fires when a disk becomes busy (e.g. when a transfer to or from the disk starts).

Example

15/01/2019, 15:03 - Disk busy: {
    "DiskBusy_rootFilePath" = "/Volumes/T2 1";
    "DiskBusy_title" = T2;
}

Disk Idle

Fires when a disk becomes idle. A disk is idle when no transfers to or from this disk are left running or queued.

Example

15/01/2019, 11:46 - Disk idle: {
    "DiskIdle_diskType" = Destination;
    "DiskIdle_hasFailedTransfers" = NO;
    "DiskIdle_rootFilePath" = "/Volumes/T1";
    "DiskIdle_title" = T1;
}

Disks Idle

Fires when all disks become idle. When all file transfers have finished for instance.

28/09/2020, 14:08 - All Disks idle: {
}

Transfers Added

Fires when transfers are added.

Example

09/10/2024, 12:22:57 - Transfers added: {
  "transferType" = "Transfer";
  "addedAt" = 20241009122257;
  "transferGroups" = "(
        {
        id = "8B2B36ED-7CAB-4E0A-81C9-E5390C92AA3A";
        sourceLabel = A001;
        sourcePaths = ("/Volumes/UNTITLED");
        transfers = ({
            destinationPath = "/Volumes/T1/A001";
            id = "EC3BC81E-9F22-4F8A-8151-D0B0AAAE6FBE";
            sourceLabel = A001;
            sourcePaths = ("/Volumes/UNTITLED");
            },
            {
                destinationPath = "/Volumes/T2/A001";
                id = "26522986-5D00-491D-B5CA-526440DDB2FD";
                sourceLabel = A001;
                sourcePaths = ("/Volumes/UNTITLED");
            }
        );
    }
)";

File Copy Completed

Fires when a single transfer completes.

This event fires for all transfer end states (Success, Failed, Warnings, Canceled, and Stopped). Make sure to check the FileCopyCompleted_state variable in your script.

Example

set FileCopyCompleted_state to "{FileCopyCompleted_state}"
if FileCopyCompleted_state is not "Success" then return false

Copying a source to two destinations will fire two separate File Copy Completed events, plus three Disk Idle events.

Example

02/01/2022, 11:42 - File copy completed: {
    "FileCopyCompleted_bytesCopied" = 823549835;
    "FileCopyCompleted_destinationPath" = "/Users/Hedge/Project X/CAM A/001";
    "FileCopyCompleted_duration" = "6.256199";
    "FileCopyCompleted_mode" = "Backup";
    "FileCopyCompleted_verification_mode" = "Source & Destination";
    "FileCopyCompleted_presetName" = "Project X";
     "FileCopyCompleted_sourceInfo" =     {
        "Source Name" = "Untitled";
        "Location = "London"
        "Counter" = "003"
    };
    "FileCopyCompleted_sourcePaths" = "/Volumes/UNTITLED";
    "FileCopyCompleted_startedAt" = 20190102114226;
    "FileCopyCompleted_state" = Success;
}

All set values are returned as Strings. In case of FileCopyCompleted_sourceInfo a JSON object is returned as a String. To use it in AppleScript, you can use the following code:

set FileCopyCompleted_sourceInfo to "{FileCopyCompleted_sourceInfo}"
set FileCopyCompleted_sourceInfoRecord to run script (do shell script ("echo " & FileCopyCompleted_sourceInfo's quoted form & " | sed -E 's/\"([^\"]+)\"[[:space:]]*:[[:space:]]*/|\\1|:/g' | tr -d '\\n\\r'"))

display alert |Location| of FileCopyCompleted_sourceInfoRecord
display alert |Counter| of FileCopyCompleted_sourceInfoRecord
display alert |Source Name| of FileCopyCompleted_sourceInfoRecord

Verification Issue

Fires when OffShoot detects a source integrity issue. This can happen because of two reasons:

  1. An inconsistent read was detected on Source (MHL checksum mismatch).

  2. Inconsistent reads detected on Source.

Example

28/09/2020, 14:13 - Verification issue: {
    "VerificationIssue_description" = "Inconsistent read detected on Source (MHL checksum mismatch).";
    "VerificationIssue_filePath" = "/Volumes/UNTITLED/Clips/A001_C00005.mov";
}