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.
Files changed (247) hide show
  1. premiere_cli/__init__.py +11 -0
  2. premiere_cli/cli.py +3664 -0
  3. premiere_cli/log.py +66 -0
  4. premiere_cli/panel/.debug +8 -0
  5. premiere_cli/panel/CSXS/manifest.xml +52 -0
  6. premiere_cli/panel/css/style.css +53 -0
  7. premiere_cli/panel/host/commands/add-adjustment-layer.jsx +190 -0
  8. premiere_cli/panel/host/commands/add-audio-keyframes.jsx +176 -0
  9. premiere_cli/panel/host/commands/add-custom-metadata-field.jsx +63 -0
  10. premiere_cli/panel/host/commands/add-keyframe.jsx +181 -0
  11. premiere_cli/panel/host/commands/add-marker-to-project-item.jsx +194 -0
  12. premiere_cli/panel/host/commands/add-marker.jsx +129 -0
  13. premiere_cli/panel/host/commands/add-text-overlay.jsx +101 -0
  14. premiere_cli/panel/host/commands/add-to-render-queue.jsx +120 -0
  15. premiere_cli/panel/host/commands/add-to-timeline.jsx +300 -0
  16. premiere_cli/panel/host/commands/add-track.jsx +188 -0
  17. premiere_cli/panel/host/commands/add-transition.jsx +134 -0
  18. premiere_cli/panel/host/commands/adjust-audio-levels.jsx +132 -0
  19. premiere_cli/panel/host/commands/apply-audio-effect.jsx +118 -0
  20. premiere_cli/panel/host/commands/apply-effect.jsx +122 -0
  21. premiere_cli/panel/host/commands/apply-lut.jsx +107 -0
  22. premiere_cli/panel/host/commands/attach-custom-property.jsx +66 -0
  23. premiere_cli/panel/host/commands/auto-reframe-sequence.jsx +124 -0
  24. premiere_cli/panel/host/commands/batch-add-transitions.jsx +158 -0
  25. premiere_cli/panel/host/commands/batch-apply-effect.jsx +182 -0
  26. premiere_cli/panel/host/commands/batch-rename-clips.jsx +170 -0
  27. premiere_cli/panel/host/commands/batch-set-clips-enabled.jsx +145 -0
  28. premiere_cli/panel/host/commands/clear-item-in-out.jsx +117 -0
  29. premiere_cli/panel/host/commands/clear-sequence-in-out.jsx +100 -0
  30. premiere_cli/panel/host/commands/close-all-source-clips.jsx +32 -0
  31. premiere_cli/panel/host/commands/close-sequence.jsx +80 -0
  32. premiere_cli/panel/host/commands/close-source-monitor.jsx +32 -0
  33. premiere_cli/panel/host/commands/color-correct.jsx +164 -0
  34. premiere_cli/panel/host/commands/copy-effect-values.jsx +183 -0
  35. premiere_cli/panel/host/commands/copy-effects-between-clips.jsx +234 -0
  36. premiere_cli/panel/host/commands/create-bars-and-tone.jsx +152 -0
  37. premiere_cli/panel/host/commands/create-bin.jsx +76 -0
  38. premiere_cli/panel/host/commands/create-caption-track.jsx +159 -0
  39. premiere_cli/panel/host/commands/create-sequence-from-clips.jsx +170 -0
  40. premiere_cli/panel/host/commands/create-sequence-from-preset.jsx +90 -0
  41. premiere_cli/panel/host/commands/create-sequence.jsx +166 -0
  42. premiere_cli/panel/host/commands/create-smart-bin.jsx +80 -0
  43. premiere_cli/panel/host/commands/create-subclip.jsx +248 -0
  44. premiere_cli/panel/host/commands/create-subsequence.jsx +136 -0
  45. premiere_cli/panel/host/commands/debug-qe-inspect.jsx +248 -0
  46. premiere_cli/panel/host/commands/debug-qe-try-mutate.jsx +305 -0
  47. premiere_cli/panel/host/commands/delete-marker.jsx +178 -0
  48. premiere_cli/panel/host/commands/deselect-all-clips.jsx +98 -0
  49. premiere_cli/panel/host/commands/detach-proxy.jsx +116 -0
  50. premiere_cli/panel/host/commands/duplicate-clip.jsx +140 -0
  51. premiere_cli/panel/host/commands/duplicate-sequence.jsx +150 -0
  52. premiere_cli/panel/host/commands/encode-file.jsx +86 -0
  53. premiere_cli/panel/host/commands/encode-project-item.jsx +145 -0
  54. premiere_cli/panel/host/commands/export-aaf.jsx +77 -0
  55. premiere_cli/panel/host/commands/export-fcp-xml.jsx +65 -0
  56. premiere_cli/panel/host/commands/export-frame.jsx +381 -0
  57. premiere_cli/panel/host/commands/export-omf.jsx +95 -0
  58. premiere_cli/panel/host/commands/export-sequence-as-project.jsx +65 -0
  59. premiere_cli/panel/host/commands/export-sequence.jsx +100 -0
  60. premiere_cli/panel/host/commands/extract-audio-track.jsx +181 -0
  61. premiere_cli/panel/host/commands/extract-selection.jsx +113 -0
  62. premiere_cli/panel/host/commands/find-items-by-media-path.jsx +112 -0
  63. premiere_cli/panel/host/commands/freeze-frame.jsx +215 -0
  64. premiere_cli/panel/host/commands/get-active-sequence.jsx +103 -0
  65. premiere_cli/panel/host/commands/get-all-project-paths.jsx +72 -0
  66. premiere_cli/panel/host/commands/get-bin-contents.jsx +176 -0
  67. premiere_cli/panel/host/commands/get-clip-adjustment-layer.jsx +83 -0
  68. premiere_cli/panel/host/commands/get-clip-at-playhead.jsx +99 -0
  69. premiere_cli/panel/host/commands/get-clip-at-position.jsx +120 -0
  70. premiere_cli/panel/host/commands/get-clip-links.jsx +135 -0
  71. premiere_cli/panel/host/commands/get-clip-markers.jsx +144 -0
  72. premiere_cli/panel/host/commands/get-clip-speed.jsx +69 -0
  73. premiere_cli/panel/host/commands/get-color-label.jsx +89 -0
  74. premiere_cli/panel/host/commands/get-color-space.jsx +99 -0
  75. premiere_cli/panel/host/commands/get-duplicate-media.jsx +78 -0
  76. premiere_cli/panel/host/commands/get-effect-properties.jsx +129 -0
  77. premiere_cli/panel/host/commands/get-encoder-presets.jsx +131 -0
  78. premiere_cli/panel/host/commands/get-export-file-extension.jsx +56 -0
  79. premiere_cli/panel/host/commands/get-footage-interpretation.jsx +113 -0
  80. premiere_cli/panel/host/commands/get-full-clip-info.jsx +162 -0
  81. premiere_cli/panel/host/commands/get-full-project-overview.jsx +193 -0
  82. premiere_cli/panel/host/commands/get-full-sequence-info.jsx +184 -0
  83. premiere_cli/panel/host/commands/get-graphics-white-luminance.jsx +31 -0
  84. premiere_cli/panel/host/commands/get-insertion-bin.jsx +35 -0
  85. premiere_cli/panel/host/commands/get-item-metadata.jsx +94 -0
  86. premiere_cli/panel/host/commands/get-keyframes.jsx +158 -0
  87. premiere_cli/panel/host/commands/get-mogrt-component.jsx +111 -0
  88. premiere_cli/panel/host/commands/get-next-edit-point.jsx +131 -0
  89. premiere_cli/panel/host/commands/get-offline-media.jsx +67 -0
  90. premiere_cli/panel/host/commands/get-open-projects.jsx +50 -0
  91. premiere_cli/panel/host/commands/get-premiere-state.jsx +164 -0
  92. premiere_cli/panel/host/commands/get-project-info.jsx +63 -0
  93. premiere_cli/panel/host/commands/get-project-item-info.jsx +247 -0
  94. premiere_cli/panel/host/commands/get-project-panel-metadata.jsx +30 -0
  95. premiere_cli/panel/host/commands/get-qe-clip-info.jsx +198 -0
  96. premiere_cli/panel/host/commands/get-render-queue-status.jsx +35 -0
  97. premiere_cli/panel/host/commands/get-sequence-count.jsx +24 -0
  98. premiere_cli/panel/host/commands/get-sequence-in-out.jsx +76 -0
  99. premiere_cli/panel/host/commands/get-sequence-markers-by-type.jsx +89 -0
  100. premiere_cli/panel/host/commands/get-source-monitor-info.jsx +34 -0
  101. premiere_cli/panel/host/commands/get-source-monitor-position.jsx +30 -0
  102. premiere_cli/panel/host/commands/get-target-tracks.jsx +76 -0
  103. premiere_cli/panel/host/commands/get-timeline-gaps.jsx +124 -0
  104. premiere_cli/panel/host/commands/get-timeline-summary.jsx +154 -0
  105. premiere_cli/panel/host/commands/get-total-clip-count.jsx +67 -0
  106. premiere_cli/panel/host/commands/get-track-info.jsx +117 -0
  107. premiere_cli/panel/host/commands/get-unused-media.jsx +99 -0
  108. premiere_cli/panel/host/commands/get-used-media-report.jsx +125 -0
  109. premiere_cli/panel/host/commands/get-value-at-time.jsx +135 -0
  110. premiere_cli/panel/host/commands/get-version-info.jsx +33 -0
  111. premiere_cli/panel/host/commands/get-work-area.jsx +52 -0
  112. premiere_cli/panel/host/commands/get-workspaces.jsx +29 -0
  113. premiere_cli/panel/host/commands/get-xmp-metadata.jsx +107 -0
  114. premiere_cli/panel/host/commands/import-ae-comps.jsx +129 -0
  115. premiere_cli/panel/host/commands/import-fcp-xml.jsx +103 -0
  116. premiere_cli/panel/host/commands/import-folder.jsx +193 -0
  117. premiere_cli/panel/host/commands/import-image-sequence.jsx +171 -0
  118. premiere_cli/panel/host/commands/import-media.jsx +217 -0
  119. premiere_cli/panel/host/commands/import-mogrt-from-library.jsx +105 -0
  120. premiere_cli/panel/host/commands/import-mogrt.jsx +111 -0
  121. premiere_cli/panel/host/commands/import-sequences-from-project.jsx +80 -0
  122. premiere_cli/panel/host/commands/insert-from-source.jsx +162 -0
  123. premiere_cli/panel/host/commands/inspect-dom-object.jsx +162 -0
  124. premiere_cli/panel/host/commands/invert-selection.jsx +114 -0
  125. premiere_cli/panel/host/commands/is-work-area-enabled.jsx +88 -0
  126. premiere_cli/panel/host/commands/lift-selection.jsx +106 -0
  127. premiere_cli/panel/host/commands/link-selection.jsx +111 -0
  128. premiere_cli/panel/host/commands/list-available-audio-effects.jsx +33 -0
  129. premiere_cli/panel/host/commands/list-available-audio-transitions.jsx +35 -0
  130. premiere_cli/panel/host/commands/list-available-effects.jsx +33 -0
  131. premiere_cli/panel/host/commands/list-available-transitions.jsx +74 -0
  132. premiere_cli/panel/host/commands/list-markers.jsx +69 -0
  133. premiere_cli/panel/host/commands/list-project-items.jsx +105 -0
  134. premiere_cli/panel/host/commands/lock-track.jsx +114 -0
  135. premiere_cli/panel/host/commands/manage-proxies.jsx +176 -0
  136. premiere_cli/panel/host/commands/match-frame.jsx +141 -0
  137. premiere_cli/panel/host/commands/move-clip-to-track.jsx +220 -0
  138. premiere_cli/panel/host/commands/move-clip.jsx +97 -0
  139. premiere_cli/panel/host/commands/move-items-to-bin.jsx +194 -0
  140. premiere_cli/panel/host/commands/move-playhead-to-edit.jsx +174 -0
  141. premiere_cli/panel/host/commands/move-playhead.jsx +137 -0
  142. premiere_cli/panel/host/commands/nest-clips.jsx +179 -0
  143. premiere_cli/panel/host/commands/open-in-source.jsx +117 -0
  144. premiere_cli/panel/host/commands/open-project.jsx +61 -0
  145. premiere_cli/panel/host/commands/overwrite-clip-at.jsx +350 -0
  146. premiere_cli/panel/host/commands/overwrite-from-source.jsx +150 -0
  147. premiere_cli/panel/host/commands/play-source-monitor.jsx +36 -0
  148. premiere_cli/panel/host/commands/play-timeline.jsx +24 -0
  149. premiere_cli/panel/host/commands/razor-all-tracks.jsx +171 -0
  150. premiere_cli/panel/host/commands/redo.jsx +69 -0
  151. premiere_cli/panel/host/commands/refresh-media.jsx +101 -0
  152. premiere_cli/panel/host/commands/relink-media.jsx +132 -0
  153. premiere_cli/panel/host/commands/remove-all-effects.jsx +114 -0
  154. premiere_cli/panel/host/commands/remove-effect-by-name.jsx +143 -0
  155. premiere_cli/panel/host/commands/remove-effect.jsx +122 -0
  156. premiere_cli/panel/host/commands/remove-from-timeline.jsx +93 -0
  157. premiere_cli/panel/host/commands/remove-keyframe-range.jsx +173 -0
  158. premiere_cli/panel/host/commands/remove-keyframe.jsx +192 -0
  159. premiere_cli/panel/host/commands/remove-selected-clips.jsx +126 -0
  160. premiere_cli/panel/host/commands/remove-track-intervals.jsx +254 -0
  161. premiere_cli/panel/host/commands/remove-transition.jsx +164 -0
  162. premiere_cli/panel/host/commands/rename-bin.jsx +88 -0
  163. premiere_cli/panel/host/commands/rename-clip.jsx +127 -0
  164. premiere_cli/panel/host/commands/rename-project-item.jsx +111 -0
  165. premiere_cli/panel/host/commands/rename-track.jsx +84 -0
  166. premiere_cli/panel/host/commands/replace-clip-media.jsx +140 -0
  167. premiere_cli/panel/host/commands/replace-clip.jsx +188 -0
  168. premiere_cli/panel/host/commands/reverse-clip.jsx +187 -0
  169. premiere_cli/panel/host/commands/ripple-delete-clip.jsx +156 -0
  170. premiere_cli/panel/host/commands/roll-edit.jsx +162 -0
  171. premiere_cli/panel/host/commands/save-project-as.jsx +55 -0
  172. premiere_cli/panel/host/commands/save-project.jsx +57 -0
  173. premiere_cli/panel/host/commands/scene-edit-detection.jsx +128 -0
  174. premiere_cli/panel/host/commands/search-project-items.jsx +180 -0
  175. premiere_cli/panel/host/commands/select-all-clips.jsx +107 -0
  176. premiere_cli/panel/host/commands/select-clips-by-color.jsx +142 -0
  177. premiere_cli/panel/host/commands/select-clips-by-name.jsx +133 -0
  178. premiere_cli/panel/host/commands/select-clips-in-range.jsx +133 -0
  179. premiere_cli/panel/host/commands/select-disabled-clips.jsx +127 -0
  180. premiere_cli/panel/host/commands/select-project-item.jsx +115 -0
  181. premiere_cli/panel/host/commands/set-active-project.jsx +184 -0
  182. premiere_cli/panel/host/commands/set-active-sequence.jsx +87 -0
  183. premiere_cli/panel/host/commands/set-all-tracks-targeted.jsx +112 -0
  184. premiere_cli/panel/host/commands/set-anti-alias-quality.jsx +125 -0
  185. premiere_cli/panel/host/commands/set-blend-mode.jsx +111 -0
  186. premiere_cli/panel/host/commands/set-clip-anchor-point.jsx +102 -0
  187. premiere_cli/panel/host/commands/set-clip-enabled.jsx +127 -0
  188. premiere_cli/panel/host/commands/set-clip-opacity.jsx +102 -0
  189. premiere_cli/panel/host/commands/set-clip-pan.jsx +107 -0
  190. premiere_cli/panel/host/commands/set-clip-position.jsx +103 -0
  191. premiere_cli/panel/host/commands/set-clip-properties.jsx +221 -0
  192. premiere_cli/panel/host/commands/set-clip-rotation.jsx +102 -0
  193. premiere_cli/panel/host/commands/set-clip-scale.jsx +102 -0
  194. premiere_cli/panel/host/commands/set-clip-selection.jsx +144 -0
  195. premiere_cli/panel/host/commands/set-clip-speed.jsx +160 -0
  196. premiere_cli/panel/host/commands/set-clip-volume.jsx +128 -0
  197. premiere_cli/panel/host/commands/set-color-label.jsx +123 -0
  198. premiere_cli/panel/host/commands/set-color-value.jsx +155 -0
  199. premiere_cli/panel/host/commands/set-effect-property.jsx +124 -0
  200. premiere_cli/panel/host/commands/set-footage-interpretation.jsx +173 -0
  201. premiere_cli/panel/host/commands/set-frame-blend.jsx +145 -0
  202. premiere_cli/panel/host/commands/set-graphics-white-luminance.jsx +73 -0
  203. premiere_cli/panel/host/commands/set-item-in-out.jsx +180 -0
  204. premiere_cli/panel/host/commands/set-item-metadata.jsx +134 -0
  205. premiere_cli/panel/host/commands/set-item-offline.jsx +109 -0
  206. premiere_cli/panel/host/commands/set-item-start-time.jsx +139 -0
  207. premiere_cli/panel/host/commands/set-keyframe-interpolation.jsx +186 -0
  208. premiere_cli/panel/host/commands/set-override-frame-rate.jsx +123 -0
  209. premiere_cli/panel/host/commands/set-override-pixel-aspect-ratio.jsx +129 -0
  210. premiere_cli/panel/host/commands/set-poster-frame.jsx +192 -0
  211. premiere_cli/panel/host/commands/set-project-panel-metadata.jsx +69 -0
  212. premiere_cli/panel/host/commands/set-scale-to-frame-size.jsx +101 -0
  213. premiere_cli/panel/host/commands/set-scale-width-height.jsx +140 -0
  214. premiere_cli/panel/host/commands/set-sequence-in-out.jsx +65 -0
  215. premiere_cli/panel/host/commands/set-sequence-settings.jsx +184 -0
  216. premiere_cli/panel/host/commands/set-source-in-out.jsx +98 -0
  217. premiere_cli/panel/host/commands/set-target-track.jsx +91 -0
  218. premiere_cli/panel/host/commands/set-time-interpolation.jsx +141 -0
  219. premiere_cli/panel/host/commands/set-track-mute.jsx +91 -0
  220. premiere_cli/panel/host/commands/set-track-visibility.jsx +94 -0
  221. premiere_cli/panel/host/commands/set-transcode-on-ingest.jsx +78 -0
  222. premiere_cli/panel/host/commands/set-uniform-scale.jsx +104 -0
  223. premiere_cli/panel/host/commands/set-work-area.jsx +76 -0
  224. premiere_cli/panel/host/commands/set-workspace.jsx +35 -0
  225. premiere_cli/panel/host/commands/set-xmp-metadata.jsx +157 -0
  226. premiere_cli/panel/host/commands/slide-edit.jsx +162 -0
  227. premiere_cli/panel/host/commands/slip-edit.jsx +167 -0
  228. premiere_cli/panel/host/commands/split-clip.jsx +144 -0
  229. premiere_cli/panel/host/commands/stabilize-clip.jsx +139 -0
  230. premiere_cli/panel/host/commands/stop-playback.jsx +23 -0
  231. premiere_cli/panel/host/commands/trim-clip.jsx +111 -0
  232. premiere_cli/panel/host/commands/undo.jsx +114 -0
  233. premiere_cli/panel/host/commands/unlink-selection.jsx +106 -0
  234. premiere_cli/panel/host/commands/unnest-sequence.jsx +207 -0
  235. premiere_cli/panel/host/commands/update-marker.jsx +120 -0
  236. premiere_cli/panel/host/index.jsx +1227 -0
  237. premiere_cli/panel/host/presets/default-4k-25fps.sqpreset +63 -0
  238. premiere_cli/panel/index.html +16 -0
  239. premiere_cli/panel/js/cs-interface.js +11 -0
  240. premiere_cli/panel/js/main.js +409 -0
  241. premiere_cli/panel_install.py +220 -0
  242. premiere_cli-0.2.0.dist-info/METADATA +127 -0
  243. premiere_cli-0.2.0.dist-info/RECORD +247 -0
  244. premiere_cli-0.2.0.dist-info/WHEEL +5 -0
  245. premiere_cli-0.2.0.dist-info/entry_points.txt +3 -0
  246. premiere_cli-0.2.0.dist-info/licenses/LICENSE +428 -0
  247. premiere_cli-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,160 @@
1
+ // Command: set-clip-speed → ppb_setClipSpeed
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // resolveTimelineClip, resolveQeClip, ensureQEEnabled,
5
+ // activateSequenceForQE, TICKS_PER_SECOND, ...) are already defined
6
+ // there.
7
+ //
8
+ // Sets a clip's playback speed via QE. LIVE-CALIBRATED 2026-07-17 (see
9
+ // BUILD_FINDINGS.md corrections): the working signature on this build is
10
+ // the 5-arg
11
+ // qeClip.setSpeed(speedMultiplier, ticksString, reverse, false, false)
12
+ // where:
13
+ // - arg1 is a MULTIPLIER (1 = 100%), NOT a percent — and the
14
+ // standard-DOM clip.getSpeed() read-back uses the same scale (a
15
+ // normal clip reads 1, not 100);
16
+ // - arg2 must be a plausible ticks string — garbage there (e.g. the
17
+ // literal "ticks") collapses the clip to ONE FRAME. The clip's own
18
+ // current duration in ticks is passed;
19
+ // - arg3 is the reverse flag (verified via isSpeedReversed()) —
20
+ // negative multipliers do NOT reverse, they clamp to a degenerate
21
+ // state, so reversal must go through this flag;
22
+ // - args 4/5 are unidentified; false/false is the tested-safe value.
23
+ // Speed-up shortens the timeline item to source/speed ROUNDED UP to
24
+ // whole frames (getSpeed() then reads the post-rounding actual — e.g.
25
+ // requesting 50x on a 27.16s clip yields 48.5). Slow-down does NOT
26
+ // extend the item; source usage truncates instead.
27
+ //
28
+ // MUTATION RULE: verified via the STANDARD-DOM clip.getSpeed()/
29
+ // isSpeedReversed() read-back after the QE call — never trusting
30
+ // setSpeed()'s own return value. Because of frame rounding the speed
31
+ // comparison uses a 5% relative tolerance.
32
+
33
+ function ppb_setClipSpeed(argsJson) {
34
+ try {
35
+ var args;
36
+ try {
37
+ args = JSON.parse(argsJson);
38
+ } catch (e) {
39
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
40
+ }
41
+
42
+ if (args.trackType !== "video" && args.trackType !== "audio") {
43
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
44
+ }
45
+ if (typeof args.trackIndex !== "number" || typeof args.clipIndex !== "number") {
46
+ return JSON.stringify({ ok: false, error: "trackIndex and clipIndex are required" });
47
+ }
48
+ if (typeof args.speedPercent !== "number" || args.speedPercent === 0) {
49
+ return JSON.stringify({ ok: false, error: "speedPercent is required and must be non-zero (100 = normal, negative = reversed)" });
50
+ }
51
+
52
+ var reverse = args.speedPercent < 0;
53
+ var multiplier = Math.abs(args.speedPercent) / 100;
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 stdResolved = resolveTimelineClip(seq, args.trackType, args.trackIndex, args.clipIndex);
73
+ if (stdResolved.error) {
74
+ return JSON.stringify({ ok: false, error: stdResolved.error });
75
+ }
76
+ var stdClip = stdResolved.clip;
77
+
78
+ var previousSpeed = null;
79
+ var previousReversed = null;
80
+ try { previousSpeed = stdClip.getSpeed(); } catch (e2) { previousSpeed = null; }
81
+ try { previousReversed = stdClip.isSpeedReversed() === true || stdClip.isSpeedReversed() === 1; } catch (e3) { previousReversed = null; }
82
+
83
+ // arg2 of setSpeed must be a plausible ticks string — the clip's own
84
+ // current timeline duration.
85
+ var durTicks = null;
86
+ try {
87
+ durTicks = String(Math.round((stdClip.end.seconds - stdClip.start.seconds) * TICKS_PER_SECOND));
88
+ } catch (e4) {
89
+ return JSON.stringify({ ok: false, error: "could not read the clip's duration for setSpeed's ticks argument: " + e4.toString() });
90
+ }
91
+
92
+ try {
93
+ ensureQEEnabled();
94
+ activateSequenceForQE(seq);
95
+ } catch (e5) {
96
+ return JSON.stringify({ ok: false, error: "app.enableQE()/sequence activation failed: " + e5.toString() });
97
+ }
98
+ if (typeof qe === "undefined" || !qe.project) {
99
+ return JSON.stringify({ ok: false, error: "QE DOM not available after enableQE()" });
100
+ }
101
+
102
+ var qeSeq;
103
+ try {
104
+ qeSeq = qe.project.getActiveSequence();
105
+ } catch (e6) {
106
+ return JSON.stringify({ ok: false, error: "qe.project.getActiveSequence() failed: " + e6.toString() });
107
+ }
108
+
109
+ var qeResolved = resolveQeClip(qeSeq, args.trackType, args.trackIndex, args.clipIndex);
110
+ if (qeResolved.error) {
111
+ return JSON.stringify({ ok: false, error: qeResolved.error });
112
+ }
113
+ var qeClip = qeResolved.qeClip;
114
+
115
+ try {
116
+ qeClip.setSpeed(multiplier, durTicks, reverse, false, false);
117
+ } catch (e7) {
118
+ return JSON.stringify({
119
+ ok: false,
120
+ error: "qeClip.setSpeed(multiplier, ticksString, reverse, false, false) threw: " + e7.toString(),
121
+ previousSpeed: previousSpeed,
122
+ previousReversed: previousReversed
123
+ });
124
+ }
125
+
126
+ var newSpeed = null;
127
+ var newReversed = null;
128
+ try { newSpeed = stdClip.getSpeed(); } catch (e8) { newSpeed = null; }
129
+ try { newReversed = stdClip.isSpeedReversed() === true || stdClip.isSpeedReversed() === 1; } catch (e9) { newReversed = null; }
130
+
131
+ // Frame rounding shifts the actual applied speed (see header) — 5%
132
+ // relative tolerance on the multiplier, exact match on the flag.
133
+ var speedVerified = newSpeed !== null && multiplier > 0 &&
134
+ Math.abs(newSpeed - multiplier) / multiplier <= 0.05;
135
+ var reverseVerified = newReversed !== null ? (newReversed === reverse) : null;
136
+
137
+ return JSON.stringify({
138
+ ok: true,
139
+ result: {
140
+ sequenceName: seq.name,
141
+ trackType: args.trackType,
142
+ trackIndex: args.trackIndex,
143
+ clipIndex: args.clipIndex,
144
+ clipName: (function () { try { return stdClip.name; } catch (e) { return null; } })(),
145
+ requestedSpeedPercent: args.speedPercent,
146
+ requestedMultiplier: multiplier,
147
+ reverse: reverse,
148
+ previousSpeed: previousSpeed,
149
+ previousReversed: previousReversed,
150
+ newSpeed: newSpeed,
151
+ newSpeedPercent: newSpeed !== null ? newSpeed * 100 : null,
152
+ newReversed: newReversed,
153
+ verified: speedVerified && reverseVerified !== false,
154
+ note: "getSpeed() values are MULTIPLIERS on this build (1 = 100%); the applied speed is frame-rounded, so newSpeed can differ slightly from the request. Slow-motion does not extend the timeline item."
155
+ }
156
+ });
157
+ } catch (e) {
158
+ return JSON.stringify({ ok: false, error: e.toString() });
159
+ }
160
+ }
@@ -0,0 +1,128 @@
1
+ // Command: set-clip-volume → ppb_setClipVolume
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // findVolumeLevelProperty, dbToLinearCalibrated, linearToDbCalibrated, ...)
5
+ // are already defined there.
6
+ //
7
+ // Standard-DOM mutation. Ported from leancoderkavy's premiere-pro-mcp
8
+ // `set_clip_volume` tool (track-targeting.ts), which sets the Volume
9
+ // component's Level property directly to the raw dB number passed in —
10
+ // but PREMIERE_API_NOTES.md is explicit that Level is LINEAR AMPLITUDE, not
11
+ // dB, so setValue(dB) as the reference does is almost certainly wrong on
12
+ // any real build. This command instead converts the requested dB to
13
+ // linear amplitude via hetpatel's empirical calibration for this build
14
+ // family (linear = 10^((dB-15)/20)) before calling setValue().
15
+ //
16
+ // *** CALIBRATION UNCERTAINTY — READ BEFORE TRUSTING THIS COMMAND ***
17
+ // The three reference MCP repos studied for this port do NOT agree on the
18
+ // dB->linear formula: hetpatel's calibrated 10^((dB-15)/20) (used here),
19
+ // leancoderkavy's uncalibrated 10^(dB/20), and ayushozha's "mostly raw dB,
20
+ // docs admit it's linear". None of this has been live-verified against
21
+ // THIS Premiere build — do that before relying on the resulting level
22
+ // sounding correct. Both the raw linear values (previous/requested/new)
23
+ // AND the requested dB are returned so a caller can sanity-check/recalibrate
24
+ // without re-running the mutation.
25
+ function ppb_setClipVolume(argsJson) {
26
+ try {
27
+ var args;
28
+ try {
29
+ args = JSON.parse(argsJson);
30
+ } catch (e) {
31
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
32
+ }
33
+
34
+ if (args.trackType !== "video" && args.trackType !== "audio") {
35
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
36
+ }
37
+ if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
38
+ return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
39
+ }
40
+ if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
41
+ return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
42
+ }
43
+ if (typeof args.db !== "number" || isNaN(args.db)) {
44
+ return JSON.stringify({ ok: false, error: "db must be a number" });
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 trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
65
+ var numTracks = trackCollection.numTracks;
66
+ if (args.trackIndex >= numTracks) {
67
+ return JSON.stringify({
68
+ ok: false,
69
+ error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
70
+ });
71
+ }
72
+
73
+ var track = trackCollection[args.trackIndex];
74
+ var numClips = track.clips.numItems;
75
+ if (args.clipIndex >= numClips) {
76
+ return JSON.stringify({
77
+ ok: false,
78
+ error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
79
+ });
80
+ }
81
+
82
+ var clip = track.clips[args.clipIndex];
83
+ var clipName = null;
84
+ try { clipName = clip.name; } catch (e) { clipName = null; }
85
+
86
+ var levelProp = findVolumeLevelProperty(clip);
87
+ if (!levelProp) {
88
+ return JSON.stringify({ ok: false, error: "could not find Volume/Level property on clip — is this an audio clip?" });
89
+ }
90
+
91
+ var previousLinear = null;
92
+ try { previousLinear = levelProp.getValue(); } catch (e) { previousLinear = null; }
93
+
94
+ var requestedLinear = dbToLinearCalibrated(args.db);
95
+
96
+ try {
97
+ levelProp.setValue(requestedLinear, true);
98
+ } catch (e) {
99
+ return JSON.stringify({ ok: false, error: "levelProp.setValue() failed: " + e.toString() });
100
+ }
101
+
102
+ var newLinear = null;
103
+ try { newLinear = levelProp.getValue(); } catch (e) { newLinear = null; }
104
+
105
+ var verified = newLinear !== null && Math.abs(newLinear - requestedLinear) < 0.0005;
106
+
107
+ var result = {
108
+ sequenceName: seq.name,
109
+ trackType: args.trackType,
110
+ trackIndex: args.trackIndex,
111
+ clipIndex: args.clipIndex,
112
+ clipName: clipName,
113
+ requestedDb: args.db,
114
+ previousValue: previousLinear,
115
+ requestedValue: requestedLinear,
116
+ newValue: newLinear,
117
+ verified: verified,
118
+ previousDbEstimate: linearToDbCalibrated(previousLinear),
119
+ calibrationNote: "Level is LINEAR AMPLITUDE, not dB. Converted via hetpatel's empirical " +
120
+ "calibration linear = 10^((db-15)/20) — UNVERIFIED against this Premiere build; " +
121
+ "other reference repos use different formulas (see file header comment)."
122
+ };
123
+
124
+ return JSON.stringify({ ok: true, result: result });
125
+ } catch (e) {
126
+ return JSON.stringify({ ok: false, error: e.toString() });
127
+ }
128
+ }
@@ -0,0 +1,123 @@
1
+ // Command: set-color-label → ppb_setColorLabel
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
+ // WRITE command — write-side counterpart of get-color-label. Undo is
10
+ // NON-FUNCTIONAL on this build — `previousValue` is the only restoration
11
+ // path. get-color-label degrades honestly when getColorLabel is absent
12
+ // on a build; this command mirrors that for both the getter (used for
13
+ // previousValue/newValue) and the setter itself.
14
+
15
+ function ppbFindItemSetColorLabel_walk(item, args, depth) {
16
+ if (depth > 32) {
17
+ return null;
18
+ }
19
+
20
+ var isBin = false;
21
+ try {
22
+ isBin = typeof ProjectItemType !== "undefined" && item.type === ProjectItemType.BIN;
23
+ } catch (e) {
24
+ isBin = false;
25
+ }
26
+
27
+ var matched = false;
28
+ if (args.nodeId !== null) {
29
+ try { matched = item.nodeId === args.nodeId; } catch (e) { matched = false; }
30
+ } else if (args.name !== null) {
31
+ try { matched = item.name === args.name; } catch (e) { matched = false; }
32
+ }
33
+ if (matched) {
34
+ return item;
35
+ }
36
+
37
+ if (isBin && item.children) {
38
+ for (var i = 0; i < item.children.numItems; i++) {
39
+ var found = ppbFindItemSetColorLabel_walk(item.children[i], args, depth + 1);
40
+ if (found) {
41
+ return found;
42
+ }
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+
48
+ function ppbFindItemSetColorLabel_resolve(args) {
49
+ var root = app.project.rootItem;
50
+ for (var i = 0; i < root.children.numItems; i++) {
51
+ var found = ppbFindItemSetColorLabel_walk(root.children[i], args, 1);
52
+ if (found) {
53
+ return found;
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+
59
+ function ppb_setColorLabel(argsJson) {
60
+ try {
61
+ var args;
62
+ try {
63
+ args = JSON.parse(argsJson);
64
+ } catch (e) {
65
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
66
+ }
67
+
68
+ var hasNodeId = typeof args.nodeId === "string" && args.nodeId.length > 0;
69
+ var hasName = typeof args.name === "string" && args.name.length > 0;
70
+ if (!hasNodeId && !hasName) {
71
+ return JSON.stringify({ ok: false, error: "either nodeId or name is required" });
72
+ }
73
+
74
+ if (typeof args.colorLabel !== "number" || args.colorLabel < 0 || args.colorLabel > 15) {
75
+ return JSON.stringify({ ok: false, error: "colorLabel (integer 0-15) is required" });
76
+ }
77
+
78
+ if (!app.project) {
79
+ return JSON.stringify({ ok: false, error: "no project open" });
80
+ }
81
+
82
+ var item = ppbFindItemSetColorLabel_resolve({
83
+ nodeId: hasNodeId ? args.nodeId : null,
84
+ name: hasNodeId ? null : args.name
85
+ });
86
+ if (!item) {
87
+ return JSON.stringify({ ok: false, error: "no project item found matching the given nodeId/name" });
88
+ }
89
+
90
+ if (typeof item.setColorLabel !== "function") {
91
+ return JSON.stringify({ ok: false, error: "setColorLabel is not available on this Premiere build" });
92
+ }
93
+
94
+ var previousValue = null;
95
+ try { previousValue = item.getColorLabel(); } catch (e) { previousValue = null; }
96
+
97
+ try {
98
+ item.setColorLabel(args.colorLabel);
99
+ } catch (e) {
100
+ return JSON.stringify({ ok: false, error: "setColorLabel() failed: " + e.toString() });
101
+ }
102
+
103
+ var newValue = null;
104
+ try { newValue = item.getColorLabel(); } catch (e) { newValue = null; }
105
+
106
+ var verified = newValue !== null && newValue === args.colorLabel;
107
+
108
+ var result = {
109
+ name: null,
110
+ nodeId: null,
111
+ previousValue: previousValue,
112
+ requestedValue: args.colorLabel,
113
+ newValue: newValue,
114
+ verified: verified
115
+ };
116
+ try { result.name = item.name; } catch (e) { result.name = null; }
117
+ try { result.nodeId = item.nodeId; } catch (e) { result.nodeId = null; }
118
+
119
+ return JSON.stringify({ ok: true, result: result });
120
+ } catch (e) {
121
+ return JSON.stringify({ ok: false, error: e.toString() });
122
+ }
123
+ }
@@ -0,0 +1,155 @@
1
+ // Command: set-color-value → ppb_setColorValue
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // findClipComponent, findComponentProperty, valuesApproximatelyEqual, ...)
5
+ // are already defined there.
6
+ //
7
+ // Standard-DOM mutation. Ported from leancoderkavy's premiere-pro-mcp
8
+ // `set_color_value` tool (advanced.ts), addressed here by
9
+ // trackType/trackIndex/clipIndex + componentName/propertyName (same
10
+ // convention as get-effect-properties/set-effect-property) instead of
11
+ // node_id. Sets a color-typed property (e.g. a Lumetri tint, a title fill
12
+ // color) via prop.setColorValue(alpha, red, green, blue, true) — each
13
+ // channel 0-255, per PREMIERE_API_NOTES.md's Property API block. Mutating
14
+ // — undo is non-functional on this build, so previousValue is the
15
+ // caller's only restoration path.
16
+ function ppb_setColorValue(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 (args.trackType !== "video" && args.trackType !== "audio") {
26
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
27
+ }
28
+ if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
29
+ return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
30
+ }
31
+ if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
32
+ return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
33
+ }
34
+ if (typeof args.componentName !== "string" || !args.componentName) {
35
+ return JSON.stringify({ ok: false, error: "componentName is required" });
36
+ }
37
+ if (typeof args.propertyName !== "string" || !args.propertyName) {
38
+ return JSON.stringify({ ok: false, error: "propertyName is required" });
39
+ }
40
+
41
+ var channels = ["alpha", "red", "green", "blue"];
42
+ for (var c = 0; c < channels.length; c++) {
43
+ var v = args[channels[c]];
44
+ if (typeof v !== "number" || v < 0 || v > 255) {
45
+ return JSON.stringify({ ok: false, error: channels[c] + " must be a number between 0 and 255" });
46
+ }
47
+ }
48
+
49
+ if (!app.project) {
50
+ return JSON.stringify({ ok: false, error: "no project open" });
51
+ }
52
+
53
+ var seq = null;
54
+ if (args.sequenceName && typeof args.sequenceName === "string") {
55
+ seq = findSequenceByName(args.sequenceName);
56
+ if (!seq) {
57
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
58
+ }
59
+ } else {
60
+ seq = app.project.activeSequence;
61
+ if (!seq) {
62
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
63
+ }
64
+ }
65
+
66
+ var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
67
+ var numTracks = trackCollection.numTracks;
68
+ if (args.trackIndex >= numTracks) {
69
+ return JSON.stringify({
70
+ ok: false,
71
+ error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
72
+ });
73
+ }
74
+
75
+ var track = trackCollection[args.trackIndex];
76
+ var numClips = track.clips.numItems;
77
+ if (args.clipIndex >= numClips) {
78
+ return JSON.stringify({
79
+ ok: false,
80
+ error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
81
+ });
82
+ }
83
+
84
+ var clip = track.clips[args.clipIndex];
85
+ var clipName = null;
86
+ try { clipName = clip.name; } catch (e) { clipName = null; }
87
+
88
+ var comp = findClipComponent(clip, [args.componentName], [args.componentName]);
89
+ if (!comp) {
90
+ return JSON.stringify({
91
+ ok: false,
92
+ error: "component \"" + args.componentName + "\" not found on clip (matched against matchName and displayName)"
93
+ });
94
+ }
95
+ var compDisplayName = null;
96
+ try { compDisplayName = comp.displayName; } catch (e) { compDisplayName = null; }
97
+
98
+ var prop = findComponentProperty(comp, [args.propertyName]);
99
+ if (!prop) {
100
+ return JSON.stringify({
101
+ ok: false,
102
+ error: "property \"" + args.propertyName + "\" not found on component \"" + compDisplayName + "\""
103
+ });
104
+ }
105
+
106
+ var previousValue = null;
107
+ try { previousValue = prop.getValue(); } catch (e) { previousValue = null; }
108
+
109
+ var alpha = args.alpha, red = args.red, green = args.green, blue = args.blue;
110
+ var setError = null;
111
+ try {
112
+ prop.setColorValue(alpha, red, green, blue, true);
113
+ } catch (e2) {
114
+ setError = e2.toString();
115
+ }
116
+
117
+ var newValue = null;
118
+ try { newValue = prop.getValue(); } catch (e3) { newValue = null; }
119
+
120
+ var verified = false;
121
+ if (setError === null) {
122
+ if (newValue instanceof Array && newValue.length === 4) {
123
+ verified = valuesApproximatelyEqual(newValue, [alpha, red, green, blue], 1);
124
+ } else {
125
+ // No confirmed cross-build representation for a color value read
126
+ // back via getValue() (packed int vs. [a,r,g,b] array vs. other) —
127
+ // report the call succeeded without throwing, but don't claim a
128
+ // verified numeric match unless it's the expected 4-element array.
129
+ verified = false;
130
+ }
131
+ }
132
+
133
+ return JSON.stringify({
134
+ ok: true,
135
+ result: {
136
+ sequenceName: seq.name,
137
+ trackType: args.trackType,
138
+ trackIndex: args.trackIndex,
139
+ clipIndex: args.clipIndex,
140
+ clipName: clipName,
141
+ componentName: compDisplayName,
142
+ propertyName: args.propertyName,
143
+ requestedColor: { alpha: alpha, red: red, green: green, blue: blue },
144
+ previousValue: previousValue,
145
+ newValue: newValue,
146
+ setError: setError,
147
+ verified: verified,
148
+ note: "verified only asserts a match when newValue round-trips as a 4-element [a,r,g,b] array — " +
149
+ "this property's getValue() representation is unconfirmed on this build."
150
+ }
151
+ });
152
+ } catch (e) {
153
+ return JSON.stringify({ ok: false, error: e.toString() });
154
+ }
155
+ }
@@ -0,0 +1,124 @@
1
+ // Command: set-effect-property → ppb_setEffectProperty
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (findSequenceByName,
4
+ // findClipComponent, findComponentProperty, setComponentProperty, ...) are
5
+ // already defined there.
6
+ //
7
+ // Standard-DOM only — no QE needed. Ported from leancoderkavy's
8
+ // premiere-pro-mcp `set_effect_property` tool (keyframes.ts), addressed
9
+ // here by trackType/trackIndex/clipIndex + componentName/propertyName
10
+ // (same convention as get-effect-properties) instead of node_id. Unlike
11
+ // the reference tool (numbers only), this accepts number/string/boolean
12
+ // via an explicit valueType field for unambiguous typing over the wire —
13
+ // premiere_cli.py coerces --value to the right JSON type before sending
14
+ // based on --value-type. Mutating — undo is non-functional on this build,
15
+ // so previousValue is the caller's only restoration path.
16
+ function ppb_setEffectProperty(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 (args.trackType !== "video" && args.trackType !== "audio") {
26
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
27
+ }
28
+ if (typeof args.trackIndex !== "number" || args.trackIndex < 0 || Math.floor(args.trackIndex) !== args.trackIndex) {
29
+ return JSON.stringify({ ok: false, error: "trackIndex must be a non-negative integer" });
30
+ }
31
+ if (typeof args.clipIndex !== "number" || args.clipIndex < 0 || Math.floor(args.clipIndex) !== args.clipIndex) {
32
+ return JSON.stringify({ ok: false, error: "clipIndex must be a non-negative integer" });
33
+ }
34
+ if (typeof args.componentName !== "string" || !args.componentName) {
35
+ return JSON.stringify({ ok: false, error: "componentName is required" });
36
+ }
37
+ if (typeof args.propertyName !== "string" || !args.propertyName) {
38
+ return JSON.stringify({ ok: false, error: "propertyName is required" });
39
+ }
40
+ if (args.valueType !== "number" && args.valueType !== "string" && args.valueType !== "boolean") {
41
+ return JSON.stringify({ ok: false, error: "valueType must be \"number\", \"string\", or \"boolean\"" });
42
+ }
43
+ if (typeof args.value === "undefined") {
44
+ return JSON.stringify({ ok: false, error: "value is required" });
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 trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
65
+ var numTracks = trackCollection.numTracks;
66
+ if (args.trackIndex >= numTracks) {
67
+ return JSON.stringify({
68
+ ok: false,
69
+ error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)"
70
+ });
71
+ }
72
+
73
+ var track = trackCollection[args.trackIndex];
74
+ var numClips = track.clips.numItems;
75
+ if (args.clipIndex >= numClips) {
76
+ return JSON.stringify({
77
+ ok: false,
78
+ error: "clipIndex " + args.clipIndex + " is out of range — track " + args.trackIndex + " has " + numClips + " clip(s)"
79
+ });
80
+ }
81
+
82
+ var clip = track.clips[args.clipIndex];
83
+ var clipName = null;
84
+ try { clipName = clip.name; } catch (e) { clipName = null; }
85
+
86
+ var comp = findClipComponent(clip, [args.componentName], [args.componentName]);
87
+ if (!comp) {
88
+ return JSON.stringify({
89
+ ok: false,
90
+ error: "component \"" + args.componentName + "\" not found on clip (matched against matchName and displayName)"
91
+ });
92
+ }
93
+ var compDisplayName = null;
94
+ try { compDisplayName = comp.displayName; } catch (e) { compDisplayName = null; }
95
+
96
+ var setResult = setComponentProperty(comp, [args.propertyName], args.value);
97
+ if (!setResult.found) {
98
+ return JSON.stringify({
99
+ ok: false,
100
+ error: "property \"" + args.propertyName + "\" not found on component \"" + compDisplayName + "\""
101
+ });
102
+ }
103
+
104
+ return JSON.stringify({
105
+ ok: true,
106
+ result: {
107
+ sequenceName: seq.name,
108
+ trackType: args.trackType,
109
+ trackIndex: args.trackIndex,
110
+ clipIndex: args.clipIndex,
111
+ clipName: clipName,
112
+ componentName: compDisplayName,
113
+ propertyName: args.propertyName,
114
+ valueType: args.valueType,
115
+ previousValue: setResult.previousValue,
116
+ requestedValue: setResult.requestedValue,
117
+ newValue: setResult.newValue,
118
+ verified: setResult.verified
119
+ }
120
+ });
121
+ } catch (e) {
122
+ return JSON.stringify({ ok: false, error: e.toString() });
123
+ }
124
+ }