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,217 @@
1
+ // Command: import-media → ppb_importMedia
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
+ // Ports the reference project's media.ts import_media tool. Per
7
+ // PREMIERE_API_NOTES.md's "Project / bins / import" section:
8
+ // app.project.importFiles()'s own return value is unreliable, and an
9
+ // unsupported/unrecognized file extension can pop a BLOCKING modal dialog
10
+ // that freezes the whole CEP bridge — so files are pre-filtered against a
11
+ // safe extension allowlist below, and success is verified by diffing
12
+ // nodeId snapshots of the whole project tree before/after the import call,
13
+ // never by trusting importFiles()'s return value. Helper names are
14
+ // prefixed ppbImportMedia_ to avoid colliding with same-purpose helpers in
15
+ // other lazily-loaded command files evaluated into this same global
16
+ // context (import-folder.jsx and import-image-sequence.jsx duplicate this
17
+ // allowlist/snapshot logic under their own prefixes for the same reason).
18
+
19
+ var PPB_IMPORT_MEDIA_ALLOWED_EXTENSIONS = [
20
+ // video
21
+ "mp4", "mov", "avi", "mkv", "webm", "mxf", "m4v", "wmv", "mpg", "mpeg",
22
+ // audio
23
+ "wav", "mp3", "aac", "m4a", "aif", "aiff", "flac", "ogg",
24
+ // image
25
+ "png", "jpg", "jpeg", "gif", "tiff", "tif", "bmp", "psd", "tga", "exr", "dpx", "webp",
26
+ // project
27
+ "prproj"
28
+ ];
29
+
30
+ function ppbImportMedia_extensionOf(path) {
31
+ var lastDot = path.lastIndexOf(".");
32
+ if (lastDot === -1 || lastDot === path.length - 1) {
33
+ return "";
34
+ }
35
+ return path.substring(lastDot + 1).toLowerCase();
36
+ }
37
+
38
+ function ppbImportMedia_isAllowedExtension(path) {
39
+ var ext = ppbImportMedia_extensionOf(path);
40
+ for (var i = 0; i < PPB_IMPORT_MEDIA_ALLOWED_EXTENSIONS.length; i++) {
41
+ if (ext === PPB_IMPORT_MEDIA_ALLOWED_EXTENSIONS[i]) {
42
+ return true;
43
+ }
44
+ }
45
+ return false;
46
+ }
47
+
48
+ // Depth-capped (32) recursive walk collecting every nodeId currently in the
49
+ // project, keyed in a plain object for O(1) diffing. Recurses on
50
+ // children-presence (item.children truthy), NOT an isBin() gate — the
51
+ // ROOT item's type is ROOT, not BIN, and per get-project-item-info.jsx's
52
+ // live-debugged finding, an isBin() gate here would silently stop any
53
+ // walk that starts at the root itself. Snapshot walks in this file always
54
+ // start at rootItem.children, but the same helper is reused by the
55
+ // resolveBinPath below which DOES start at rootItem, so the non-gated
56
+ // form is used uniformly.
57
+ function ppbImportMedia_snapshotNodeIds(item, depth, seen) {
58
+ if (depth > 32) {
59
+ return;
60
+ }
61
+ try {
62
+ if (item.nodeId) {
63
+ seen[item.nodeId] = true;
64
+ }
65
+ } catch (e) {
66
+ // ignore
67
+ }
68
+ if (item.children && item.children.numItems > 0) {
69
+ for (var i = 0; i < item.children.numItems; i++) {
70
+ ppbImportMedia_snapshotNodeIds(item.children[i], depth + 1, seen);
71
+ }
72
+ }
73
+ }
74
+
75
+ function ppbImportMedia_takeSnapshot() {
76
+ var seen = {};
77
+ var root = app.project.rootItem;
78
+ ppbImportMedia_snapshotNodeIds(root, 0, seen);
79
+ return seen;
80
+ }
81
+
82
+ // Finds every item in the current project whose nodeId isn't in
83
+ // `beforeSnapshot` — the newly-imported items. Depth-capped the same way.
84
+ function ppbImportMedia_collectNew(item, depth, beforeSnapshot, out) {
85
+ if (depth > 32) {
86
+ return;
87
+ }
88
+ try {
89
+ if (item.nodeId && !beforeSnapshot[item.nodeId]) {
90
+ var entry = { name: null, nodeId: null, treePath: null, mediaPath: null };
91
+ try { entry.name = item.name; } catch (e) { entry.name = null; }
92
+ try { entry.nodeId = item.nodeId; } catch (e) { entry.nodeId = null; }
93
+ try { entry.treePath = item.treePath; } catch (e) { entry.treePath = null; }
94
+ try { entry.mediaPath = item.getMediaPath(); } catch (e) { entry.mediaPath = null; }
95
+ out.push(entry);
96
+ }
97
+ } catch (e) {
98
+ // ignore
99
+ }
100
+ if (item.children && item.children.numItems > 0) {
101
+ for (var i = 0; i < item.children.numItems; i++) {
102
+ ppbImportMedia_collectNew(item.children[i], depth + 1, beforeSnapshot, out);
103
+ }
104
+ }
105
+ }
106
+
107
+ // Resolves (but does NOT create) a '/'-separated bin path against the
108
+ // project's root bin. Returns {bin} on success or {error} if any segment
109
+ // is missing.
110
+ function ppbImportMedia_resolveBinPath(binPath) {
111
+ var segments = binPath.split("/").filter(function (s) { return s.length > 0; });
112
+ var current = app.project.rootItem;
113
+ for (var i = 0; i < segments.length; i++) {
114
+ var found = null;
115
+ for (var j = 0; j < current.children.numItems; j++) {
116
+ var child = current.children[j];
117
+ if (child.name === segments[i] && typeof ProjectItemType !== "undefined" && child.type === ProjectItemType.BIN) {
118
+ found = child;
119
+ break;
120
+ }
121
+ }
122
+ if (!found) {
123
+ return { error: "bin path segment \"" + segments[i] + "\" not found in \"" + binPath + "\" (target bin must already exist)" };
124
+ }
125
+ current = found;
126
+ }
127
+ return { bin: current };
128
+ }
129
+
130
+ function ppb_importMedia(argsJson) {
131
+ try {
132
+ var args;
133
+ try {
134
+ args = JSON.parse(argsJson);
135
+ } catch (e) {
136
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
137
+ }
138
+
139
+ var filePaths = null;
140
+ if (typeof args.filePaths === "string" && args.filePaths.length > 0) {
141
+ try {
142
+ filePaths = JSON.parse(args.filePaths);
143
+ } catch (e) {
144
+ return JSON.stringify({ ok: false, error: "filePaths must be a JSON array string: " + e.toString() });
145
+ }
146
+ } else if (args.filePaths instanceof Array) {
147
+ filePaths = args.filePaths;
148
+ } else if (typeof args.filePath === "string" && args.filePath.length > 0) {
149
+ filePaths = [args.filePath];
150
+ }
151
+
152
+ if (!filePaths || !(filePaths instanceof Array) || filePaths.length === 0) {
153
+ return JSON.stringify({ ok: false, error: "either filePath (string) or filePaths (JSON array) is required" });
154
+ }
155
+
156
+ if (!app.project) {
157
+ return JSON.stringify({ ok: false, error: "no project open" });
158
+ }
159
+
160
+ var refused = [];
161
+ for (var i = 0; i < filePaths.length; i++) {
162
+ if (!ppbImportMedia_isAllowedExtension(filePaths[i])) {
163
+ refused.push(filePaths[i]);
164
+ }
165
+ }
166
+ if (refused.length > 0) {
167
+ return JSON.stringify({
168
+ ok: false,
169
+ error: "refusing to import file(s) with an unrecognized extension — an unsupported format can pop a " +
170
+ "BLOCKING dialog that freezes the Premiere Bridge panel: " + refused.join(", "),
171
+ refused: refused,
172
+ allowedExtensions: PPB_IMPORT_MEDIA_ALLOWED_EXTENSIONS
173
+ });
174
+ }
175
+
176
+ var targetBin = app.project.rootItem;
177
+ if (typeof args.targetBinPath === "string" && args.targetBinPath.length > 0) {
178
+ var resolved = ppbImportMedia_resolveBinPath(args.targetBinPath);
179
+ if (resolved.error) {
180
+ return JSON.stringify({ ok: false, error: resolved.error });
181
+ }
182
+ targetBin = resolved.bin;
183
+ }
184
+
185
+ var before = ppbImportMedia_takeSnapshot();
186
+
187
+ try {
188
+ app.project.importFiles(filePaths, true, targetBin, false);
189
+ } catch (e) {
190
+ return JSON.stringify({ ok: false, error: "app.project.importFiles() threw: " + e.toString() });
191
+ }
192
+
193
+ var imported = [];
194
+ ppbImportMedia_collectNew(app.project.rootItem, 0, before, imported);
195
+
196
+ if (imported.length === 0) {
197
+ return JSON.stringify({
198
+ ok: false,
199
+ error: "importFiles() did not throw, but no new project item appeared (nodeId-diff found nothing) — " +
200
+ "the file(s) may already be in the project, or the import silently failed",
201
+ requestedFiles: filePaths
202
+ });
203
+ }
204
+
205
+ return JSON.stringify({
206
+ ok: true,
207
+ result: {
208
+ requestedFiles: filePaths,
209
+ targetBinPath: args.targetBinPath || null,
210
+ importedCount: imported.length,
211
+ imported: imported
212
+ }
213
+ });
214
+ } catch (e) {
215
+ return JSON.stringify({ ok: false, error: e.toString() });
216
+ }
217
+ }
@@ -0,0 +1,105 @@
1
+ // Command: import-mogrt-from-library → ppb_importMogrtFromLibrary
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — findSequenceByName,
4
+ // secondsToTicksString are already defined there.
5
+ //
6
+ // Ported from leancoderkavy's premiere-pro-mcp text.ts
7
+ // import_mogrt_from_library, WITH ONE DELIBERATE CORRECTION: that
8
+ // reference tool calls seq.importMGTFromLibrary(mogrtName, startTicks,
9
+ // trackIndex, trackIndex) — omitting a library name entirely — but
10
+ // PREMIERE_API_NOTES.md documents the real signature as
11
+ // seq.importMGTFromLibrary(libName, mogrtName, ticks, v, a), five
12
+ // arguments with the library name first. The reference's own call would
13
+ // pass a mogrt name where the library name belongs, which reads like a
14
+ // bug in that repo rather than an intentional simplification — this port
15
+ // follows PREMIERE_API_NOTES.md's documented signature instead, adding a
16
+ // required libraryName argument the reference's own tool lacks.
17
+ //
18
+ // MUTATION RULE: same as import-mogrt — verified via the target video
19
+ // track's own clip count before/after, never the call's return value
20
+ // (same ambiguous-return-type caveat).
21
+ function ppb_importMogrtFromLibrary(argsJson) {
22
+ try {
23
+ var args;
24
+ try {
25
+ args = JSON.parse(argsJson);
26
+ } catch (e) {
27
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
28
+ }
29
+
30
+ if (typeof args.libraryName !== "string" || !args.libraryName) {
31
+ return JSON.stringify({ ok: false, error: "libraryName is required (PREMIERE_API_NOTES.md documents importMGTFromLibrary as (libName, mogrtName, ticks, v, a) — the reference tool this ports omits it, which this command does not follow)" });
32
+ }
33
+ if (typeof args.mogrtName !== "string" || !args.mogrtName) {
34
+ return JSON.stringify({ ok: false, error: "mogrtName is required" });
35
+ }
36
+ if (typeof args.startSeconds !== "number") {
37
+ return JSON.stringify({ ok: false, error: "startSeconds is required" });
38
+ }
39
+ if (typeof args.videoTrackIndex !== "number") {
40
+ return JSON.stringify({ ok: false, error: "videoTrackIndex is required" });
41
+ }
42
+ if (typeof args.audioTrackIndex !== "number") {
43
+ return JSON.stringify({ ok: false, error: "audioTrackIndex is required" });
44
+ }
45
+
46
+ if (!app.project) {
47
+ return JSON.stringify({ ok: false, error: "no project open" });
48
+ }
49
+
50
+ var seq = null;
51
+ if (args.sequenceName && typeof args.sequenceName === "string") {
52
+ seq = findSequenceByName(args.sequenceName);
53
+ if (!seq) {
54
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
55
+ }
56
+ } else {
57
+ seq = app.project.activeSequence;
58
+ if (!seq) {
59
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
60
+ }
61
+ }
62
+
63
+ var numVideoTracks;
64
+ try { numVideoTracks = seq.videoTracks.numTracks; } catch (e2) { numVideoTracks = 0; }
65
+ if (args.videoTrackIndex >= numVideoTracks) {
66
+ return JSON.stringify({ ok: false, error: "videoTrackIndex " + args.videoTrackIndex + " is out of range — sequence has " + numVideoTracks + " video track(s)" });
67
+ }
68
+ var videoTrack = seq.videoTracks[args.videoTrackIndex];
69
+ var trackClipCountBefore = null;
70
+ try { trackClipCountBefore = videoTrack.clips.numItems; } catch (e3) { trackClipCountBefore = null; }
71
+
72
+ var startTicks = secondsToTicksString(args.startSeconds);
73
+ var importResult = null;
74
+ try {
75
+ importResult = seq.importMGTFromLibrary(args.libraryName, args.mogrtName, startTicks, args.videoTrackIndex, args.audioTrackIndex);
76
+ } catch (e4) {
77
+ return JSON.stringify({ ok: false, error: "seq.importMGTFromLibrary() failed: " + e4.toString() });
78
+ }
79
+
80
+ var trackClipCountAfter = null;
81
+ try { trackClipCountAfter = videoTrack.clips.numItems; } catch (e5) { trackClipCountAfter = null; }
82
+
83
+ var placed = trackClipCountBefore !== null && trackClipCountAfter !== null && trackClipCountAfter > trackClipCountBefore;
84
+
85
+ return JSON.stringify({
86
+ ok: true,
87
+ result: {
88
+ sequenceName: seq.name,
89
+ libraryName: args.libraryName,
90
+ mogrtName: args.mogrtName,
91
+ startSeconds: args.startSeconds,
92
+ videoTrackIndex: args.videoTrackIndex,
93
+ audioTrackIndex: args.audioTrackIndex,
94
+ trackClipCountBefore: trackClipCountBefore,
95
+ trackClipCountAfter: trackClipCountAfter,
96
+ placed: placed,
97
+ verified: placed,
98
+ importReturnValueTruthy: !!importResult,
99
+ note: "libraryName argument added per PREMIERE_API_NOTES.md's documented 5-arg signature — the ported reference tool's own call omits it (see file header comment)."
100
+ }
101
+ });
102
+ } catch (e) {
103
+ return JSON.stringify({ ok: false, error: e.toString() });
104
+ }
105
+ }
@@ -0,0 +1,111 @@
1
+ // Command: import-mogrt → ppb_importMogrt
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — findSequenceByName,
4
+ // secondsToTicksString, timeValueToSeconds are already defined there.
5
+ //
6
+ // Ported from leancoderkavy's premiere-pro-mcp text.ts import_mogrt.
7
+ // Imports a .mogrt file directly onto the timeline via
8
+ // seq.importMGT(mogrtPath, startTicksString, videoTrackIndex,
9
+ // audioTrackIndex).
10
+ //
11
+ // ⚠️ RETURN-VALUE DISCREPANCY: text.ts treats importMGT()'s return value
12
+ // as a boolean ("if (!success) return __error(...)"), but
13
+ // PREMIERE_API_NOTES.md documents it as returning a trackItem object
14
+ // ("seq.importMGT(...) → trackItem"). Both are handled defensively here —
15
+ // the raw return value's type is reported, and if it looks like a
16
+ // trackItem (a non-null object with a readable .name), that's surfaced
17
+ // too — but the PRIMARY verification is independent of either claim: the
18
+ // target video track's own clip count before/after, same MUTATION RULE
19
+ // every other placement command in this panel follows (add-to-timeline,
20
+ // duplicate-clip, ...) rather than trusting an ambiguous return value.
21
+ function ppb_importMogrt(argsJson) {
22
+ try {
23
+ var args;
24
+ try {
25
+ args = JSON.parse(argsJson);
26
+ } catch (e) {
27
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
28
+ }
29
+
30
+ if (typeof args.mogrtPath !== "string" || !args.mogrtPath) {
31
+ return JSON.stringify({ ok: false, error: "mogrtPath is required" });
32
+ }
33
+ if (typeof args.startSeconds !== "number") {
34
+ return JSON.stringify({ ok: false, error: "startSeconds is required" });
35
+ }
36
+ if (typeof args.videoTrackIndex !== "number") {
37
+ return JSON.stringify({ ok: false, error: "videoTrackIndex is required" });
38
+ }
39
+ if (typeof args.audioTrackIndex !== "number") {
40
+ return JSON.stringify({ ok: false, error: "audioTrackIndex is required" });
41
+ }
42
+
43
+ if (!app.project) {
44
+ return JSON.stringify({ ok: false, error: "no project open" });
45
+ }
46
+
47
+ var seq = null;
48
+ if (args.sequenceName && typeof args.sequenceName === "string") {
49
+ seq = findSequenceByName(args.sequenceName);
50
+ if (!seq) {
51
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
52
+ }
53
+ } else {
54
+ seq = app.project.activeSequence;
55
+ if (!seq) {
56
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
57
+ }
58
+ }
59
+
60
+ var numVideoTracks;
61
+ try { numVideoTracks = seq.videoTracks.numTracks; } catch (e2) { numVideoTracks = 0; }
62
+ if (args.videoTrackIndex >= numVideoTracks) {
63
+ return JSON.stringify({ ok: false, error: "videoTrackIndex " + args.videoTrackIndex + " is out of range — sequence has " + numVideoTracks + " video track(s)" });
64
+ }
65
+ var videoTrack = seq.videoTracks[args.videoTrackIndex];
66
+ var trackClipCountBefore = null;
67
+ try { trackClipCountBefore = videoTrack.clips.numItems; } catch (e3) { trackClipCountBefore = null; }
68
+
69
+ var startTicks = secondsToTicksString(args.startSeconds);
70
+ var importResult = null;
71
+ try {
72
+ importResult = seq.importMGT(args.mogrtPath, startTicks, args.videoTrackIndex, args.audioTrackIndex);
73
+ } catch (e4) {
74
+ return JSON.stringify({ ok: false, error: "seq.importMGT() failed: " + e4.toString() });
75
+ }
76
+
77
+ var trackClipCountAfter = null;
78
+ try { trackClipCountAfter = videoTrack.clips.numItems; } catch (e5) { trackClipCountAfter = null; }
79
+
80
+ var placed = trackClipCountBefore !== null && trackClipCountAfter !== null && trackClipCountAfter > trackClipCountBefore;
81
+
82
+ var returnValueType = typeof importResult;
83
+ var returnValueIsObject = importResult !== null && typeof importResult === "object";
84
+ var returnValueName = null;
85
+ if (returnValueIsObject) {
86
+ try { returnValueName = importResult.name; } catch (e6) { returnValueName = null; }
87
+ }
88
+ var returnValueTruthy = !!importResult;
89
+
90
+ return JSON.stringify({
91
+ ok: true,
92
+ result: {
93
+ sequenceName: seq.name,
94
+ mogrtPath: args.mogrtPath,
95
+ startSeconds: args.startSeconds,
96
+ videoTrackIndex: args.videoTrackIndex,
97
+ audioTrackIndex: args.audioTrackIndex,
98
+ trackClipCountBefore: trackClipCountBefore,
99
+ trackClipCountAfter: trackClipCountAfter,
100
+ placed: placed,
101
+ verified: placed,
102
+ importReturnValueType: returnValueType,
103
+ importReturnValueTruthy: returnValueTruthy,
104
+ importReturnValueName: returnValueName,
105
+ note: "verified via the target video track's clip count, not importMGT()'s own return value — text.ts treats that return as a boolean while PREMIERE_API_NOTES.md documents it as a trackItem; both are reported above but neither is trusted for verification."
106
+ }
107
+ });
108
+ } catch (e) {
109
+ return JSON.stringify({ ok: false, error: e.toString() });
110
+ }
111
+ }
@@ -0,0 +1,80 @@
1
+ // Command: import-sequences-from-project → ppb_importSequencesFromProject
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context.
4
+ //
5
+ // Ported from leancoderkavy/premiere-pro-mcp's project.ts
6
+ // import_sequences. Calls app.project.importSequences(prprojPath,
7
+ // [seqIds]) per PREMIERE_API_NOTES.md's Sequences table; if sequenceIds
8
+ // is omitted, calls the one-arg form (documented by the reference tool
9
+ // as "imports all sequences"). File-exists check on projectPath first,
10
+ // same cheap guard as open-project.jsx. Verified by a project sequence-
11
+ // count increase (never trusting the call's own return value) — cannot
12
+ // name which sequences were imported beyond that (importSequences has no
13
+ // documented return value naming them).
14
+
15
+ function ppb_importSequencesFromProject(argsJson) {
16
+ try {
17
+ var args;
18
+ try {
19
+ args = JSON.parse(argsJson);
20
+ } catch (e) {
21
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
22
+ }
23
+
24
+ if (!args.projectPath || typeof args.projectPath !== "string") {
25
+ return JSON.stringify({ ok: false, error: "projectPath is required" });
26
+ }
27
+
28
+ var file = new File(args.projectPath);
29
+ if (!file.exists) {
30
+ return JSON.stringify({ ok: false, error: "no file exists at projectPath: " + args.projectPath });
31
+ }
32
+
33
+ if (!app.project) {
34
+ return JSON.stringify({ ok: false, error: "no project open" });
35
+ }
36
+ if (typeof app.project.importSequences !== "function") {
37
+ return JSON.stringify({ ok: false, error: "importSequences is not available on this Premiere build" });
38
+ }
39
+
40
+ var hasIds = Object.prototype.toString.call(args.sequenceIds) === "[object Array]" && args.sequenceIds.length > 0;
41
+
42
+ var countBefore = app.project.sequences.numSequences;
43
+
44
+ try {
45
+ if (hasIds) {
46
+ app.project.importSequences(args.projectPath, args.sequenceIds);
47
+ } else {
48
+ app.project.importSequences(args.projectPath);
49
+ }
50
+ } catch (e) {
51
+ return JSON.stringify({ ok: false, error: "importSequences() failed: " + e.toString() });
52
+ }
53
+
54
+ var countAfter = app.project.sequences.numSequences;
55
+ var imported = countAfter > countBefore;
56
+
57
+ if (!imported) {
58
+ return JSON.stringify({
59
+ ok: false,
60
+ error: "importSequences() did not throw, but the project's sequence count did not increase",
61
+ countBefore: countBefore,
62
+ countAfter: countAfter
63
+ });
64
+ }
65
+
66
+ return JSON.stringify({
67
+ ok: true,
68
+ result: {
69
+ imported: true,
70
+ projectPath: args.projectPath,
71
+ sequenceIds: hasIds ? args.sequenceIds : null,
72
+ allSequences: !hasIds,
73
+ countBefore: countBefore,
74
+ countAfter: countAfter
75
+ }
76
+ });
77
+ } catch (e) {
78
+ return JSON.stringify({ ok: false, error: e.toString() });
79
+ }
80
+ }
@@ -0,0 +1,162 @@
1
+ // Command: insert-from-source → ppb_insertFromSource
2
+ // Loaded lazily by ppb_dispatch (host/index.jsx) on first use, into the
3
+ // same global ExtendScript context — shared helpers (secondsToTicksString,
4
+ // timeValueToSeconds, serializeTrackItem, findSequenceByName,
5
+ // ppbAddToTimeline_cleanupLinkedAudio) are already defined there.
6
+ //
7
+ // Ported from leancoderkavy's premiere-pro-mcp source-monitor.ts
8
+ // insert_from_source — a 3-point insert edit of whatever clip is open in
9
+ // the Source Monitor (its own in/out points, set via set-source-in-out,
10
+ // combine with the sequence's insertClip() call) at either the given
11
+ // atSeconds or the sequence's current playhead. -1 is passed for the
12
+ // non-addressed track index, same convention as add-to-timeline.
13
+ //
14
+ // ⚠️ Same auto-linked-audio trap as add-to-timeline: a video placement
15
+ // whose source item also carries audio can silently land linked audio on
16
+ // some audio track even with audioTrackIndex -1. The shared cleanup
17
+ // helper (ppbAddToTimeline_cleanupLinkedAudio, host/index.jsx) is reused
18
+ // here unchanged for video placements.
19
+ //
20
+ // MUTATION RULE: verified the same way as add-to-timeline — never trust
21
+ // insertClip()'s own return value. LIVE FINDING (add-to-timeline,
22
+ // 2026-07-17): insertClip/overwriteClip IGNORE their track index argument
23
+ // on this build, so the actual landing track is discovered by re-scanning
24
+ // the timeline afterward and reported alongside trackHonored, exactly like
25
+ // add-to-timeline.
26
+ function ppb_insertFromSource(argsJson) {
27
+ try {
28
+ var args;
29
+ try {
30
+ args = JSON.parse(argsJson);
31
+ } catch (e) {
32
+ return JSON.stringify({ ok: false, error: "invalid args JSON: " + e.toString() });
33
+ }
34
+
35
+ if (args.trackType !== "video" && args.trackType !== "audio") {
36
+ return JSON.stringify({ ok: false, error: "trackType must be \"video\" or \"audio\"" });
37
+ }
38
+ if (typeof args.trackIndex !== "number") {
39
+ return JSON.stringify({ ok: false, error: "trackIndex is required" });
40
+ }
41
+
42
+ if (!app.project) {
43
+ return JSON.stringify({ ok: false, error: "no project open" });
44
+ }
45
+
46
+ var seq = null;
47
+ if (args.sequenceName && typeof args.sequenceName === "string") {
48
+ seq = findSequenceByName(args.sequenceName);
49
+ if (!seq) {
50
+ return JSON.stringify({ ok: false, error: "no sequence named \"" + args.sequenceName + "\" is open" });
51
+ }
52
+ } else {
53
+ seq = app.project.activeSequence;
54
+ if (!seq) {
55
+ return JSON.stringify({ ok: false, error: "no active sequence, and no sequenceName given" });
56
+ }
57
+ }
58
+
59
+ var item = null;
60
+ try {
61
+ item = app.sourceMonitor.getProjectItem();
62
+ } catch (e2) {
63
+ return JSON.stringify({ ok: false, error: "app.sourceMonitor.getProjectItem() failed: " + e2.toString() });
64
+ }
65
+ if (!item) {
66
+ return JSON.stringify({ ok: false, error: "no clip open in Source Monitor" });
67
+ }
68
+ var itemNodeId = null;
69
+ try { itemNodeId = item.nodeId; } catch (e3) { itemNodeId = null; }
70
+
71
+ var atSeconds = null;
72
+ var posTicks = null;
73
+ if (typeof args.atSeconds === "number" && !isNaN(args.atSeconds)) {
74
+ atSeconds = args.atSeconds;
75
+ posTicks = secondsToTicksString(atSeconds);
76
+ } else {
77
+ try {
78
+ var playerPos = seq.getPlayerPosition();
79
+ posTicks = playerPos.ticks;
80
+ atSeconds = timeValueToSeconds(playerPos);
81
+ } catch (e4) {
82
+ return JSON.stringify({ ok: false, error: "atSeconds was not given and seq.getPlayerPosition() failed: " + e4.toString() });
83
+ }
84
+ }
85
+
86
+ var trackCollection = args.trackType === "video" ? seq.videoTracks : seq.audioTracks;
87
+ var numTracks;
88
+ try { numTracks = trackCollection.numTracks; } catch (e5) { numTracks = 0; }
89
+ if (args.trackIndex >= numTracks) {
90
+ return JSON.stringify({ ok: false, error: "trackIndex " + args.trackIndex + " is out of range — sequence has " + numTracks + " " + args.trackType + " track(s)" });
91
+ }
92
+ var targetTrack = trackCollection[args.trackIndex];
93
+ var trackClipCountBefore = null;
94
+ try { trackClipCountBefore = targetTrack.clips.numItems; } catch (e6) { trackClipCountBefore = null; }
95
+
96
+ var vIdx = args.trackType === "video" ? args.trackIndex : -1;
97
+ var aIdx = args.trackType === "audio" ? args.trackIndex : -1;
98
+
99
+ try {
100
+ seq.insertClip(item, posTicks, vIdx, aIdx);
101
+ } catch (e7) {
102
+ return JSON.stringify({ ok: false, error: "seq.insertClip() failed: " + e7.toString() });
103
+ }
104
+
105
+ var trackClipCountAfter = null;
106
+ try { trackClipCountAfter = targetTrack.clips.numItems; } catch (e8) { trackClipCountAfter = null; }
107
+
108
+ var toleranceSeconds = 0.1;
109
+ function ppbInsertFromSource_locate() {
110
+ try {
111
+ for (var t2 = 0; t2 < trackCollection.numTracks; t2++) {
112
+ var scanTrack = trackCollection[t2];
113
+ for (var c2 = 0; c2 < scanTrack.clips.numItems; c2++) {
114
+ var candidate = scanTrack.clips[c2];
115
+ var candNodeId = null;
116
+ try { candNodeId = candidate.projectItem.nodeId; } catch (e9) { candNodeId = null; }
117
+ if (candNodeId !== itemNodeId) {
118
+ continue;
119
+ }
120
+ var candStart = null;
121
+ try { candStart = timeValueToSeconds(candidate.start); } catch (e10) { candStart = null; }
122
+ if (candStart !== null && Math.abs(candStart - atSeconds) <= toleranceSeconds) {
123
+ return serializeTrackItem(candidate, t2, c2);
124
+ }
125
+ }
126
+ }
127
+ } catch (e11) {
128
+ // fall through
129
+ }
130
+ return null;
131
+ }
132
+
133
+ var placedClip = ppbInsertFromSource_locate();
134
+ var trackHonored = placedClip !== null && placedClip.trackIndex === args.trackIndex;
135
+
136
+ var linkedAudioCleanup = { performed: false, removedCount: 0, removed: [] };
137
+ if (args.trackType === "video") {
138
+ var removedList = ppbAddToTimeline_cleanupLinkedAudio(seq, itemNodeId, atSeconds, toleranceSeconds);
139
+ linkedAudioCleanup = { performed: true, removedCount: removedList.length, removed: removedList };
140
+ }
141
+
142
+ return JSON.stringify({
143
+ ok: true,
144
+ result: {
145
+ sequenceName: seq.name,
146
+ inserted: true,
147
+ trackType: args.trackType,
148
+ requestedTrackIndex: args.trackIndex,
149
+ actualTrackIndex: placedClip !== null ? placedClip.trackIndex : null,
150
+ trackHonored: trackHonored,
151
+ atSeconds: atSeconds,
152
+ item: { name: (function () { try { return item.name; } catch (e) { return null; } })(), nodeId: itemNodeId },
153
+ placedClip: placedClip,
154
+ trackClipCountBefore: trackClipCountBefore,
155
+ trackClipCountAfter: trackClipCountAfter,
156
+ linkedAudioCleanup: linkedAudioCleanup
157
+ }
158
+ });
159
+ } catch (e) {
160
+ return JSON.stringify({ ok: false, error: e.toString() });
161
+ }
162
+ }