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,183 @@
|
|
|
1
|
+
// Command: copy-effect-values → ppb_copyEffectValues
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// resolveTimelineClip, findClipComponent, valuesApproximatelyEqual, ...)
|
|
5
|
+
// are already defined there.
|
|
6
|
+
//
|
|
7
|
+
// Ports leancoderkavy's clipboard.ts copy_effect_values: the named effect
|
|
8
|
+
// must ALREADY be applied on BOTH clips (no QE apply step here, unlike
|
|
9
|
+
// copy-effects-between-clips) — only property VALUES are copied across via
|
|
10
|
+
// getValue()/setValue(), matched by displayName. Standard-DOM only, no QE
|
|
11
|
+
// needed, so source and target may be on different sequences with no
|
|
12
|
+
// active-sequence juggling.
|
|
13
|
+
function ppb_copyEffectValues(argsJson) {
|
|
14
|
+
try {
|
|
15
|
+
var args;
|
|
16
|
+
try {
|
|
17
|
+
args = JSON.parse(argsJson);
|
|
18
|
+
} catch (e) {
|
|
19
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (args.sourceTrackType !== "video" && args.sourceTrackType !== "audio") {
|
|
23
|
+
return JSON.stringify({ ok: false, error: "sourceTrackType must be \"video\" or \"audio\"" });
|
|
24
|
+
}
|
|
25
|
+
if (args.targetTrackType !== "video" && args.targetTrackType !== "audio") {
|
|
26
|
+
return JSON.stringify({ ok: false, error: "targetTrackType must be \"video\" or \"audio\"" });
|
|
27
|
+
}
|
|
28
|
+
var indexFields = ["sourceTrackIndex", "sourceClipIndex", "targetTrackIndex", "targetClipIndex"];
|
|
29
|
+
for (var f = 0; f < indexFields.length; f++) {
|
|
30
|
+
var v = args[indexFields[f]];
|
|
31
|
+
if (typeof v !== "number" || v < 0 || Math.floor(v) !== v) {
|
|
32
|
+
return JSON.stringify({ ok: false, error: indexFields[f] + " must be a non-negative integer" });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (typeof args.effectName !== "string" || !args.effectName) {
|
|
36
|
+
return JSON.stringify({ ok: false, error: "effectName must be a non-empty string" });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!app.project) {
|
|
40
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolveSeq(name) {
|
|
44
|
+
if (name && typeof name === "string") {
|
|
45
|
+
var found = findSequenceByName(name);
|
|
46
|
+
if (!found) {
|
|
47
|
+
return { error: "no sequence named \"" + name + "\" is open" };
|
|
48
|
+
}
|
|
49
|
+
return { seq: found };
|
|
50
|
+
}
|
|
51
|
+
var active = app.project.activeSequence;
|
|
52
|
+
if (!active) {
|
|
53
|
+
return { error: "no active sequence, and no sequenceName given" };
|
|
54
|
+
}
|
|
55
|
+
return { seq: active };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
var srcSeqResolved = resolveSeq(args.sourceSequenceName);
|
|
59
|
+
if (srcSeqResolved.error) {
|
|
60
|
+
return JSON.stringify({ ok: false, error: "source: " + srcSeqResolved.error });
|
|
61
|
+
}
|
|
62
|
+
var srcSeq = srcSeqResolved.seq;
|
|
63
|
+
|
|
64
|
+
var tgtSeqResolved = resolveSeq(args.targetSequenceName);
|
|
65
|
+
if (tgtSeqResolved.error) {
|
|
66
|
+
return JSON.stringify({ ok: false, error: "target: " + tgtSeqResolved.error });
|
|
67
|
+
}
|
|
68
|
+
var tgtSeq = tgtSeqResolved.seq;
|
|
69
|
+
|
|
70
|
+
var srcResolvedClip = resolveTimelineClip(srcSeq, args.sourceTrackType, args.sourceTrackIndex, args.sourceClipIndex);
|
|
71
|
+
if (srcResolvedClip.error) {
|
|
72
|
+
return JSON.stringify({ ok: false, error: "source: " + srcResolvedClip.error });
|
|
73
|
+
}
|
|
74
|
+
var srcClip = srcResolvedClip.clip;
|
|
75
|
+
var srcClipName = null;
|
|
76
|
+
try { srcClipName = srcClip.name; } catch (e) { srcClipName = null; }
|
|
77
|
+
|
|
78
|
+
var tgtResolvedClip = resolveTimelineClip(tgtSeq, args.targetTrackType, args.targetTrackIndex, args.targetClipIndex);
|
|
79
|
+
if (tgtResolvedClip.error) {
|
|
80
|
+
return JSON.stringify({ ok: false, error: "target: " + tgtResolvedClip.error });
|
|
81
|
+
}
|
|
82
|
+
var tgtClip = tgtResolvedClip.clip;
|
|
83
|
+
var tgtClipName = null;
|
|
84
|
+
try { tgtClipName = tgtClip.name; } catch (e) { tgtClipName = null; }
|
|
85
|
+
|
|
86
|
+
var srcComp = findClipComponent(srcClip, null, [args.effectName]);
|
|
87
|
+
if (!srcComp) {
|
|
88
|
+
return JSON.stringify({ ok: false, error: "effect \"" + args.effectName + "\" not found on the source clip" });
|
|
89
|
+
}
|
|
90
|
+
var tgtComp = findClipComponent(tgtClip, null, [args.effectName]);
|
|
91
|
+
if (!tgtComp) {
|
|
92
|
+
return JSON.stringify({ ok: false, error: "effect \"" + args.effectName + "\" not found on the target clip" });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
var numSrcProps = 0;
|
|
96
|
+
try { numSrcProps = srcComp.properties.numItems; } catch (e) { numSrcProps = 0; }
|
|
97
|
+
var numTgtProps = 0;
|
|
98
|
+
try { numTgtProps = tgtComp.properties.numItems; } catch (e) { numTgtProps = 0; }
|
|
99
|
+
|
|
100
|
+
var properties = [];
|
|
101
|
+
var copiedCount = 0;
|
|
102
|
+
|
|
103
|
+
for (var sp = 0; sp < numSrcProps; sp++) {
|
|
104
|
+
var srcProp = srcComp.properties[sp];
|
|
105
|
+
var spName = null;
|
|
106
|
+
try { spName = srcProp.displayName; } catch (e2) { spName = null; }
|
|
107
|
+
if (!spName) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
var matchedTgtProp = null;
|
|
112
|
+
for (var tp = 0; tp < numTgtProps; tp++) {
|
|
113
|
+
var candidate = tgtComp.properties[tp];
|
|
114
|
+
var tpName = null;
|
|
115
|
+
try { tpName = candidate.displayName; } catch (e3) { tpName = null; }
|
|
116
|
+
if (tpName === spName) {
|
|
117
|
+
matchedTgtProp = candidate;
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (!matchedTgtProp) {
|
|
122
|
+
properties.push({ displayName: spName, copied: false, error: "no matching property on target clip's effect" });
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var previousValue = null;
|
|
127
|
+
try { previousValue = matchedTgtProp.getValue(); } catch (e4) { previousValue = null; }
|
|
128
|
+
var requestedValue = null;
|
|
129
|
+
try { requestedValue = srcProp.getValue(); } catch (e5) { requestedValue = null; }
|
|
130
|
+
|
|
131
|
+
var copied = false;
|
|
132
|
+
var errorMsg = null;
|
|
133
|
+
try {
|
|
134
|
+
matchedTgtProp.setValue(requestedValue, true);
|
|
135
|
+
copied = true;
|
|
136
|
+
} catch (e6) {
|
|
137
|
+
errorMsg = e6.toString();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
var newValue = null;
|
|
141
|
+
if (copied) {
|
|
142
|
+
try { newValue = matchedTgtProp.getValue(); } catch (e7) { newValue = null; }
|
|
143
|
+
copiedCount++;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
properties.push({
|
|
147
|
+
displayName: spName,
|
|
148
|
+
previousValue: previousValue,
|
|
149
|
+
requestedValue: requestedValue,
|
|
150
|
+
newValue: newValue,
|
|
151
|
+
copied: copied,
|
|
152
|
+
verified: copied && valuesApproximatelyEqual(newValue, requestedValue),
|
|
153
|
+
error: errorMsg
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return JSON.stringify({
|
|
158
|
+
ok: true,
|
|
159
|
+
result: {
|
|
160
|
+
effectName: args.effectName,
|
|
161
|
+
source: {
|
|
162
|
+
sequenceName: srcSeq.name,
|
|
163
|
+
trackType: args.sourceTrackType,
|
|
164
|
+
trackIndex: args.sourceTrackIndex,
|
|
165
|
+
clipIndex: args.sourceClipIndex,
|
|
166
|
+
clipName: srcClipName
|
|
167
|
+
},
|
|
168
|
+
target: {
|
|
169
|
+
sequenceName: tgtSeq.name,
|
|
170
|
+
trackType: args.targetTrackType,
|
|
171
|
+
trackIndex: args.targetTrackIndex,
|
|
172
|
+
clipIndex: args.targetClipIndex,
|
|
173
|
+
clipName: tgtClipName
|
|
174
|
+
},
|
|
175
|
+
propertiesTotal: numSrcProps,
|
|
176
|
+
propertiesCopied: copiedCount,
|
|
177
|
+
properties: properties
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
} catch (e) {
|
|
181
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// Command: copy-effects-between-clips → ppb_copyEffectsBetweenClips
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// ensureQEEnabled, activateSequenceForQE, resolveTimelineClip,
|
|
5
|
+
// resolveQeClip, serializeClipComponents, findQeVideoEffectByName,
|
|
6
|
+
// findQeAudioEffectByName, isIntrinsicComponentDisplayName, ...) are already
|
|
7
|
+
// defined there.
|
|
8
|
+
//
|
|
9
|
+
// Ports leancoderkavy's clipboard.ts copy_effects_between_clips: for each
|
|
10
|
+
// non-intrinsic component on the SOURCE clip (Motion/Opacity/Time
|
|
11
|
+
// Remapping/Volume/Channel Volume/Panner are skipped — see
|
|
12
|
+
// isIntrinsicComponentDisplayName — unless effectName narrows the copy to
|
|
13
|
+
// one specific effect), re-applies the same-named effect on the TARGET clip
|
|
14
|
+
// via the standard QE dance, then copies every matching property's value
|
|
15
|
+
// across via getValue()/setValue(). Source and target clips may be on
|
|
16
|
+
// DIFFERENT sequences — QE only ever operates on the ACTIVE sequence, so
|
|
17
|
+
// the TARGET's sequence is made active for the QE apply calls (the source
|
|
18
|
+
// is read via the standard DOM only, which needs no activation).
|
|
19
|
+
function ppb_copyEffectsBetweenClips(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.sourceTrackType !== "video" && args.sourceTrackType !== "audio") {
|
|
29
|
+
return JSON.stringify({ ok: false, error: "sourceTrackType must be \"video\" or \"audio\"" });
|
|
30
|
+
}
|
|
31
|
+
if (args.targetTrackType !== "video" && args.targetTrackType !== "audio") {
|
|
32
|
+
return JSON.stringify({ ok: false, error: "targetTrackType must be \"video\" or \"audio\"" });
|
|
33
|
+
}
|
|
34
|
+
var indexFields = ["sourceTrackIndex", "sourceClipIndex", "targetTrackIndex", "targetClipIndex"];
|
|
35
|
+
for (var f = 0; f < indexFields.length; f++) {
|
|
36
|
+
var v = args[indexFields[f]];
|
|
37
|
+
if (typeof v !== "number" || v < 0 || Math.floor(v) !== v) {
|
|
38
|
+
return JSON.stringify({ ok: false, error: indexFields[f] + " must be a non-negative integer" });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!app.project) {
|
|
43
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function resolveSeq(name) {
|
|
47
|
+
if (name && typeof name === "string") {
|
|
48
|
+
var found = findSequenceByName(name);
|
|
49
|
+
if (!found) {
|
|
50
|
+
return { error: "no sequence named \"" + name + "\" is open" };
|
|
51
|
+
}
|
|
52
|
+
return { seq: found };
|
|
53
|
+
}
|
|
54
|
+
var active = app.project.activeSequence;
|
|
55
|
+
if (!active) {
|
|
56
|
+
return { error: "no active sequence, and no sequenceName given" };
|
|
57
|
+
}
|
|
58
|
+
return { seq: active };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
var srcSeqResolved = resolveSeq(args.sourceSequenceName);
|
|
62
|
+
if (srcSeqResolved.error) {
|
|
63
|
+
return JSON.stringify({ ok: false, error: "source: " + srcSeqResolved.error });
|
|
64
|
+
}
|
|
65
|
+
var srcSeq = srcSeqResolved.seq;
|
|
66
|
+
|
|
67
|
+
var tgtSeqResolved = resolveSeq(args.targetSequenceName);
|
|
68
|
+
if (tgtSeqResolved.error) {
|
|
69
|
+
return JSON.stringify({ ok: false, error: "target: " + tgtSeqResolved.error });
|
|
70
|
+
}
|
|
71
|
+
var tgtSeq = tgtSeqResolved.seq;
|
|
72
|
+
|
|
73
|
+
var srcResolvedClip = resolveTimelineClip(srcSeq, args.sourceTrackType, args.sourceTrackIndex, args.sourceClipIndex);
|
|
74
|
+
if (srcResolvedClip.error) {
|
|
75
|
+
return JSON.stringify({ ok: false, error: "source: " + srcResolvedClip.error });
|
|
76
|
+
}
|
|
77
|
+
var srcClip = srcResolvedClip.clip;
|
|
78
|
+
var srcClipName = null;
|
|
79
|
+
try { srcClipName = srcClip.name; } catch (e) { srcClipName = null; }
|
|
80
|
+
|
|
81
|
+
var tgtResolvedClip = resolveTimelineClip(tgtSeq, args.targetTrackType, args.targetTrackIndex, args.targetClipIndex);
|
|
82
|
+
if (tgtResolvedClip.error) {
|
|
83
|
+
return JSON.stringify({ ok: false, error: "target: " + tgtResolvedClip.error });
|
|
84
|
+
}
|
|
85
|
+
var tgtClip = tgtResolvedClip.clip;
|
|
86
|
+
var tgtClipName = null;
|
|
87
|
+
try { tgtClipName = tgtClip.name; } catch (e) { tgtClipName = null; }
|
|
88
|
+
|
|
89
|
+
var previousTargetComponents = serializeClipComponents(tgtClip);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
ensureQEEnabled();
|
|
93
|
+
activateSequenceForQE(tgtSeq);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
return JSON.stringify({ ok: false, error: "app.enableQE()/target sequence activation failed: " + e.toString() });
|
|
96
|
+
}
|
|
97
|
+
if (typeof qe === "undefined" || !qe.project) {
|
|
98
|
+
return JSON.stringify({ ok: false, error: "QE DOM not available after enableQE()" });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
var qeSeq;
|
|
102
|
+
try {
|
|
103
|
+
qeSeq = qe.project.getActiveSequence();
|
|
104
|
+
} catch (e) {
|
|
105
|
+
return JSON.stringify({ ok: false, error: "qe.project.getActiveSequence() failed: " + e.toString() });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var tgtQeResolved = resolveQeClip(qeSeq, args.targetTrackType, args.targetTrackIndex, args.targetClipIndex);
|
|
109
|
+
if (tgtQeResolved.error) {
|
|
110
|
+
return JSON.stringify({ ok: false, error: "target: " + tgtQeResolved.error });
|
|
111
|
+
}
|
|
112
|
+
var tgtQeClip = tgtQeResolved.qeClip;
|
|
113
|
+
|
|
114
|
+
var effectFilter = (typeof args.effectName === "string" && args.effectName) ? args.effectName : null;
|
|
115
|
+
|
|
116
|
+
var numSrcComponents;
|
|
117
|
+
try {
|
|
118
|
+
numSrcComponents = srcClip.components.numItems;
|
|
119
|
+
} catch (e) {
|
|
120
|
+
return JSON.stringify({ ok: false, error: "could not read source clip's components: " + e.toString() });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
var effectResults = [];
|
|
124
|
+
var appliedCount = 0;
|
|
125
|
+
|
|
126
|
+
for (var i = 0; i < numSrcComponents; i++) {
|
|
127
|
+
var comp = srcClip.components[i];
|
|
128
|
+
var dn = null;
|
|
129
|
+
try { dn = comp.displayName; } catch (e2) { dn = null; }
|
|
130
|
+
if (!dn) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (effectFilter) {
|
|
134
|
+
if (dn !== effectFilter) {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
} else if (isIntrinsicComponentDisplayName(dn)) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
var fx = args.targetTrackType === "video" ? findQeVideoEffectByName(dn) : findQeAudioEffectByName(dn);
|
|
142
|
+
if (!fx) {
|
|
143
|
+
effectResults.push({ effect: dn, applied: false, error: "effect not found in the target track type's QE catalog" });
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
if (args.targetTrackType === "video") {
|
|
149
|
+
tgtQeClip.addVideoEffect(fx);
|
|
150
|
+
} else {
|
|
151
|
+
tgtQeClip.addAudioEffect(fx);
|
|
152
|
+
}
|
|
153
|
+
} catch (e3) {
|
|
154
|
+
effectResults.push({ effect: dn, applied: false, error: "addVideoEffect/addAudioEffect failed: " + e3.toString() });
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Per PREMIERE_API_NOTES.md, the newly-applied component is appended
|
|
159
|
+
// LAST on the standard-DOM clip.
|
|
160
|
+
var tgtNumComponents;
|
|
161
|
+
try {
|
|
162
|
+
tgtNumComponents = tgtClip.components.numItems;
|
|
163
|
+
} catch (e4) {
|
|
164
|
+
effectResults.push({ effect: dn, applied: true, propertiesCopied: 0, propertiesTotal: 0, error: "applied, but could not re-read target clip's components to copy property values: " + e4.toString() });
|
|
165
|
+
appliedCount++;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
var tgtComp = tgtClip.components[tgtNumComponents - 1];
|
|
169
|
+
|
|
170
|
+
var numSrcProps = 0;
|
|
171
|
+
try { numSrcProps = comp.properties.numItems; } catch (e5) { numSrcProps = 0; }
|
|
172
|
+
var numTgtProps = 0;
|
|
173
|
+
try { numTgtProps = tgtComp.properties.numItems; } catch (e6) { numTgtProps = 0; }
|
|
174
|
+
|
|
175
|
+
var propertiesCopied = 0;
|
|
176
|
+
for (var sp = 0; sp < numSrcProps; sp++) {
|
|
177
|
+
var srcProp = comp.properties[sp];
|
|
178
|
+
var spName = null;
|
|
179
|
+
try { spName = srcProp.displayName; } catch (e7) { spName = null; }
|
|
180
|
+
if (!spName) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
for (var tp = 0; tp < numTgtProps; tp++) {
|
|
184
|
+
var tgtProp = tgtComp.properties[tp];
|
|
185
|
+
var tpName = null;
|
|
186
|
+
try { tpName = tgtProp.displayName; } catch (e8) { tpName = null; }
|
|
187
|
+
if (tpName === spName) {
|
|
188
|
+
try {
|
|
189
|
+
var val = srcProp.getValue();
|
|
190
|
+
tgtProp.setValue(val, true);
|
|
191
|
+
propertiesCopied++;
|
|
192
|
+
} catch (e9) {
|
|
193
|
+
// best-effort — one unsettable property must not abort the
|
|
194
|
+
// whole effect's copy
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
effectResults.push({ effect: dn, applied: true, propertiesCopied: propertiesCopied, propertiesTotal: numSrcProps });
|
|
202
|
+
appliedCount++;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
var newTargetComponents = serializeClipComponents(tgtClip);
|
|
206
|
+
|
|
207
|
+
return JSON.stringify({
|
|
208
|
+
ok: true,
|
|
209
|
+
result: {
|
|
210
|
+
source: {
|
|
211
|
+
sequenceName: srcSeq.name,
|
|
212
|
+
trackType: args.sourceTrackType,
|
|
213
|
+
trackIndex: args.sourceTrackIndex,
|
|
214
|
+
clipIndex: args.sourceClipIndex,
|
|
215
|
+
clipName: srcClipName
|
|
216
|
+
},
|
|
217
|
+
target: {
|
|
218
|
+
sequenceName: tgtSeq.name,
|
|
219
|
+
trackType: args.targetTrackType,
|
|
220
|
+
trackIndex: args.targetTrackIndex,
|
|
221
|
+
clipIndex: args.targetClipIndex,
|
|
222
|
+
clipName: tgtClipName
|
|
223
|
+
},
|
|
224
|
+
effectFilter: effectFilter,
|
|
225
|
+
appliedCount: appliedCount,
|
|
226
|
+
effects: effectResults,
|
|
227
|
+
previousTargetComponents: previousTargetComponents,
|
|
228
|
+
newTargetComponents: newTargetComponents
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
} catch (e) {
|
|
232
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// Command: create-bars-and-tone → ppb_createBarsAndTone
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (TICKS_PER_SECOND,
|
|
4
|
+
// ensureQEEnabled, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// REWRITTEN 2026-07-17 after the probe session (see BUILD_FINDINGS.md
|
|
7
|
+
// corrections): the standard-DOM app.project.newBarsAndTone(...) throws
|
|
8
|
+
// "Illegal Parameter type" on this build, but the QE 2-arg form —
|
|
9
|
+
// qe.project.newBarsAndTone(width, height) — WORKS (found in the
|
|
10
|
+
// antipaster/Adobe-Premiere-Pro-MCP repo; live-verified creating an
|
|
11
|
+
// "HD Bars and Tone" project item). The QE call takes no name argument;
|
|
12
|
+
// Premiere names the item itself (e.g. "HD Bars and Tone"), so a
|
|
13
|
+
// requested name is applied afterward via item.name assignment.
|
|
14
|
+
// width/height default to 1920x1080 (bars-and-tone is a calibration/
|
|
15
|
+
// leader item, not a project deliverable). Verified via a project-tree
|
|
16
|
+
// nodeId diff of the root bin's children (never trusting the call's own
|
|
17
|
+
// return value). The standard-DOM form is still tried FIRST in case a
|
|
18
|
+
// future build repairs it (it accepts a name and timebase natively).
|
|
19
|
+
|
|
20
|
+
function ppbCreateBarsAndTone_snapshotRootIds() {
|
|
21
|
+
var ids = {};
|
|
22
|
+
var root = app.project.rootItem;
|
|
23
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
24
|
+
var nid = null;
|
|
25
|
+
try { nid = root.children[i].nodeId; } catch (e) { nid = null; }
|
|
26
|
+
if (nid) { ids[nid] = true; }
|
|
27
|
+
}
|
|
28
|
+
return ids;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function ppbCreateBarsAndTone_findNewItem(beforeIds) {
|
|
32
|
+
var root = app.project.rootItem;
|
|
33
|
+
for (var i = root.children.numItems - 1; i >= 0; i--) {
|
|
34
|
+
var nid = null;
|
|
35
|
+
try { nid = root.children[i].nodeId; } catch (e) { nid = null; }
|
|
36
|
+
if (nid && !beforeIds.hasOwnProperty(nid)) {
|
|
37
|
+
return root.children[i];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ppb_createBarsAndTone(argsJson) {
|
|
44
|
+
try {
|
|
45
|
+
var args;
|
|
46
|
+
try {
|
|
47
|
+
args = JSON.parse(argsJson);
|
|
48
|
+
} catch (e) {
|
|
49
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!app.project) {
|
|
53
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var width = typeof args.width === "number" ? args.width : 1920;
|
|
57
|
+
var height = typeof args.height === "number" ? args.height : 1080;
|
|
58
|
+
var requestedName = (typeof args.name === "string" && args.name.length > 0) ? args.name : null;
|
|
59
|
+
|
|
60
|
+
var attempts = [];
|
|
61
|
+
var newItem = null;
|
|
62
|
+
var methodUsed = null;
|
|
63
|
+
|
|
64
|
+
// 1. standard DOM — broken on 26.3.0 ("Illegal Parameter type") but
|
|
65
|
+
// cheap to try in case a future build repairs it.
|
|
66
|
+
if (typeof app.project.newBarsAndTone === "function") {
|
|
67
|
+
var timebase = null;
|
|
68
|
+
try {
|
|
69
|
+
var activeSeq = app.project.activeSequence;
|
|
70
|
+
timebase = activeSeq ? String(activeSeq.timebase) : String(TICKS_PER_SECOND);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
timebase = String(TICKS_PER_SECOND);
|
|
73
|
+
}
|
|
74
|
+
var beforeIds1 = ppbCreateBarsAndTone_snapshotRootIds();
|
|
75
|
+
var att1 = { method: "app.project.newBarsAndTone(w, h, timebaseStr, name)" };
|
|
76
|
+
try {
|
|
77
|
+
app.project.newBarsAndTone(width, height, timebase, requestedName || "Bars and Tone");
|
|
78
|
+
att1.threw = false;
|
|
79
|
+
} catch (e2) {
|
|
80
|
+
att1.threw = true;
|
|
81
|
+
att1.error = e2.toString();
|
|
82
|
+
}
|
|
83
|
+
newItem = ppbCreateBarsAndTone_findNewItem(beforeIds1);
|
|
84
|
+
att1.effective = newItem !== null;
|
|
85
|
+
attempts.push(att1);
|
|
86
|
+
if (newItem) { methodUsed = att1.method; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 2. QE 2-arg form — live-verified working on 26.3.0.
|
|
90
|
+
if (!newItem) {
|
|
91
|
+
try {
|
|
92
|
+
ensureQEEnabled();
|
|
93
|
+
} catch (e3) {
|
|
94
|
+
return JSON.stringify({ ok: false, error: "app.enableQE() failed: " + e3.toString(), attempts: attempts });
|
|
95
|
+
}
|
|
96
|
+
if (typeof qe === "undefined" || !qe.project || typeof qe.project.newBarsAndTone !== "function") {
|
|
97
|
+
return JSON.stringify({ ok: false, error: "no working bars-and-tone API on this build (standard DOM failed, qe.project.newBarsAndTone unavailable)", attempts: attempts });
|
|
98
|
+
}
|
|
99
|
+
var beforeIds2 = ppbCreateBarsAndTone_snapshotRootIds();
|
|
100
|
+
var att2 = { method: "qe.project.newBarsAndTone(w, h)" };
|
|
101
|
+
try {
|
|
102
|
+
qe.project.newBarsAndTone(width, height);
|
|
103
|
+
att2.threw = false;
|
|
104
|
+
} catch (e4) {
|
|
105
|
+
att2.threw = true;
|
|
106
|
+
att2.error = e4.toString();
|
|
107
|
+
}
|
|
108
|
+
newItem = ppbCreateBarsAndTone_findNewItem(beforeIds2);
|
|
109
|
+
att2.effective = newItem !== null;
|
|
110
|
+
attempts.push(att2);
|
|
111
|
+
if (newItem) { methodUsed = att2.method; }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!newItem) {
|
|
115
|
+
return JSON.stringify({
|
|
116
|
+
ok: false,
|
|
117
|
+
error: "no bars-and-tone item appeared in the root bin after any attempted call",
|
|
118
|
+
attempts: attempts
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// The QE form takes no name — apply a requested name afterward.
|
|
123
|
+
var premiereGivenName = null;
|
|
124
|
+
try { premiereGivenName = newItem.name; } catch (e5) { premiereGivenName = null; }
|
|
125
|
+
var renamed = null;
|
|
126
|
+
if (requestedName && premiereGivenName !== requestedName) {
|
|
127
|
+
try {
|
|
128
|
+
newItem.name = requestedName;
|
|
129
|
+
renamed = (newItem.name === requestedName);
|
|
130
|
+
} catch (e6) {
|
|
131
|
+
renamed = false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return JSON.stringify({
|
|
136
|
+
ok: true,
|
|
137
|
+
result: {
|
|
138
|
+
created: true,
|
|
139
|
+
methodUsed: methodUsed,
|
|
140
|
+
attempts: attempts,
|
|
141
|
+
premiereGivenName: premiereGivenName,
|
|
142
|
+
name: (function () { try { return newItem.name; } catch (e) { return premiereGivenName; } })(),
|
|
143
|
+
renamed: renamed,
|
|
144
|
+
width: width,
|
|
145
|
+
height: height,
|
|
146
|
+
nodeId: (function () { try { return newItem.nodeId; } catch (e) { return null; } })()
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
} catch (e) {
|
|
150
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Command: create-bin → ppb_createBin
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (TICKS_PER_SECOND, ...)
|
|
4
|
+
// are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Creates every missing segment of a '/'-separated bin path via
|
|
7
|
+
// parentBin.createBin(name), same bin-path-walking approach as
|
|
8
|
+
// create-sequence.jsx's own bin argument. Reports which segments already
|
|
9
|
+
// existed vs. were newly created, rather than silently no-oping on an
|
|
10
|
+
// existing path.
|
|
11
|
+
|
|
12
|
+
function ppb_createBin(argsJson) {
|
|
13
|
+
try {
|
|
14
|
+
var args;
|
|
15
|
+
try {
|
|
16
|
+
args = JSON.parse(argsJson);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!args.binPath || typeof args.binPath !== "string") {
|
|
22
|
+
return JSON.stringify({ ok: false, error: "binPath is required" });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!app.project) {
|
|
26
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var segments = args.binPath.split("/").filter(function (s) { return s.length > 0; });
|
|
30
|
+
if (segments.length === 0) {
|
|
31
|
+
return JSON.stringify({ ok: false, error: "binPath must contain at least one non-empty segment" });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var current = app.project.rootItem;
|
|
35
|
+
var createdSegments = [];
|
|
36
|
+
var existedSegments = [];
|
|
37
|
+
|
|
38
|
+
for (var i = 0; i < segments.length; i++) {
|
|
39
|
+
var segment = segments[i];
|
|
40
|
+
var found = null;
|
|
41
|
+
for (var j = 0; j < current.children.numItems; j++) {
|
|
42
|
+
var child = current.children[j];
|
|
43
|
+
if (child.name === segment && typeof ProjectItemType !== "undefined" && child.type === ProjectItemType.BIN) {
|
|
44
|
+
found = child;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (found) {
|
|
49
|
+
existedSegments.push(segment);
|
|
50
|
+
current = found;
|
|
51
|
+
} else {
|
|
52
|
+
var created;
|
|
53
|
+
try {
|
|
54
|
+
created = current.createBin(segment);
|
|
55
|
+
} catch (e) {
|
|
56
|
+
return JSON.stringify({ ok: false, error: "createBin(\"" + segment + "\") failed: " + e.toString() });
|
|
57
|
+
}
|
|
58
|
+
createdSegments.push(segment);
|
|
59
|
+
current = created;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return JSON.stringify({
|
|
64
|
+
ok: true,
|
|
65
|
+
result: {
|
|
66
|
+
binPath: args.binPath,
|
|
67
|
+
nodeId: current.nodeId,
|
|
68
|
+
createdSegments: createdSegments,
|
|
69
|
+
existedSegments: existedSegments,
|
|
70
|
+
alreadyExisted: createdSegments.length === 0
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
} catch (e) {
|
|
74
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
75
|
+
}
|
|
76
|
+
}
|