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,135 @@
|
|
|
1
|
+
// Command: get-clip-links → ppb_getClipLinks
|
|
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
|
+
// findSequenceByName, timeValueToSeconds, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Standard-DOM read only, no QE DOM needed. Clip addressing (sequenceName?,
|
|
7
|
+
// trackType, trackIndex, clipIndex) matches get-full-clip-info.jsx. Linked
|
|
8
|
+
// clips are detected heuristically — same source projectItem.nodeId and
|
|
9
|
+
// the same start time — since there is no direct "get linked items" API
|
|
10
|
+
// (per PREMIERE_API_NOTES.md's Clips/TrackItems section). Helper names are
|
|
11
|
+
// prefixed ppbClipLinks_ to avoid colliding with same-purpose helpers in
|
|
12
|
+
// other lazily-loaded command files evaluated into this same global
|
|
13
|
+
// context.
|
|
14
|
+
|
|
15
|
+
function ppbClipLinks_findLinked(tracks, trackTypeLabel, clipNodeId, clipStartSeconds, srcNodeId, linked) {
|
|
16
|
+
for (var t = 0; t < tracks.numTracks; t++) {
|
|
17
|
+
var track = tracks[t];
|
|
18
|
+
var numClips = 0;
|
|
19
|
+
try {
|
|
20
|
+
numClips = track.clips.numItems;
|
|
21
|
+
} catch (e) {
|
|
22
|
+
numClips = 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (var c = 0; c < numClips; c++) {
|
|
26
|
+
var other = track.clips[c];
|
|
27
|
+
|
|
28
|
+
var otherNodeId = null;
|
|
29
|
+
try { otherNodeId = other.nodeId; } catch (e) { otherNodeId = null; }
|
|
30
|
+
if (otherNodeId && clipNodeId && otherNodeId === clipNodeId) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var otherSrcNodeId = null;
|
|
35
|
+
try {
|
|
36
|
+
otherSrcNodeId = other.projectItem ? other.projectItem.nodeId : null;
|
|
37
|
+
} catch (e) {
|
|
38
|
+
otherSrcNodeId = null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var otherStartSeconds = null;
|
|
42
|
+
try { otherStartSeconds = timeValueToSeconds(other.start); } catch (e) { otherStartSeconds = null; }
|
|
43
|
+
|
|
44
|
+
if (srcNodeId && otherSrcNodeId === srcNodeId && otherStartSeconds !== null && clipStartSeconds !== null && otherStartSeconds === clipStartSeconds) {
|
|
45
|
+
var entry = { nodeId: otherNodeId, name: null, trackType: trackTypeLabel, trackIndex: t, startSeconds: otherStartSeconds, endSeconds: null };
|
|
46
|
+
try { entry.name = other.name; } catch (e) { entry.name = null; }
|
|
47
|
+
try { entry.endSeconds = timeValueToSeconds(other.end); } catch (e) { entry.endSeconds = null; }
|
|
48
|
+
linked.push(entry);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ppb_getClipLinks(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
|
+
if (args.trackType !== "video" && args.trackType !== "audio") {
|
|
64
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
|
|
65
|
+
}
|
|
66
|
+
if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
|
|
67
|
+
return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
|
|
68
|
+
}
|
|
69
|
+
if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
|
|
70
|
+
return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!app.project) {
|
|
74
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
var seq = null;
|
|
78
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
79
|
+
seq = findSequenceByName(args.sequenceName);
|
|
80
|
+
if (!seq) {
|
|
81
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
seq = app.project.activeSequence;
|
|
85
|
+
if (!seq) {
|
|
86
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
|
|
91
|
+
var numTracks = trackCollection.numTracks;
|
|
92
|
+
if (args.trackIndex >= numTracks) {
|
|
93
|
+
return JSON.stringify({
|
|
94
|
+
ok: false,
|
|
95
|
+
error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
var track = trackCollection[args.trackIndex];
|
|
100
|
+
var numClips = track.clips.numItems;
|
|
101
|
+
if (args.clipIndex >= numClips) {
|
|
102
|
+
return JSON.stringify({
|
|
103
|
+
ok: false,
|
|
104
|
+
error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
var clip = track.clips[args.clipIndex];
|
|
109
|
+
|
|
110
|
+
var info = { nodeId: null, name: null, trackType: args.trackType, trackIndex: args.trackIndex, clipIndex: args.clipIndex };
|
|
111
|
+
try { info.nodeId = clip.nodeId; } catch (e) { info.nodeId = null; }
|
|
112
|
+
try { info.name = clip.name; } catch (e) { info.name = null; }
|
|
113
|
+
|
|
114
|
+
var clipStartSeconds = null;
|
|
115
|
+
try { clipStartSeconds = timeValueToSeconds(clip.start); } catch (e) { clipStartSeconds = null; }
|
|
116
|
+
|
|
117
|
+
var srcNodeId = null;
|
|
118
|
+
try {
|
|
119
|
+
srcNodeId = clip.projectItem ? clip.projectItem.nodeId : null;
|
|
120
|
+
} catch (e) {
|
|
121
|
+
srcNodeId = null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
var linked = [];
|
|
125
|
+
ppbClipLinks_findLinked(seq.videoTracks, "video", info.nodeId, clipStartSeconds, srcNodeId, linked);
|
|
126
|
+
ppbClipLinks_findLinked(seq.audioTracks, "audio", info.nodeId, clipStartSeconds, srcNodeId, linked);
|
|
127
|
+
|
|
128
|
+
info.linkedClips = linked;
|
|
129
|
+
info.linkedCount = linked.length;
|
|
130
|
+
|
|
131
|
+
return JSON.stringify({ ok: true, result: info });
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Command: get-clip-markers → ppb_getClipMarkers
|
|
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
|
+
// findSequenceByName, timeValueToSeconds, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Clip addressing matches get-full-clip-info.jsx (sequenceName?,
|
|
7
|
+
// trackType, trackIndex, clipIndex) — the reference tool this is ported
|
|
8
|
+
// from (leancoderkavy's get_clip_markers) addresses a PROJECT item by
|
|
9
|
+
// item_id, but per our own convention every other clip-scoped command
|
|
10
|
+
// addresses a TIMELINE clip the same way get-full-clip-info does, so this
|
|
11
|
+
// reads clip.markers (a TrackItem's own marker collection — same API
|
|
12
|
+
// shape as seq.markers per PREMIERE_API_NOTES.md) rather than a project
|
|
13
|
+
// item's getMarkers().
|
|
14
|
+
|
|
15
|
+
function ppbGetClipMarkers_serialize(clip, sourceOut) {
|
|
16
|
+
var markers = [];
|
|
17
|
+
// clip.markers (a TrackItem's own marker collection) is undefined on
|
|
18
|
+
// this Premiere 2026 build (live-tested 2026-07-17: "undefined is not
|
|
19
|
+
// an object") — fall back to the clip's source project item's
|
|
20
|
+
// getMarkers(). Semantics differ slightly (source-item markers vs
|
|
21
|
+
// timeline-clip markers); result reports which source answered.
|
|
22
|
+
var collection = null;
|
|
23
|
+
try {
|
|
24
|
+
if (clip.markers && typeof clip.markers.getFirstMarker === "function") {
|
|
25
|
+
collection = clip.markers;
|
|
26
|
+
sourceOut.source = "trackItem";
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
// fall through
|
|
30
|
+
}
|
|
31
|
+
if (collection === null) {
|
|
32
|
+
try {
|
|
33
|
+
var itemMarkers = clip.projectItem.getMarkers();
|
|
34
|
+
if (itemMarkers && typeof itemMarkers.getFirstMarker === "function") {
|
|
35
|
+
collection = itemMarkers;
|
|
36
|
+
sourceOut.source = "projectItem";
|
|
37
|
+
}
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// fall through
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (collection === null) {
|
|
43
|
+
throw new Error("neither clip.markers nor clip.projectItem.getMarkers() is available on this build");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var m = collection.getFirstMarker();
|
|
47
|
+
var iterations = 0;
|
|
48
|
+
while (m !== null && typeof m !== "undefined" && iterations < 10000) {
|
|
49
|
+
var entry = { name: null, comments: null, type: null, startSeconds: null, endSeconds: null, guid: null };
|
|
50
|
+
try { entry.name = m.name; } catch (e) { entry.name = null; }
|
|
51
|
+
try { entry.comments = m.comments; } catch (e) { entry.comments = null; }
|
|
52
|
+
try { entry.type = m.type; } catch (e) { entry.type = null; }
|
|
53
|
+
try { entry.startSeconds = timeValueToSeconds(m.start); } catch (e) { entry.startSeconds = null; }
|
|
54
|
+
try { entry.endSeconds = timeValueToSeconds(m.end); } catch (e) { entry.endSeconds = null; }
|
|
55
|
+
try { entry.guid = m.guid; } catch (e) { entry.guid = null; }
|
|
56
|
+
markers.push(entry);
|
|
57
|
+
|
|
58
|
+
m = collection.getNextMarker(m);
|
|
59
|
+
iterations++;
|
|
60
|
+
}
|
|
61
|
+
return markers;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function ppb_getClipMarkers(argsJson) {
|
|
65
|
+
try {
|
|
66
|
+
var args;
|
|
67
|
+
try {
|
|
68
|
+
args = JSON.parse(argsJson);
|
|
69
|
+
} catch (e) {
|
|
70
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (args.trackType !== "video" && args.trackType !== "audio") {
|
|
74
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
|
|
75
|
+
}
|
|
76
|
+
if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
|
|
77
|
+
return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
|
|
78
|
+
}
|
|
79
|
+
if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
|
|
80
|
+
return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!app.project) {
|
|
84
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var seq = null;
|
|
88
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
89
|
+
seq = findSequenceByName(args.sequenceName);
|
|
90
|
+
if (!seq) {
|
|
91
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
seq = app.project.activeSequence;
|
|
95
|
+
if (!seq) {
|
|
96
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
|
|
101
|
+
var numTracks = trackCollection.numTracks;
|
|
102
|
+
if (args.trackIndex >= numTracks) {
|
|
103
|
+
return JSON.stringify({
|
|
104
|
+
ok: false,
|
|
105
|
+
error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
var track = trackCollection[args.trackIndex];
|
|
110
|
+
var numClips = track.clips.numItems;
|
|
111
|
+
if (args.clipIndex >= numClips) {
|
|
112
|
+
return JSON.stringify({
|
|
113
|
+
ok: false,
|
|
114
|
+
error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
var clip = track.clips[args.clipIndex];
|
|
119
|
+
|
|
120
|
+
var markers = [];
|
|
121
|
+
try {
|
|
122
|
+
var markerSource = { source: null };
|
|
123
|
+
markers = ppbGetClipMarkers_serialize(clip, markerSource);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
return JSON.stringify({ ok: false, error: "failed to read clip markers: " + e.toString() });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return JSON.stringify({
|
|
129
|
+
ok: true,
|
|
130
|
+
result: {
|
|
131
|
+
sequenceName: seq.name,
|
|
132
|
+
trackType: args.trackType,
|
|
133
|
+
trackIndex: args.trackIndex,
|
|
134
|
+
clipIndex: args.clipIndex,
|
|
135
|
+
clipName: (function () { try { return clip.name; } catch (e) { return null; } })(),
|
|
136
|
+
markers: markers,
|
|
137
|
+
markerCount: markers.length,
|
|
138
|
+
markerSource: markerSource.source
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
} catch (e) {
|
|
142
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Command: get-clip-speed → ppb_getClipSpeed
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context — shared helpers (findSequenceByName,
|
|
4
|
+
// resolveTimelineClip, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// READ-ONLY. Ported from leancoderkavy's premiere-pro-mcp get_clip_speed
|
|
7
|
+
// tool: reads the standard-DOM clip.getSpeed()/isSpeedReversed(), the
|
|
8
|
+
// same pair set-clip-speed verifies its own writes against.
|
|
9
|
+
|
|
10
|
+
function ppb_getClipSpeed(argsJson) {
|
|
11
|
+
try {
|
|
12
|
+
var args;
|
|
13
|
+
try {
|
|
14
|
+
args = JSON.parse(argsJson);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (args.trackType !== "video" && args.trackType !== "audio") {
|
|
20
|
+
return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
|
|
21
|
+
}
|
|
22
|
+
if (typeof args.trackIndex !== "number" || typeof args.clipIndex !== "number") {
|
|
23
|
+
return JSON.stringify({ ok: false, error: "trackIndex and clipIndex are required" });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!app.project) {
|
|
27
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var seq = null;
|
|
31
|
+
if (args.sequenceName && typeof args.sequenceName === "string") {
|
|
32
|
+
seq = findSequenceByName(args.sequenceName);
|
|
33
|
+
if (!seq) {
|
|
34
|
+
return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
seq = app.project.activeSequence;
|
|
38
|
+
if (!seq) {
|
|
39
|
+
return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var resolved = resolveTimelineClip(seq, args.trackType, args.trackIndex, args.clipIndex);
|
|
44
|
+
if (resolved.error) {
|
|
45
|
+
return JSON.stringify({ ok: false, error: resolved.error });
|
|
46
|
+
}
|
|
47
|
+
var clip = resolved.clip;
|
|
48
|
+
|
|
49
|
+
var speed = null;
|
|
50
|
+
var isSpeedReversed = null;
|
|
51
|
+
try { speed = clip.getSpeed(); } catch (e2) { speed = null; }
|
|
52
|
+
try { isSpeedReversed = clip.isSpeedReversed() === true || clip.isSpeedReversed() === 1; } catch (e3) { isSpeedReversed = null; }
|
|
53
|
+
|
|
54
|
+
return JSON.stringify({
|
|
55
|
+
ok: true,
|
|
56
|
+
result: {
|
|
57
|
+
sequenceName: seq.name,
|
|
58
|
+
trackType: args.trackType,
|
|
59
|
+
trackIndex: args.trackIndex,
|
|
60
|
+
clipIndex: args.clipIndex,
|
|
61
|
+
clipName: (function () { try { return clip.name; } catch (e) { return null; } })(),
|
|
62
|
+
speed: speed,
|
|
63
|
+
isSpeedReversed: isSpeedReversed
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
} catch (e) {
|
|
67
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Command: get-color-label → ppb_getColorLabel
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context.
|
|
4
|
+
//
|
|
5
|
+
// Project-item addressing: at least one of nodeId/name is required (see
|
|
6
|
+
// get-item-metadata.jsx for the shared design note — the resolver is
|
|
7
|
+
// duplicated per-file since command files load independently).
|
|
8
|
+
|
|
9
|
+
function ppbFindItemGetColorLabel_walk(item, args, depth) {
|
|
10
|
+
if (depth > 32) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var isBin = false;
|
|
15
|
+
try {
|
|
16
|
+
isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
|
|
17
|
+
} catch (e) {
|
|
18
|
+
isBin = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var matched = false;
|
|
22
|
+
if (args.nodeId !== null) {
|
|
23
|
+
try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
|
|
24
|
+
} else if (args.name !== null) {
|
|
25
|
+
try { matched = item.name === args.name; } catch (e) { matched = false; }
|
|
26
|
+
}
|
|
27
|
+
if (matched) {
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isBin && item.children) {
|
|
32
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
33
|
+
var found = ppbFindItemGetColorLabel_walk(item.children[i], args, depth + 1);
|
|
34
|
+
if (found) {
|
|
35
|
+
return found;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ppbFindItemGetColorLabel_resolve(args) {
|
|
43
|
+
var root = app.project.rootItem;
|
|
44
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
45
|
+
var found = ppbFindItemGetColorLabel_walk(root.children[i], args, 1);
|
|
46
|
+
if (found) {
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ppb_getColorLabel(argsJson) {
|
|
54
|
+
try {
|
|
55
|
+
var args;
|
|
56
|
+
try {
|
|
57
|
+
args = JSON.parse(argsJson);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
63
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
64
|
+
if (!hasNodeId && !hasName) {
|
|
65
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!app.project) {
|
|
69
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var item = ppbFindItemGetColorLabel_resolve({
|
|
73
|
+
nodeId: hasNodeId ? args.nodeId : null,
|
|
74
|
+
name: hasNodeId ? null : args.name
|
|
75
|
+
});
|
|
76
|
+
if (!item) {
|
|
77
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var result = { name: null, nodeId: null, colorLabel: null };
|
|
81
|
+
try { result.name = item.name; } catch (e) { result.name = null; }
|
|
82
|
+
try { result.nodeId = item.nodeId; } catch (e) { result.nodeId = null; }
|
|
83
|
+
try { result.colorLabel = item.getColorLabel(); } catch (e) { result.colorLabel = null; }
|
|
84
|
+
|
|
85
|
+
return JSON.stringify({ ok: true, result: result });
|
|
86
|
+
} catch (e) {
|
|
87
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Command: get-color-space → ppb_getColorSpace
|
|
2
|
+
// Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
|
|
3
|
+
// same global ExtendScript context.
|
|
4
|
+
//
|
|
5
|
+
// Project-item addressing: at least one of nodeId/name is required (see
|
|
6
|
+
// get-item-metadata.jsx for the shared design note — the resolver is
|
|
7
|
+
// duplicated per-file since command files load independently).
|
|
8
|
+
|
|
9
|
+
function ppbFindItemGetColorSpace_walk(item, args, depth) {
|
|
10
|
+
if (depth > 32) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var isBin = false;
|
|
15
|
+
try {
|
|
16
|
+
isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
|
|
17
|
+
} catch (e) {
|
|
18
|
+
isBin = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
var matched = false;
|
|
22
|
+
if (args.nodeId !== null) {
|
|
23
|
+
try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
|
|
24
|
+
} else if (args.name !== null) {
|
|
25
|
+
try { matched = item.name === args.name; } catch (e) { matched = false; }
|
|
26
|
+
}
|
|
27
|
+
if (matched) {
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (isBin && item.children) {
|
|
32
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
33
|
+
var found = ppbFindItemGetColorSpace_walk(item.children[i], args, depth + 1);
|
|
34
|
+
if (found) {
|
|
35
|
+
return found;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ppbFindItemGetColorSpace_resolve(args) {
|
|
43
|
+
var root = app.project.rootItem;
|
|
44
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
45
|
+
var found = ppbFindItemGetColorSpace_walk(root.children[i], args, 1);
|
|
46
|
+
if (found) {
|
|
47
|
+
return found;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ppb_getColorSpace(argsJson) {
|
|
54
|
+
try {
|
|
55
|
+
var args;
|
|
56
|
+
try {
|
|
57
|
+
args = JSON.parse(argsJson);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
|
|
63
|
+
var hasName = typeof args.name === "string" && args.name.length > 0;
|
|
64
|
+
if (!hasNodeId && !hasName) {
|
|
65
|
+
return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!app.project) {
|
|
69
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var item = ppbFindItemGetColorSpace_resolve({
|
|
73
|
+
nodeId: hasNodeId ? args.nodeId : null,
|
|
74
|
+
name: hasNodeId ? null : args.name
|
|
75
|
+
});
|
|
76
|
+
if (!item) {
|
|
77
|
+
return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var result = {
|
|
81
|
+
name: null,
|
|
82
|
+
nodeId: null,
|
|
83
|
+
colorSpace: null,
|
|
84
|
+
originalColorSpace: null,
|
|
85
|
+
embeddedLUT: null,
|
|
86
|
+
inputLUT: null
|
|
87
|
+
};
|
|
88
|
+
try { result.name = item.name; } catch (e) { result.name = null; }
|
|
89
|
+
try { result.nodeId = item.nodeId; } catch (e) { result.nodeId = null; }
|
|
90
|
+
try { result.colorSpace = item.getColorSpace(); } catch (e) { result.colorSpace = null; }
|
|
91
|
+
try { result.originalColorSpace = item.getOriginalColorSpace(); } catch (e) { result.originalColorSpace = null; }
|
|
92
|
+
try { result.embeddedLUT = item.getEmbeddedLUTID(); } catch (e) { result.embeddedLUT = null; }
|
|
93
|
+
try { result.inputLUT = item.getInputLUTID(); } catch (e) { result.inputLUT = null; }
|
|
94
|
+
|
|
95
|
+
return JSON.stringify({ ok: true, result: result });
|
|
96
|
+
} catch (e) {
|
|
97
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Command: get-duplicate-media → ppb_getDuplicateMedia
|
|
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, findSequenceByName, ...) are already defined there.
|
|
5
|
+
//
|
|
6
|
+
// Recursive walk of app.project.rootItem.children (same shape as
|
|
7
|
+
// list-project-items.jsx), grouping non-bin items by mediaPath and
|
|
8
|
+
// reporting groups with more than one member. Helper names are prefixed
|
|
9
|
+
// ppbDuplicateMedia_ to avoid colliding with same-purpose helpers in other
|
|
10
|
+
// lazily-loaded command files evaluated into this same global context.
|
|
11
|
+
|
|
12
|
+
function ppbDuplicateMedia_isBin(item) {
|
|
13
|
+
try {
|
|
14
|
+
return typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Capped at depth 32 to defend against pathological/circular bin
|
|
21
|
+
// structures rather than looping forever.
|
|
22
|
+
function ppbDuplicateMedia_scan(item, depth, pathMap, order) {
|
|
23
|
+
if (depth > 32) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var mediaPath = null;
|
|
28
|
+
try {
|
|
29
|
+
mediaPath = item.getMediaPath();
|
|
30
|
+
} catch (e) {
|
|
31
|
+
mediaPath = null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (mediaPath) {
|
|
35
|
+
if (!pathMap[mediaPath]) {
|
|
36
|
+
pathMap[mediaPath] = [];
|
|
37
|
+
order.push(mediaPath);
|
|
38
|
+
}
|
|
39
|
+
var entry = { nodeId: null, name: null, treePath: null };
|
|
40
|
+
try { entry.nodeId = item.nodeId; } catch (e) { entry.nodeId = null; }
|
|
41
|
+
try { entry.name = item.name; } catch (e) { entry.name = null; }
|
|
42
|
+
try { entry.treePath = item.treePath; } catch (e) { entry.treePath = null; }
|
|
43
|
+
pathMap[mediaPath].push(entry);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (ppbDuplicateMedia_isBin(item) && item.children) {
|
|
47
|
+
for (var i = 0; i < item.children.numItems; i++) {
|
|
48
|
+
ppbDuplicateMedia_scan(item.children[i], depth + 1, pathMap, order);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ppb_getDuplicateMedia(argsJson) {
|
|
54
|
+
try {
|
|
55
|
+
if (!app.project) {
|
|
56
|
+
return JSON.stringify({ ok: false, error: "no project open" });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var pathMap = {};
|
|
60
|
+
var order = [];
|
|
61
|
+
var root = app.project.rootItem;
|
|
62
|
+
for (var i = 0; i < root.children.numItems; i++) {
|
|
63
|
+
ppbDuplicateMedia_scan(root.children[i], 1, pathMap, order);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
var duplicates = [];
|
|
67
|
+
for (var j = 0; j < order.length; j++) {
|
|
68
|
+
var path = order[j];
|
|
69
|
+
if (pathMap[path].length > 1) {
|
|
70
|
+
duplicates.push({ mediaPath: path, count: pathMap[path].length, items: pathMap[path] });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return JSON.stringify({ ok: true, result: { duplicateGroupCount: duplicates.length, duplicates: duplicates } });
|
|
75
|
+
} catch (e) {
|
|
76
|
+
return JSON.stringify({ ok: false, error: e.toString() });
|
|
77
|
+
}
|
|
78
|
+
}
|