premiere-cli 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- premiere_cli/__init__.py +11 -0
- premiere_cli/cli.py +3664 -0
- premiere_cli/log.py +66 -0
- premiere_cli/panel/.debug +8 -0
- premiere_cli/panel/CSXS/manifest.xml +52 -0
- premiere_cli/panel/css/style.css +53 -0
- premiere_cli/panel/host/commands/add-adjustment-layer.jsx +190 -0
- premiere_cli/panel/host/commands/add-audio-keyframes.jsx +176 -0
- premiere_cli/panel/host/commands/add-custom-metadata-field.jsx +63 -0
- premiere_cli/panel/host/commands/add-keyframe.jsx +181 -0
- premiere_cli/panel/host/commands/add-marker-to-project-item.jsx +194 -0
- premiere_cli/panel/host/commands/add-marker.jsx +129 -0
- premiere_cli/panel/host/commands/add-text-overlay.jsx +101 -0
- premiere_cli/panel/host/commands/add-to-render-queue.jsx +120 -0
- premiere_cli/panel/host/commands/add-to-timeline.jsx +300 -0
- premiere_cli/panel/host/commands/add-track.jsx +188 -0
- premiere_cli/panel/host/commands/add-transition.jsx +134 -0
- premiere_cli/panel/host/commands/adjust-audio-levels.jsx +132 -0
- premiere_cli/panel/host/commands/apply-audio-effect.jsx +118 -0
- premiere_cli/panel/host/commands/apply-effect.jsx +122 -0
- premiere_cli/panel/host/commands/apply-lut.jsx +107 -0
- premiere_cli/panel/host/commands/attach-custom-property.jsx +66 -0
- premiere_cli/panel/host/commands/auto-reframe-sequence.jsx +124 -0
- premiere_cli/panel/host/commands/batch-add-transitions.jsx +158 -0
- premiere_cli/panel/host/commands/batch-apply-effect.jsx +182 -0
- premiere_cli/panel/host/commands/batch-rename-clips.jsx +170 -0
- premiere_cli/panel/host/commands/batch-set-clips-enabled.jsx +145 -0
- premiere_cli/panel/host/commands/clear-item-in-out.jsx +117 -0
- premiere_cli/panel/host/commands/clear-sequence-in-out.jsx +100 -0
- premiere_cli/panel/host/commands/close-all-source-clips.jsx +32 -0
- premiere_cli/panel/host/commands/close-sequence.jsx +80 -0
- premiere_cli/panel/host/commands/close-source-monitor.jsx +32 -0
- premiere_cli/panel/host/commands/color-correct.jsx +164 -0
- premiere_cli/panel/host/commands/copy-effect-values.jsx +183 -0
- premiere_cli/panel/host/commands/copy-effects-between-clips.jsx +234 -0
- premiere_cli/panel/host/commands/create-bars-and-tone.jsx +152 -0
- premiere_cli/panel/host/commands/create-bin.jsx +76 -0
- premiere_cli/panel/host/commands/create-caption-track.jsx +159 -0
- premiere_cli/panel/host/commands/create-sequence-from-clips.jsx +170 -0
- premiere_cli/panel/host/commands/create-sequence-from-preset.jsx +90 -0
- premiere_cli/panel/host/commands/create-sequence.jsx +166 -0
- premiere_cli/panel/host/commands/create-smart-bin.jsx +80 -0
- premiere_cli/panel/host/commands/create-subclip.jsx +248 -0
- premiere_cli/panel/host/commands/create-subsequence.jsx +136 -0
- premiere_cli/panel/host/commands/debug-qe-inspect.jsx +248 -0
- premiere_cli/panel/host/commands/debug-qe-try-mutate.jsx +305 -0
- premiere_cli/panel/host/commands/delete-marker.jsx +178 -0
- premiere_cli/panel/host/commands/deselect-all-clips.jsx +98 -0
- premiere_cli/panel/host/commands/detach-proxy.jsx +116 -0
- premiere_cli/panel/host/commands/duplicate-clip.jsx +140 -0
- premiere_cli/panel/host/commands/duplicate-sequence.jsx +150 -0
- premiere_cli/panel/host/commands/encode-file.jsx +86 -0
- premiere_cli/panel/host/commands/encode-project-item.jsx +145 -0
- premiere_cli/panel/host/commands/export-aaf.jsx +77 -0
- premiere_cli/panel/host/commands/export-fcp-xml.jsx +65 -0
- premiere_cli/panel/host/commands/export-frame.jsx +381 -0
- premiere_cli/panel/host/commands/export-omf.jsx +95 -0
- premiere_cli/panel/host/commands/export-sequence-as-project.jsx +65 -0
- premiere_cli/panel/host/commands/export-sequence.jsx +100 -0
- premiere_cli/panel/host/commands/extract-audio-track.jsx +181 -0
- premiere_cli/panel/host/commands/extract-selection.jsx +113 -0
- premiere_cli/panel/host/commands/find-items-by-media-path.jsx +112 -0
- premiere_cli/panel/host/commands/freeze-frame.jsx +215 -0
- premiere_cli/panel/host/commands/get-active-sequence.jsx +103 -0
- premiere_cli/panel/host/commands/get-all-project-paths.jsx +72 -0
- premiere_cli/panel/host/commands/get-bin-contents.jsx +176 -0
- premiere_cli/panel/host/commands/get-clip-adjustment-layer.jsx +83 -0
- premiere_cli/panel/host/commands/get-clip-at-playhead.jsx +99 -0
- premiere_cli/panel/host/commands/get-clip-at-position.jsx +120 -0
- premiere_cli/panel/host/commands/get-clip-links.jsx +135 -0
- premiere_cli/panel/host/commands/get-clip-markers.jsx +144 -0
- premiere_cli/panel/host/commands/get-clip-speed.jsx +69 -0
- premiere_cli/panel/host/commands/get-color-label.jsx +89 -0
- premiere_cli/panel/host/commands/get-color-space.jsx +99 -0
- premiere_cli/panel/host/commands/get-duplicate-media.jsx +78 -0
- premiere_cli/panel/host/commands/get-effect-properties.jsx +129 -0
- premiere_cli/panel/host/commands/get-encoder-presets.jsx +131 -0
- premiere_cli/panel/host/commands/get-export-file-extension.jsx +56 -0
- premiere_cli/panel/host/commands/get-footage-interpretation.jsx +113 -0
- premiere_cli/panel/host/commands/get-full-clip-info.jsx +162 -0
- premiere_cli/panel/host/commands/get-full-project-overview.jsx +193 -0
- premiere_cli/panel/host/commands/get-full-sequence-info.jsx +184 -0
- premiere_cli/panel/host/commands/get-graphics-white-luminance.jsx +31 -0
- premiere_cli/panel/host/commands/get-insertion-bin.jsx +35 -0
- premiere_cli/panel/host/commands/get-item-metadata.jsx +94 -0
- premiere_cli/panel/host/commands/get-keyframes.jsx +158 -0
- premiere_cli/panel/host/commands/get-mogrt-component.jsx +111 -0
- premiere_cli/panel/host/commands/get-next-edit-point.jsx +131 -0
- premiere_cli/panel/host/commands/get-offline-media.jsx +67 -0
- premiere_cli/panel/host/commands/get-open-projects.jsx +50 -0
- premiere_cli/panel/host/commands/get-premiere-state.jsx +164 -0
- premiere_cli/panel/host/commands/get-project-info.jsx +63 -0
- premiere_cli/panel/host/commands/get-project-item-info.jsx +247 -0
- premiere_cli/panel/host/commands/get-project-panel-metadata.jsx +30 -0
- premiere_cli/panel/host/commands/get-qe-clip-info.jsx +198 -0
- premiere_cli/panel/host/commands/get-render-queue-status.jsx +35 -0
- premiere_cli/panel/host/commands/get-sequence-count.jsx +24 -0
- premiere_cli/panel/host/commands/get-sequence-in-out.jsx +76 -0
- premiere_cli/panel/host/commands/get-sequence-markers-by-type.jsx +89 -0
- premiere_cli/panel/host/commands/get-source-monitor-info.jsx +34 -0
- premiere_cli/panel/host/commands/get-source-monitor-position.jsx +30 -0
- premiere_cli/panel/host/commands/get-target-tracks.jsx +76 -0
- premiere_cli/panel/host/commands/get-timeline-gaps.jsx +124 -0
- premiere_cli/panel/host/commands/get-timeline-summary.jsx +154 -0
- premiere_cli/panel/host/commands/get-total-clip-count.jsx +67 -0
- premiere_cli/panel/host/commands/get-track-info.jsx +117 -0
- premiere_cli/panel/host/commands/get-unused-media.jsx +99 -0
- premiere_cli/panel/host/commands/get-used-media-report.jsx +125 -0
- premiere_cli/panel/host/commands/get-value-at-time.jsx +135 -0
- premiere_cli/panel/host/commands/get-version-info.jsx +33 -0
- premiere_cli/panel/host/commands/get-work-area.jsx +52 -0
- premiere_cli/panel/host/commands/get-workspaces.jsx +29 -0
- premiere_cli/panel/host/commands/get-xmp-metadata.jsx +107 -0
- premiere_cli/panel/host/commands/import-ae-comps.jsx +129 -0
- premiere_cli/panel/host/commands/import-fcp-xml.jsx +103 -0
- premiere_cli/panel/host/commands/import-folder.jsx +193 -0
- premiere_cli/panel/host/commands/import-image-sequence.jsx +171 -0
- premiere_cli/panel/host/commands/import-media.jsx +217 -0
- premiere_cli/panel/host/commands/import-mogrt-from-library.jsx +105 -0
- premiere_cli/panel/host/commands/import-mogrt.jsx +111 -0
- premiere_cli/panel/host/commands/import-sequences-from-project.jsx +80 -0
- premiere_cli/panel/host/commands/insert-from-source.jsx +162 -0
- premiere_cli/panel/host/commands/inspect-dom-object.jsx +162 -0
- premiere_cli/panel/host/commands/invert-selection.jsx +114 -0
- premiere_cli/panel/host/commands/is-work-area-enabled.jsx +88 -0
- premiere_cli/panel/host/commands/lift-selection.jsx +106 -0
- premiere_cli/panel/host/commands/link-selection.jsx +111 -0
- premiere_cli/panel/host/commands/list-available-audio-effects.jsx +33 -0
- premiere_cli/panel/host/commands/list-available-audio-transitions.jsx +35 -0
- premiere_cli/panel/host/commands/list-available-effects.jsx +33 -0
- premiere_cli/panel/host/commands/list-available-transitions.jsx +74 -0
- premiere_cli/panel/host/commands/list-markers.jsx +69 -0
- premiere_cli/panel/host/commands/list-project-items.jsx +105 -0
- premiere_cli/panel/host/commands/lock-track.jsx +114 -0
- premiere_cli/panel/host/commands/manage-proxies.jsx +176 -0
- premiere_cli/panel/host/commands/match-frame.jsx +141 -0
- premiere_cli/panel/host/commands/move-clip-to-track.jsx +220 -0
- premiere_cli/panel/host/commands/move-clip.jsx +97 -0
- premiere_cli/panel/host/commands/move-items-to-bin.jsx +194 -0
- premiere_cli/panel/host/commands/move-playhead-to-edit.jsx +174 -0
- premiere_cli/panel/host/commands/move-playhead.jsx +137 -0
- premiere_cli/panel/host/commands/nest-clips.jsx +179 -0
- premiere_cli/panel/host/commands/open-in-source.jsx +117 -0
- premiere_cli/panel/host/commands/open-project.jsx +61 -0
- premiere_cli/panel/host/commands/overwrite-clip-at.jsx +350 -0
- premiere_cli/panel/host/commands/overwrite-from-source.jsx +150 -0
- premiere_cli/panel/host/commands/play-source-monitor.jsx +36 -0
- premiere_cli/panel/host/commands/play-timeline.jsx +24 -0
- premiere_cli/panel/host/commands/razor-all-tracks.jsx +171 -0
- premiere_cli/panel/host/commands/redo.jsx +69 -0
- premiere_cli/panel/host/commands/refresh-media.jsx +101 -0
- premiere_cli/panel/host/commands/relink-media.jsx +132 -0
- premiere_cli/panel/host/commands/remove-all-effects.jsx +114 -0
- premiere_cli/panel/host/commands/remove-effect-by-name.jsx +143 -0
- premiere_cli/panel/host/commands/remove-effect.jsx +122 -0
- premiere_cli/panel/host/commands/remove-from-timeline.jsx +93 -0
- premiere_cli/panel/host/commands/remove-keyframe-range.jsx +173 -0
- premiere_cli/panel/host/commands/remove-keyframe.jsx +192 -0
- premiere_cli/panel/host/commands/remove-selected-clips.jsx +126 -0
- premiere_cli/panel/host/commands/remove-track-intervals.jsx +254 -0
- premiere_cli/panel/host/commands/remove-transition.jsx +164 -0
- premiere_cli/panel/host/commands/rename-bin.jsx +88 -0
- premiere_cli/panel/host/commands/rename-clip.jsx +127 -0
- premiere_cli/panel/host/commands/rename-project-item.jsx +111 -0
- premiere_cli/panel/host/commands/rename-track.jsx +84 -0
- premiere_cli/panel/host/commands/replace-clip-media.jsx +140 -0
- premiere_cli/panel/host/commands/replace-clip.jsx +188 -0
- premiere_cli/panel/host/commands/reverse-clip.jsx +187 -0
- premiere_cli/panel/host/commands/ripple-delete-clip.jsx +156 -0
- premiere_cli/panel/host/commands/roll-edit.jsx +162 -0
- premiere_cli/panel/host/commands/save-project-as.jsx +55 -0
- premiere_cli/panel/host/commands/save-project.jsx +57 -0
- premiere_cli/panel/host/commands/scene-edit-detection.jsx +128 -0
- premiere_cli/panel/host/commands/search-project-items.jsx +180 -0
- premiere_cli/panel/host/commands/select-all-clips.jsx +107 -0
- premiere_cli/panel/host/commands/select-clips-by-color.jsx +142 -0
- premiere_cli/panel/host/commands/select-clips-by-name.jsx +133 -0
- premiere_cli/panel/host/commands/select-clips-in-range.jsx +133 -0
- premiere_cli/panel/host/commands/select-disabled-clips.jsx +127 -0
- premiere_cli/panel/host/commands/select-project-item.jsx +115 -0
- premiere_cli/panel/host/commands/set-active-project.jsx +184 -0
- premiere_cli/panel/host/commands/set-active-sequence.jsx +87 -0
- premiere_cli/panel/host/commands/set-all-tracks-targeted.jsx +112 -0
- premiere_cli/panel/host/commands/set-anti-alias-quality.jsx +125 -0
- premiere_cli/panel/host/commands/set-blend-mode.jsx +111 -0
- premiere_cli/panel/host/commands/set-clip-anchor-point.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-enabled.jsx +127 -0
- premiere_cli/panel/host/commands/set-clip-opacity.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-pan.jsx +107 -0
- premiere_cli/panel/host/commands/set-clip-position.jsx +103 -0
- premiere_cli/panel/host/commands/set-clip-properties.jsx +221 -0
- premiere_cli/panel/host/commands/set-clip-rotation.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-scale.jsx +102 -0
- premiere_cli/panel/host/commands/set-clip-selection.jsx +144 -0
- premiere_cli/panel/host/commands/set-clip-speed.jsx +160 -0
- premiere_cli/panel/host/commands/set-clip-volume.jsx +128 -0
- premiere_cli/panel/host/commands/set-color-label.jsx +123 -0
- premiere_cli/panel/host/commands/set-color-value.jsx +155 -0
- premiere_cli/panel/host/commands/set-effect-property.jsx +124 -0
- premiere_cli/panel/host/commands/set-footage-interpretation.jsx +173 -0
- premiere_cli/panel/host/commands/set-frame-blend.jsx +145 -0
- premiere_cli/panel/host/commands/set-graphics-white-luminance.jsx +73 -0
- premiere_cli/panel/host/commands/set-item-in-out.jsx +180 -0
- premiere_cli/panel/host/commands/set-item-metadata.jsx +134 -0
- premiere_cli/panel/host/commands/set-item-offline.jsx +109 -0
- premiere_cli/panel/host/commands/set-item-start-time.jsx +139 -0
- premiere_cli/panel/host/commands/set-keyframe-interpolation.jsx +186 -0
- premiere_cli/panel/host/commands/set-override-frame-rate.jsx +123 -0
- premiere_cli/panel/host/commands/set-override-pixel-aspect-ratio.jsx +129 -0
- premiere_cli/panel/host/commands/set-poster-frame.jsx +192 -0
- premiere_cli/panel/host/commands/set-project-panel-metadata.jsx +69 -0
- premiere_cli/panel/host/commands/set-scale-to-frame-size.jsx +101 -0
- premiere_cli/panel/host/commands/set-scale-width-height.jsx +140 -0
- premiere_cli/panel/host/commands/set-sequence-in-out.jsx +65 -0
- premiere_cli/panel/host/commands/set-sequence-settings.jsx +184 -0
- premiere_cli/panel/host/commands/set-source-in-out.jsx +98 -0
- premiere_cli/panel/host/commands/set-target-track.jsx +91 -0
- premiere_cli/panel/host/commands/set-time-interpolation.jsx +141 -0
- premiere_cli/panel/host/commands/set-track-mute.jsx +91 -0
- premiere_cli/panel/host/commands/set-track-visibility.jsx +94 -0
- premiere_cli/panel/host/commands/set-transcode-on-ingest.jsx +78 -0
- premiere_cli/panel/host/commands/set-uniform-scale.jsx +104 -0
- premiere_cli/panel/host/commands/set-work-area.jsx +76 -0
- premiere_cli/panel/host/commands/set-workspace.jsx +35 -0
- premiere_cli/panel/host/commands/set-xmp-metadata.jsx +157 -0
- premiere_cli/panel/host/commands/slide-edit.jsx +162 -0
- premiere_cli/panel/host/commands/slip-edit.jsx +167 -0
- premiere_cli/panel/host/commands/split-clip.jsx +144 -0
- premiere_cli/panel/host/commands/stabilize-clip.jsx +139 -0
- premiere_cli/panel/host/commands/stop-playback.jsx +23 -0
- premiere_cli/panel/host/commands/trim-clip.jsx +111 -0
- premiere_cli/panel/host/commands/undo.jsx +114 -0
- premiere_cli/panel/host/commands/unlink-selection.jsx +106 -0
- premiere_cli/panel/host/commands/unnest-sequence.jsx +207 -0
- premiere_cli/panel/host/commands/update-marker.jsx +120 -0
- premiere_cli/panel/host/index.jsx +1227 -0
- premiere_cli/panel/host/presets/default-4k-25fps.sqpreset +63 -0
- premiere_cli/panel/index.html +16 -0
- premiere_cli/panel/js/cs-interface.js +11 -0
- premiere_cli/panel/js/main.js +409 -0
- premiere_cli/panel_install.py +220 -0
- premiere_cli-0.2.0.dist-info/METADATA +127 -0
- premiere_cli-0.2.0.dist-info/RECORD +247 -0
- premiere_cli-0.2.0.dist-info/WHEEL +5 -0
- premiere_cli-0.2.0.dist-info/entry_points.txt +3 -0
- premiere_cli-0.2.0.dist-info/licenses/LICENSE +428 -0
- premiere_cli-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Command: batch-set-clips-enabled → ppb_batchSetClipsEnabled
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Standard-DOM mutation. Ported from leancoderkavy's premiere-pro-mcp
|
|
7
|
+
// `batch_enable_disable` tool (track-targeting.ts), which supports
|
|
8
|
+
// target: "selected"|"track"|"all" — collapsed here to two filters
|
|
9
|
+
// (`nameContains`, `trackType`) since this bridge otherwise always exposes
|
|
10
|
+
// filters rather than a target enum (matching batch-rename-clips'
|
|
11
|
+
// convention); omit both to affect every clip in the sequence, matching
|
|
12
|
+
// the reference's "all" target. There is no `target: "selected"`
|
|
13
|
+
// equivalent — use select-clips-by-name / set-clip-selection first, then
|
|
14
|
+
// filter batch-set-clips-enabled by the same `nameContains` if that
|
|
15
|
+
// combination is needed. Same `clip.disabled`/`setDisabled()` dual-probe
|
|
16
|
+
// as set-clip-enabled, capped at 200 clips per call, with a per-track
|
|
17
|
+
// read-back verification summary rather than trusting the mutation calls.
|
|
18
|
+
var BATCH_SET_CLIPS_ENABLED_MAX = 200;
|
|
19
|
+
|
|
20
|
+
function ppb_batchSetClipsEnabledOnTrack(track, trackType, trackIndex, nameContainsLower, enabled, budget, results) {
|
|
21
|
+
var affected = 0;
|
|
22
|
+
var verifiedCount = 0;
|
|
23
|
+
var numClips = track.clips.numItems;
|
|
24
|
+
var requestedDisabled = !enabled;
|
|
25
|
+
|
|
26
|
+
for (var c = 0; c < numClips; c++) {
|
|
27
|
+
if (budget.remaining <= 0) {
|
|
28
|
+
budget.cappedAtLimit = true;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var clip = track.clips[c];
|
|
33
|
+
var clipName = null;
|
|
34
|
+
try { clipName = clip.name; } catch (e) { clipName = null; }
|
|
35
|
+
|
|
36
|
+
if (nameContainsLower !== null) {
|
|
37
|
+
var haystack = clipName === null ? "" : String(clipName).toLowerCase();
|
|
38
|
+
if (haystack.indexOf(nameContainsLower) === -1) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var entry = { trackType: trackType, trackIndex: trackIndex, clipIndex: c, clipName: clipName, verified: false };
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
clip.disabled = requestedDisabled;
|
|
47
|
+
} catch (e1) {
|
|
48
|
+
try {
|
|
49
|
+
clip.setDisabled(requestedDisabled);
|
|
50
|
+
} catch (e2) {
|
|
51
|
+
entry.error = e1.toString() + " / " + e2.toString();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var newDisabled = null;
|
|
56
|
+
try { newDisabled = clip.disabled; } catch (e) { newDisabled = null; }
|
|
57
|
+
entry.verified = newDisabled === requestedDisabled;
|
|
58
|
+
|
|
59
|
+
if (entry.verified) {
|
|
60
|
+
verifiedCount++;
|
|
61
|
+
}
|
|
62
|
+
affected++;
|
|
63
|
+
budget.remaining--;
|
|
64
|
+
results.push(entry);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return { affected: affected, verifiedCount: verifiedCount };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function ppb_batchSetClipsEnabled(argsJson) {
|
|
71
|
+
try {
|
|
72
|
+
var args;
|
|
73
|
+
try {
|
|
74
|
+
args = JSON.parse(argsJson);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (typeof args.enabled !== "boolean") {
|
|
80
|
+
return JSON.stringify({ ok: false, error: "enabled must be a boolean" });
|
|
81
|
+
}
|
|
82
|
+
var trackTypeFilter = args.trackType || "both";
|
|
83
|
+
if (trackTypeFilter !== "video" && trackTypeFilter !== "audio" && trackTypeFilter !== "both") {
|
|
84
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\", \"audio\", or \"both\"" });
|
|
85
|
+
}
|
|
86
|
+
var nameContainsLower = null;
|
|
87
|
+
if (typeof args.nameContains === "string" && args.nameContains.length > 0) {
|
|
88
|
+
nameContainsLower = args.nameContains.toLowerCase();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!app.project) {
|
|
92
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
var seq = null;
|
|
96
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
97
|
+
seq = findSequenceByName(args.sequenceName);
|
|
98
|
+
if (!seq) {
|
|
99
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
seq = app.project.activeSequence;
|
|
103
|
+
if (!seq) {
|
|
104
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var results = [];
|
|
109
|
+
var budget = { remaining: BATCH_SET_CLIPS_ENABLED_MAX, cappedAtLimit: false };
|
|
110
|
+
var totalAffected = 0;
|
|
111
|
+
var totalVerified = 0;
|
|
112
|
+
|
|
113
|
+
if (trackTypeFilter === "video" || trackTypeFilter === "both") {
|
|
114
|
+
for (var vt = 0; vt < seq.videoTracks.numTracks; vt++) {
|
|
115
|
+
var vRes = ppb_batchSetClipsEnabledOnTrack(seq.videoTracks[vt], "video", vt, nameContainsLower, args.enabled, budget, results);
|
|
116
|
+
totalAffected += vRes.affected;
|
|
117
|
+
totalVerified += vRes.verifiedCount;
|
|
118
|
+
if (budget.cappedAtLimit) { break; }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!budget.cappedAtLimit && (trackTypeFilter === "audio" || trackTypeFilter === "both")) {
|
|
122
|
+
for (var at = 0; at < seq.audioTracks.numTracks; at++) {
|
|
123
|
+
var aRes = ppb_batchSetClipsEnabledOnTrack(seq.audioTracks[at], "audio", at, nameContainsLower, args.enabled, budget, results);
|
|
124
|
+
totalAffected += aRes.affected;
|
|
125
|
+
totalVerified += aRes.verifiedCount;
|
|
126
|
+
if (budget.cappedAtLimit) { break; }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
var result = {
|
|
131
|
+
sequenceName: seq.name,
|
|
132
|
+
trackType: trackTypeFilter,
|
|
133
|
+
nameContains: args.nameContains || null,
|
|
134
|
+
requestedEnabled: args.enabled,
|
|
135
|
+
affected: totalAffected,
|
|
136
|
+
verifiedCount: totalVerified,
|
|
137
|
+
cappedAtLimit: budget.cappedAtLimit,
|
|
138
|
+
results: results
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return JSON.stringify({ ok: true, result: result });
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// Command: clear-item-in-out → ppb_clearItemInOut
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context.
|
|
4
|
+
//
|
|
5
|
+
// Ported from leancoderkavy/premiere-pro-mcp's track-targeting.ts
|
|
6
|
+
// clear_item_in_out — clears in and/or out points on a PROJECT item via
|
|
7
|
+
// item.clearInPoint()/clearOutPoint(), resetting it to its full source
|
|
8
|
+
// duration. Both default to true (clear both) unless explicitly set false.
|
|
9
|
+
//
|
|
10
|
+
// Project-item addressing/lookup duplicated per command file, same
|
|
11
|
+
// convention as get-item-metadata.jsx / set-item-in-out.jsx.
|
|
12
|
+
|
|
13
|
+
function ppbFindItemClearItemInOut_walk(item, args, depth) {
|
|
14
|
+
if (depth > 32) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
var isBin = false;
|
|
18
|
+
try {
|
|
19
|
+
isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
isBin = false;
|
|
22
|
+
}
|
|
23
|
+
var matched = false;
|
|
24
|
+
if (args.nodeId !== null) {
|
|
25
|
+
try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
|
|
26
|
+
} else if (args.name !== null) {
|
|
27
|
+
try { matched = item.name === args.name; } catch (e) { matched = false; }
|
|
28
|
+
}
|
|
29
|
+
if (matched) {
|
|
30
|
+
return item;
|
|
31
|
+
}
|
|
32
|
+
if (isBin && item.children) {
|
|
33
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
34
|
+
var found = ppbFindItemClearItemInOut_walk(item.children[i], args, depth + 1);
|
|
35
|
+
if (found) {
|
|
36
|
+
return found;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ppbFindItemClearItemInOut_resolve(args) {
|
|
44
|
+
var root = app.project.rootItem;
|
|
45
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
46
|
+
var found = ppbFindItemClearItemInOut_walk(root.children[i], args, 1);
|
|
47
|
+
if (found) {
|
|
48
|
+
return found;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ppb_clearItemInOut(argsJson) {
|
|
55
|
+
try {
|
|
56
|
+
var args;
|
|
57
|
+
try {
|
|
58
|
+
args = JSON.parse(argsJson);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
64
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
65
|
+
if (!hasNodeId && !hasName) {
|
|
66
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!app.project) {
|
|
70
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
var item = ppbFindItemClearItemInOut_resolve({
|
|
74
|
+
nodeId: hasNodeId ? args.nodeId : null,
|
|
75
|
+
name: hasNodeId ? null : args.name
|
|
76
|
+
});
|
|
77
|
+
if (!item) {
|
|
78
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
var clearIn = args.clearIn !== false;
|
|
82
|
+
var clearOut = args.clearOut !== false;
|
|
83
|
+
|
|
84
|
+
var inClearError = null;
|
|
85
|
+
var outClearError = null;
|
|
86
|
+
|
|
87
|
+
if (clearIn) {
|
|
88
|
+
try {
|
|
89
|
+
item.clearInPoint();
|
|
90
|
+
} catch (e) {
|
|
91
|
+
inClearError = e.toString();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (clearOut) {
|
|
95
|
+
try {
|
|
96
|
+
item.clearOutPoint();
|
|
97
|
+
} catch (e) {
|
|
98
|
+
outClearError = e.toString();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return JSON.stringify({
|
|
103
|
+
ok: (clearIn ? inClearError === null : true) && (clearOut ? outClearError === null : true),
|
|
104
|
+
result: {
|
|
105
|
+
name: item.name,
|
|
106
|
+
nodeId: item.nodeId,
|
|
107
|
+
clearedIn: clearIn && inClearError === null,
|
|
108
|
+
clearedOut: clearOut && outClearError === null,
|
|
109
|
+
inClearError: inClearError,
|
|
110
|
+
outClearError: outClearError,
|
|
111
|
+
note: "no getInPoint/getOutPoint-style getter is confirmed available on this build (see set-item-in-out.jsx) — this only confirms the clear call(s) did not throw"
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
} catch (e) {
|
|
115
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Command: clear-sequence-in-out → ppb_clearSequenceInOut
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// trySetSequenceRange, timeValueToSeconds, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Ported from leancoderkavy/premiere-pro-mcp's track-targeting.ts
|
|
7
|
+
// clear_sequence_in_out. The reference implementation sets in=zeroPoint,
|
|
8
|
+
// out=seq.end — but per get-sequence-in-out.jsx's live finding, an actually
|
|
9
|
+
// UNSET in/out point reads back as Premiere's internal -400000 sentinel,
|
|
10
|
+
// not a real in/out range spanning the whole sequence. This command sets
|
|
11
|
+
// that literal -400000 sentinel value via the shared trySetSequenceRange()
|
|
12
|
+
// helper (its first attempt is the raw "seconds" form — i.e.
|
|
13
|
+
// seq.setInPoint(-400000) — which is exactly the value get-sequence-in-out
|
|
14
|
+
// reads back for "no point set", live-confirmed working on this build) so
|
|
15
|
+
// a subsequent get-sequence-in-out reports {inSeconds: null, outSeconds: null}.
|
|
16
|
+
var CLEAR_SEQUENCE_IN_OUT_SENTINEL = -400000;
|
|
17
|
+
|
|
18
|
+
// Duplicated from get-sequence-in-out.jsx's ppb_pointValueToSeconds (each
|
|
19
|
+
// command file loads independently and cannot rely on another command
|
|
20
|
+
// file's helpers) — treats Premiere's -400000-ish sentinel as "unset".
|
|
21
|
+
function ppbSentinelPointToSeconds(value) {
|
|
22
|
+
if (value === null || typeof value === "undefined") {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
if (typeof value === "object") {
|
|
26
|
+
return timeValueToSeconds(value);
|
|
27
|
+
}
|
|
28
|
+
var seconds = Number(value);
|
|
29
|
+
if (isNaN(seconds)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
if (seconds <= -399999) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return seconds;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function ppb_clearSequenceInOut(argsJson) {
|
|
39
|
+
try {
|
|
40
|
+
var args;
|
|
41
|
+
try {
|
|
42
|
+
args = JSON.parse(argsJson);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!app.project) {
|
|
48
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var seq = null;
|
|
52
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
53
|
+
seq = findSequenceByName(args.sequenceName);
|
|
54
|
+
if (!seq) {
|
|
55
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
seq = app.project.activeSequence;
|
|
59
|
+
if (!seq) {
|
|
60
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
var previousIn = null;
|
|
65
|
+
var previousOut = null;
|
|
66
|
+
try { previousIn = ppbSentinelPointToSeconds(seq.getInPoint()); } catch (e) { previousIn = null; }
|
|
67
|
+
try { previousOut = ppbSentinelPointToSeconds(seq.getOutPoint()); } catch (e) { previousOut = null; }
|
|
68
|
+
|
|
69
|
+
var rangeResult = trySetSequenceRange(seq, CLEAR_SEQUENCE_IN_OUT_SENTINEL, CLEAR_SEQUENCE_IN_OUT_SENTINEL);
|
|
70
|
+
if (!rangeResult.ok) {
|
|
71
|
+
return JSON.stringify({
|
|
72
|
+
ok: false,
|
|
73
|
+
error: "could not clear sequence in/out points with any known argument form",
|
|
74
|
+
attempts: rangeResult.attempts,
|
|
75
|
+
previousInSeconds: previousIn,
|
|
76
|
+
previousOutSeconds: previousOut
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var newIn = null;
|
|
81
|
+
var newOut = null;
|
|
82
|
+
try { newIn = ppbSentinelPointToSeconds(seq.getInPoint()); } catch (e) { newIn = null; }
|
|
83
|
+
try { newOut = ppbSentinelPointToSeconds(seq.getOutPoint()); } catch (e) { newOut = null; }
|
|
84
|
+
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
ok: true,
|
|
87
|
+
result: {
|
|
88
|
+
sequenceName: seq.name,
|
|
89
|
+
previousInSeconds: previousIn,
|
|
90
|
+
previousOutSeconds: previousOut,
|
|
91
|
+
inSeconds: newIn,
|
|
92
|
+
outSeconds: newOut,
|
|
93
|
+
verified: newIn === null && newOut === null,
|
|
94
|
+
attempts: rangeResult.attempts
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Command: close-all-source-clips → ppb_closeAllSourceClips
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use.
|
|
3
|
+
//
|
|
4
|
+
// Ported from leancoderkavy's premiere-pro-mcp source-monitor.ts
|
|
5
|
+
// close_all_source_clips. Closes every clip currently open across the
|
|
6
|
+
// Source Monitor's tabs via app.sourceMonitor.closeAllClips().
|
|
7
|
+
//
|
|
8
|
+
// MUTATION RULE: verified the same way as close-source-monitor — a null
|
|
9
|
+
// getProjectItem() read-back afterward confirms nothing is left loaded.
|
|
10
|
+
function ppb_closeAllSourceClips() {
|
|
11
|
+
try {
|
|
12
|
+
try {
|
|
13
|
+
app.sourceMonitor.closeAllClips();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return JSON.stringify({ ok: false, error: "app.sourceMonitor.closeAllClips() failed: " + e.toString() });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var stillLoaded = null;
|
|
19
|
+
try {
|
|
20
|
+
stillLoaded = app.sourceMonitor.getProjectItem();
|
|
21
|
+
} catch (e2) {
|
|
22
|
+
stillLoaded = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return JSON.stringify({
|
|
26
|
+
ok: true,
|
|
27
|
+
result: { closed: true, verified: !stillLoaded }
|
|
28
|
+
});
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Command: close-sequence → ppb_closeSequence
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Ported from leancoderkavy/premiere-pro-mcp's advanced.ts close_sequence
|
|
7
|
+
// tool: `seq.close()` per PREMIERE_API_NOTES.md's Sequences table.
|
|
8
|
+
//
|
|
9
|
+
// UI-TAB SEMANTICS PROBE: seq.close() is expected to close the sequence's
|
|
10
|
+
// TAB in the Timeline panel, not delete the sequence from the project —
|
|
11
|
+
// there is a separate app.project.deleteSequence(seq) for that. This
|
|
12
|
+
// command probes exactly that distinction rather than assuming it: after
|
|
13
|
+
// calling close(), it re-scans app.project.sequences (a collection
|
|
14
|
+
// distinct from open timeline tabs) for the closed sequence's own
|
|
15
|
+
// sequenceID and reports stillInProjectSequences accordingly.
|
|
16
|
+
function ppb_closeSequence(argsJson) {
|
|
17
|
+
try {
|
|
18
|
+
var args;
|
|
19
|
+
try {
|
|
20
|
+
args = JSON.parse(argsJson);
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!app.project) {
|
|
26
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var seq;
|
|
30
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
31
|
+
seq = findSequenceByName(args.sequenceName);
|
|
32
|
+
if (!seq) {
|
|
33
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
seq = app.project.activeSequence;
|
|
37
|
+
if (!seq) {
|
|
38
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var closedName = seq.name;
|
|
43
|
+
var closedSequenceID = null;
|
|
44
|
+
try { closedSequenceID = seq.sequenceID; } catch (e) { closedSequenceID = null; }
|
|
45
|
+
|
|
46
|
+
var numSequencesBefore = app.project.sequences.numSequences;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
seq.close();
|
|
50
|
+
} catch (e) {
|
|
51
|
+
return JSON.stringify({ ok: false, error: "seq.close() failed: " + e.toString() });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
var numSequencesAfter = app.project.sequences.numSequences;
|
|
55
|
+
var stillInProjectSequences = false;
|
|
56
|
+
for (var i = 0; i < app.project.sequences.numSequences; i++) {
|
|
57
|
+
var candidateId = null;
|
|
58
|
+
try { candidateId = app.project.sequences[i].sequenceID; } catch (e2) { candidateId = null; }
|
|
59
|
+
if (candidateId !== null && candidateId === closedSequenceID) {
|
|
60
|
+
stillInProjectSequences = true;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return JSON.stringify({
|
|
66
|
+
ok: true,
|
|
67
|
+
result: {
|
|
68
|
+
sequenceName: closedName,
|
|
69
|
+
sequenceID: closedSequenceID,
|
|
70
|
+
closed: true,
|
|
71
|
+
numSequencesBefore: numSequencesBefore,
|
|
72
|
+
numSequencesAfter: numSequencesAfter,
|
|
73
|
+
stillInProjectSequences: stillInProjectSequences,
|
|
74
|
+
note: "seq.close() closes the sequence's UI TAB in the Timeline panel — this is NOT the same as deleting the sequence from the project (that is app.project.deleteSequence(seq), not exposed by this command). stillInProjectSequences reports whether app.project.sequences — a collection distinct from open timeline tabs — still lists the closed sequence afterward, the only available probe of this UI-tab-vs-project-item distinction."
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Command: close-source-monitor → ppb_closeSourceMonitor
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use.
|
|
3
|
+
//
|
|
4
|
+
// Ported from leancoderkavy's premiere-pro-mcp source-monitor.ts
|
|
5
|
+
// close_source_monitor. Closes whichever single clip is open in the
|
|
6
|
+
// Source Monitor via app.sourceMonitor.closeClip().
|
|
7
|
+
//
|
|
8
|
+
// MUTATION RULE: verified by reading app.sourceMonitor.getProjectItem()
|
|
9
|
+
// back afterward — a null result confirms the monitor is now empty.
|
|
10
|
+
function ppb_closeSourceMonitor() {
|
|
11
|
+
try {
|
|
12
|
+
try {
|
|
13
|
+
app.sourceMonitor.closeClip();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return JSON.stringify({ ok: false, error: "app.sourceMonitor.closeClip() failed: " + e.toString() });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var stillLoaded = null;
|
|
19
|
+
try {
|
|
20
|
+
stillLoaded = app.sourceMonitor.getProjectItem();
|
|
21
|
+
} catch (e2) {
|
|
22
|
+
stillLoaded = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return JSON.stringify({
|
|
26
|
+
ok: true,
|
|
27
|
+
result: { closed: true, verified: !stillLoaded }
|
|
28
|
+
});
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Command: color-correct → ppb_colorCorrect
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// resolveTimelineClip, serializeClipComponents,
|
|
5
|
+
// ensureLumetriColorComponent, valuesApproximatelyEqual, ...) are already
|
|
6
|
+
// defined there.
|
|
7
|
+
//
|
|
8
|
+
// Ensures Lumetri Color is applied (via ensureLumetriColorComponent, adding
|
|
9
|
+
// it through the standard QE dance if missing), then sets any of
|
|
10
|
+
// exposure/contrast/saturation/temperature/tint by displayName. Per
|
|
11
|
+
// PREMIERE_API_NOTES.md, Lumetri repeats display names across its
|
|
12
|
+
// sub-sections (Basic Correction, Creative, HSL Secondary, ...) and not
|
|
13
|
+
// every match is writable — for each requested control, every matching
|
|
14
|
+
// property is tried in order until one setValue() doesn't throw ("first
|
|
15
|
+
// writable match wins"); previous/new values are read from that exact
|
|
16
|
+
// property index, not re-scanned from the top (which could otherwise grab
|
|
17
|
+
// an unrelated same-named property). 0 is a legitimate value for every one
|
|
18
|
+
// of these controls (e.g. full desaturate) — never falsy-checked.
|
|
19
|
+
function ppb_colorCorrect(argsJson) {
|
|
20
|
+
try {
|
|
21
|
+
var args;
|
|
22
|
+
try {
|
|
23
|
+
args = JSON.parse(argsJson);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (args.trackType !== "video") {
|
|
29
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\" — Lumetri Color is a video effect" });
|
|
30
|
+
}
|
|
31
|
+
if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
|
|
32
|
+
return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
|
|
33
|
+
}
|
|
34
|
+
if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
|
|
35
|
+
return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
var CONTROLS = [
|
|
39
|
+
{ key: "exposure", label: "Exposure" },
|
|
40
|
+
{ key: "contrast", label: "Contrast" },
|
|
41
|
+
{ key: "saturation", label: "Saturation" },
|
|
42
|
+
{ key: "temperature", label: "Temperature" },
|
|
43
|
+
{ key: "tint", label: "Tint" }
|
|
44
|
+
];
|
|
45
|
+
var requested = [];
|
|
46
|
+
for (var c = 0; c < CONTROLS.length; c++) {
|
|
47
|
+
if (typeof args[CONTROLS[c].key] === "number") {
|
|
48
|
+
requested.push(CONTROLS[c]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (requested.length === 0) {
|
|
52
|
+
return JSON.stringify({ ok: false, error: "at least one of exposure, contrast, saturation, temperature, tint is required" });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!app.project) {
|
|
56
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var seq = null;
|
|
60
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
61
|
+
seq = findSequenceByName(args.sequenceName);
|
|
62
|
+
if (!seq) {
|
|
63
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
seq = app.project.activeSequence;
|
|
67
|
+
if (!seq) {
|
|
68
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var resolvedClip = resolveTimelineClip(seq, "video", args.trackIndex, args.clipIndex);
|
|
73
|
+
if (resolvedClip.error) {
|
|
74
|
+
return JSON.stringify({ ok: false, error: resolvedClip.error });
|
|
75
|
+
}
|
|
76
|
+
var clip = resolvedClip.clip;
|
|
77
|
+
var clipName = null;
|
|
78
|
+
try { clipName = clip.name; } catch (e) { clipName = null; }
|
|
79
|
+
|
|
80
|
+
var previousComponents = serializeClipComponents(clip);
|
|
81
|
+
|
|
82
|
+
var lumetri = ensureLumetriColorComponent(seq, "video", args.trackIndex, args.clipIndex, clip);
|
|
83
|
+
if (lumetri.error) {
|
|
84
|
+
return JSON.stringify({ ok: false, error: lumetri.error });
|
|
85
|
+
}
|
|
86
|
+
var lumetriComp = lumetri.component;
|
|
87
|
+
|
|
88
|
+
var changes = {};
|
|
89
|
+
var numProps;
|
|
90
|
+
try {
|
|
91
|
+
numProps = lumetriComp.properties.numItems;
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return JSON.stringify({ ok: false, error: "could not read Lumetri Color's properties: " + e.toString() });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (var r = 0; r < requested.length; r++) {
|
|
97
|
+
var key = requested[r].key;
|
|
98
|
+
var label = requested[r].label;
|
|
99
|
+
var value = args[key];
|
|
100
|
+
|
|
101
|
+
var previousValue = null;
|
|
102
|
+
var havePrevious = false;
|
|
103
|
+
var applied = false;
|
|
104
|
+
var appliedIndex = -1;
|
|
105
|
+
var errorMsg = null;
|
|
106
|
+
|
|
107
|
+
for (var p = 0; p < numProps; p++) {
|
|
108
|
+
var prop = lumetriComp.properties[p];
|
|
109
|
+
var dn = null;
|
|
110
|
+
try { dn = prop.displayName; } catch (e2) { dn = null; }
|
|
111
|
+
if (dn !== label) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (!havePrevious) {
|
|
115
|
+
try { previousValue = prop.getValue(); } catch (e3) { previousValue = null; }
|
|
116
|
+
havePrevious = true;
|
|
117
|
+
}
|
|
118
|
+
if (!applied) {
|
|
119
|
+
try {
|
|
120
|
+
prop.setValue(value, true);
|
|
121
|
+
applied = true;
|
|
122
|
+
appliedIndex = p;
|
|
123
|
+
} catch (e4) {
|
|
124
|
+
errorMsg = e4.toString();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
var newValue = null;
|
|
130
|
+
if (applied) {
|
|
131
|
+
try { newValue = lumetriComp.properties[appliedIndex].getValue(); } catch (e5) { newValue = null; }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
changes[key] = {
|
|
135
|
+
displayName: label,
|
|
136
|
+
previousValue: previousValue,
|
|
137
|
+
requestedValue: value,
|
|
138
|
+
newValue: newValue,
|
|
139
|
+
applied: applied,
|
|
140
|
+
verified: applied && valuesApproximatelyEqual(newValue, value),
|
|
141
|
+
error: applied ? null : (errorMsg || "no writable property named \"" + label + "\" found on Lumetri Color")
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
var newComponents = serializeClipComponents(clip);
|
|
146
|
+
|
|
147
|
+
return JSON.stringify({
|
|
148
|
+
ok: true,
|
|
149
|
+
result: {
|
|
150
|
+
sequenceName: seq.name,
|
|
151
|
+
trackType: "video",
|
|
152
|
+
trackIndex: args.trackIndex,
|
|
153
|
+
clipIndex: args.clipIndex,
|
|
154
|
+
clipName: clipName,
|
|
155
|
+
lumetriApplied: lumetri.applied,
|
|
156
|
+
changes: changes,
|
|
157
|
+
previousComponents: previousComponents,
|
|
158
|
+
newComponents: newComponents
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
} catch (e) {
|
|
162
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
163
|
+
}
|
|
164
|
+
}
|