davinci-resolve-mcp 2.63.2 → 2.64.0

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  Release history for the DaVinci Resolve MCP Server. The latest release is summarized in the root README; older entries live here to keep the README focused.
4
4
 
5
+ ## What's New in v2.64.0
6
+
7
+ Adds opt-in support for DaVinci Resolve's **Network** external-scripting mode
8
+ (PR #91… correction: PR #94, by @double2tea), so the MCP can drive a Resolve
9
+ instance addressed by IP — including a Resolve running on the same machine with
10
+ `External scripting using = Network`. Contributed in PR #94 by @double2tea,
11
+ with two additional connection sites hardened during adoption. Local mode is
12
+ unchanged and remains the default.
13
+
14
+ ### Added
15
+
16
+ - **Resolve Network scripting mode** — set `RESOLVE_SCRIPT_HOST` to the Resolve
17
+ host IP (`127.0.0.1` on the same machine) to route connections through
18
+ Resolve's explicit IP-targeted `scriptapp("Resolve", host, timeout)` overload.
19
+ `RESOLVE_SCRIPT_TIMEOUT` (positive finite seconds, default 5) bounds the
20
+ connection wait. When `RESOLVE_SCRIPT_HOST` is absent, the server uses the
21
+ one-argument Local discovery exactly as before. A shared `connect_resolve`
22
+ helper centralizes this behavior; the compound server, granular server,
23
+ analysis dashboard, `scripts/doctor.py`, and the installer's post-install
24
+ connection probe all route through it. The installer copies
25
+ `RESOLVE_SCRIPT_HOST`/`RESOLVE_SCRIPT_TIMEOUT` into generated client configs
26
+ when present in its environment.
27
+ - **`doctor.py` Network flags** — `python3 scripts/doctor.py --resolve-host
28
+ <ip> [--resolve-timeout <seconds>]` runs the read-only connection check
29
+ against a Network-mode host.
30
+
31
+ ### Security
32
+
33
+ - Network scripting permits remote control of Resolve. Documentation (SKILL.md,
34
+ install.md) advises using Local mode when remote access is unnecessary, and
35
+ otherwise restricting access with host firewall and network controls.
36
+
37
+ ### Validation
38
+
39
+ - Live-validated on DaVinci Resolve Studio 19.1.3.7: Local mode (one-argument
40
+ discovery) and Network mode (`--resolve-host 127.0.0.1 --resolve-timeout 8`)
41
+ both connect through the shared `connect_resolve` helper. PR author validated
42
+ against Studio 20.3.2.9 in Network mode. Full offline suite: 1514 tests.
43
+
5
44
  ## What's New in v2.63.2
6
45
 
7
46
  Installer fix for Windows MSIX builds of Claude Desktop (issue #93, reported by
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DaVinci Resolve MCP Server
2
2
 
3
- [![Version](https://img.shields.io/badge/version-2.63.2-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
3
+ [![Version](https://img.shields.io/badge/version-2.64.0-blue.svg)](https://github.com/samuelgursky/davinci-resolve-mcp/releases)
4
4
  [![npm](https://img.shields.io/npm/v/davinci-resolve-mcp.svg?label=npm&color=CB3837)](https://www.npmjs.com/package/davinci-resolve-mcp)
5
5
  [![API Coverage](https://img.shields.io/badge/API%20Coverage-100%25-brightgreen.svg)](docs/reference/api-coverage.md)
6
6
  [![Tools](https://img.shields.io/badge/MCP%20Tools-34%20(341%20full)-blue.svg)](#server-modes)
package/docs/SKILL.md CHANGED
@@ -14,8 +14,14 @@ session — projects, timelines, clips, color grading, Fusion compositions, audi
14
14
  render queues, and more — through natural language.
15
15
 
16
16
  DaVinci Resolve must be running with **Preferences > General > "External scripting
17
- using"** set to **Local**. The server auto-launches Resolve if it is not running,
18
- but that first connection can take up to 60 seconds.
17
+ using"** set to **Local**, or set to **Network** with `RESOLVE_SCRIPT_HOST`
18
+ configured to the Resolve host IP (use `127.0.0.1` on the same machine). The
19
+ server auto-launches Resolve if it is not running, but that first connection can
20
+ take up to 60 seconds.
21
+
22
+ Network scripting permits remote control of Resolve. Use Local mode when remote
23
+ access is unnecessary; otherwise restrict access with host firewall and network
24
+ controls.
19
25
 
20
26
  **Session-start update note.** The first `resolve_control(action="get_version")`
21
27
  of a session returns an `mcp` block with the cached update check
package/docs/install.md CHANGED
@@ -7,7 +7,9 @@ This guide covers Resolve requirements, the universal installer, supported MCP c
7
7
  - **DaVinci Resolve Studio** 18.5+ (macOS, Windows, or Linux) — the free edition does not support external scripting
8
8
  - **Python 3.10+** (the MCP SDK requires 3.10). **3.10–3.12 is the lowest-risk
9
9
  choice**; 3.13/3.14 also work on recent Resolve builds — see below
10
- - DaVinci Resolve running with **Preferences > General > "External scripting using"** set to **Local**
10
+ - DaVinci Resolve running with **Preferences > General > "External scripting using"**
11
+ set to **Local**, or **Network** with `RESOLVE_SCRIPT_HOST` set to the Resolve
12
+ host IP (`127.0.0.1` when Resolve and the MCP run on the same machine)
11
13
 
12
14
  > **Python 3.13 / 3.14:** these are **allowed** — setup will use them and warn.
13
15
  > Python 3.14 is verified working against DaVinci Resolve Studio 20.3.2. On
@@ -170,6 +172,26 @@ If you prefer to set things up yourself, add to your MCP client config:
170
172
 
171
173
  On Windows, installer-generated configs also include `PYTHONHOME`. That scopes Resolve's Python binding to the selected interpreter and avoids the Resolve 20.3 multi-Python crash reported in [Issue #26](https://github.com/samuelgursky/davinci-resolve-mcp/issues/26).
172
174
 
175
+ For Resolve's **Network** scripting mode, add
176
+ `"RESOLVE_SCRIPT_HOST": "127.0.0.1"` to the `env` object above, replacing the
177
+ address when Resolve runs on another host. When this variable is present, the
178
+ server uses Resolve's explicit IP-targeted `scriptapp` call with a bounded
179
+ connection timeout. Set `RESOLVE_SCRIPT_TIMEOUT` to override the default
180
+ five-second timeout with a positive finite number of seconds. The installer
181
+ includes both values in generated client configs when they are present in its
182
+ environment.
183
+
184
+ Network scripting permits remote control of Resolve. Prefer Local mode when
185
+ remote access is unnecessary; otherwise restrict access with host firewall and
186
+ network controls.
187
+
188
+ Run the read-only doctor against Network mode explicitly:
189
+
190
+ ```bash
191
+ python3 scripts/doctor.py --resolve-host 127.0.0.1
192
+ python3 scripts/doctor.py --resolve-host resolve.example.test --resolve-timeout 12.5
193
+ ```
194
+
173
195
  When the compound server is running, `resolve_control(action="get_version")`
174
196
  includes the local MCP version, the last update-check status, and the current
175
197
  update decision under the `mcp` key. `resolve_control(action="mcp_update_status",
package/install.py CHANGED
@@ -15,6 +15,7 @@ Usage:
15
15
 
16
16
  import argparse
17
17
  import json
18
+ import math
18
19
  import os
19
20
  import platform
20
21
  import shutil
@@ -35,7 +36,7 @@ from src.utils.update_check import (
35
36
 
36
37
  # ─── Version ──────────────────────────────────────────────────────────────────
37
38
 
38
- VERSION = "2.63.2"
39
+ VERSION = "2.64.0"
39
40
  # Only hard floor: mcp[cli] requires Python 3.10+. There is no upper bound —
40
41
  # Resolve's scripting bridge loads into newer interpreters on recent builds
41
42
  # (Python 3.14 verified against Resolve Studio 20.3.2). Older Resolve builds
@@ -474,6 +475,13 @@ def build_server_env(python_path, api_path, lib_path, system=SYSTEM, python_home
474
475
  if system == "Windows":
475
476
  env["PYTHONHOME"] = str(python_home or get_python_base_install(python_path))
476
477
 
478
+ host = os.environ.get("RESOLVE_SCRIPT_HOST")
479
+ if host:
480
+ env["RESOLVE_SCRIPT_HOST"] = host
481
+ timeout = os.environ.get("RESOLVE_SCRIPT_TIMEOUT")
482
+ if timeout:
483
+ env["RESOLVE_SCRIPT_TIMEOUT"] = timeout
484
+
477
485
  return env
478
486
 
479
487
 
@@ -810,12 +818,21 @@ def verify_resolve_connection(python_path, api_path, lib_path):
810
818
 
811
819
  env = {**os.environ, **build_server_env(python_path, api_path, lib_path)}
812
820
  modules_path = env["PYTHONPATH"]
821
+ repo_root = str(Path(__file__).resolve().parent)
822
+ # Route through connect_resolve so Network mode (RESOLVE_SCRIPT_HOST, propagated
823
+ # into env by build_server_env) uses the explicit IP-targeted overload. Fall
824
+ # back to Local-mode discovery if the helper cannot be imported.
813
825
  test_script = textwrap.dedent(f"""\
814
826
  import sys
815
827
  sys.path.insert(0, {modules_path!r})
828
+ sys.path.insert(0, {repo_root!r})
816
829
  try:
817
830
  import DaVinciResolveScript as dvr
818
- resolve = dvr.scriptapp('Resolve')
831
+ try:
832
+ from src.utils.resolve_connection import connect_resolve
833
+ except Exception:
834
+ connect_resolve = lambda mod: mod.scriptapp('Resolve')
835
+ resolve = connect_resolve(dvr)
819
836
  if resolve:
820
837
  name = resolve.GetProductName()
821
838
  ver = resolve.GetVersionString()
@@ -828,12 +845,22 @@ def verify_resolve_connection(python_path, api_path, lib_path):
828
845
  print(f"ERROR: {{e}}")
829
846
  """)
830
847
 
848
+ process_timeout = 10.0
849
+ configured_timeout = env.get("RESOLVE_SCRIPT_TIMEOUT")
850
+ if configured_timeout:
851
+ try:
852
+ network_timeout = float(configured_timeout)
853
+ if math.isfinite(network_timeout) and network_timeout > 0:
854
+ process_timeout = max(process_timeout, network_timeout + 2)
855
+ except ValueError:
856
+ pass
857
+
831
858
  try:
832
859
  result = subprocess.run(
833
860
  [str(python_path), "-c", test_script],
834
861
  capture_output=True,
835
862
  text=True,
836
- timeout=10,
863
+ timeout=process_timeout,
837
864
  env=env,
838
865
  )
839
866
  output = result.stdout.strip() or result.stderr.strip()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "davinci-resolve-mcp",
3
- "version": "2.63.2",
3
+ "version": "2.64.0",
4
4
  "description": "NPM bootstrapper for the DaVinci Resolve MCP Server.",
5
5
  "license": "MIT",
6
6
  "author": "Samuel Gursky <samgursky@gmail.com>",
package/scripts/doctor.py CHANGED
@@ -7,16 +7,19 @@ mutating anything. Prints OK/WARN/FAIL lines (or JSON with --json) and exits
7
7
  nonzero only when a FAIL is present.
8
8
 
9
9
  Run: `python3 scripts/doctor.py`
10
+ Network mode: `python3 scripts/doctor.py --resolve-host 127.0.0.1`
10
11
 
11
12
  Overridable via environment: DAVINCI_MCP_REPO, DAVINCI_MCP_PYTHON,
12
13
  CODEX_HOME, CLAUDE_DESKTOP_CONFIG, RESOLVE_APP, RESOLVE_SCRIPT_API,
13
- RESOLVE_SCRIPT_MODULES, RESOLVE_SCRIPT_LIB.
14
+ RESOLVE_SCRIPT_MODULES, RESOLVE_SCRIPT_LIB, RESOLVE_SCRIPT_HOST,
15
+ RESOLVE_SCRIPT_TIMEOUT.
14
16
  """
15
17
 
16
18
  from __future__ import annotations
17
19
 
18
20
  import argparse
19
21
  import json
22
+ import math
20
23
  import os
21
24
  import re
22
25
  import subprocess
@@ -128,26 +131,41 @@ def git_head() -> str:
128
131
  return head["stdout"] or head["stderr"] or "git describe produced no output"
129
132
 
130
133
 
131
- def resolve_probe() -> dict[str, Any]:
134
+ def resolve_probe(
135
+ resolve_host: str | None = None,
136
+ resolve_timeout: float | None = None,
137
+ ) -> dict[str, Any]:
132
138
  if not PYTHON.exists():
133
139
  return {"import_ok": False, "error": f"{PYTHON} is missing"}
134
140
 
135
141
  code = f"""
136
142
  import json
137
143
  import sys
144
+ sys.path.insert(0, {str(REPO)!r})
138
145
  sys.path.insert(0, {str(RESOLVE_MODULES)!r})
139
146
  try:
140
147
  import DaVinciResolveScript as dvr
141
- resolve = dvr.scriptapp("Resolve")
142
- payload = {{
143
- "import_ok": True,
144
- "module": getattr(dvr, "__file__", None),
145
- "resolve_connected": bool(resolve),
146
- "product": resolve.GetProductName() if resolve else None,
147
- "version": resolve.GetVersionString() if resolve else None,
148
- }}
148
+ from src.utils.resolve_connection import connect_resolve
149
149
  except Exception as exc:
150
150
  payload = {{"import_ok": False, "error": repr(exc)}}
151
+ else:
152
+ try:
153
+ resolve = connect_resolve(dvr)
154
+ except Exception as exc:
155
+ payload = {{
156
+ "import_ok": True,
157
+ "module": getattr(dvr, "__file__", None),
158
+ "resolve_connected": False,
159
+ "connection_error": repr(exc),
160
+ }}
161
+ else:
162
+ payload = {{
163
+ "import_ok": True,
164
+ "module": getattr(dvr, "__file__", None),
165
+ "resolve_connected": bool(resolve),
166
+ "product": resolve.GetProductName() if resolve else None,
167
+ "version": resolve.GetVersionString() if resolve else None,
168
+ }}
151
169
  print(json.dumps(payload))
152
170
  """
153
171
  env = {
@@ -156,7 +174,26 @@ print(json.dumps(payload))
156
174
  "RESOLVE_SCRIPT_LIB": str(RESOLVE_LIB),
157
175
  "PYTHONPATH": str(RESOLVE_MODULES),
158
176
  }
159
- proc = subprocess.run([str(PYTHON), "-c", code], capture_output=True, text=True, timeout=12, env=env)
177
+ if resolve_host is not None:
178
+ env["RESOLVE_SCRIPT_HOST"] = resolve_host
179
+ if resolve_timeout is not None:
180
+ env["RESOLVE_SCRIPT_TIMEOUT"] = str(resolve_timeout)
181
+ process_timeout = 12.0
182
+ configured_timeout = env.get("RESOLVE_SCRIPT_TIMEOUT")
183
+ if configured_timeout:
184
+ try:
185
+ network_timeout = float(configured_timeout)
186
+ if math.isfinite(network_timeout) and network_timeout > 0:
187
+ process_timeout = max(process_timeout, network_timeout + 2)
188
+ except ValueError:
189
+ pass
190
+ proc = subprocess.run(
191
+ [str(PYTHON), "-c", code],
192
+ capture_output=True,
193
+ text=True,
194
+ timeout=process_timeout,
195
+ env=env,
196
+ )
160
197
  output = (proc.stdout or proc.stderr).strip()
161
198
  try:
162
199
  payload = json.loads(output)
@@ -166,7 +203,10 @@ print(json.dumps(payload))
166
203
  return payload
167
204
 
168
205
 
169
- def collect() -> list[dict[str, str]]:
206
+ def collect(
207
+ resolve_host: str | None = None,
208
+ resolve_timeout: float | None = None,
209
+ ) -> list[dict[str, str]]:
170
210
  results: list[dict[str, str]] = []
171
211
 
172
212
  check(results, "OK" if REPO.exists() else "FAIL", "MCP checkout", str(REPO))
@@ -186,18 +226,27 @@ def collect() -> list[dict[str, str]]:
186
226
  pyver = run([str(PYTHON), "--version"]) if PYTHON.exists() else {"ok": False, "stdout": "", "stderr": "missing"}
187
227
  check(results, "OK" if pyver["ok"] else "FAIL", "Python version", pyver["stdout"] or pyver["stderr"])
188
228
 
189
- probe = resolve_probe()
229
+ probe = resolve_probe(resolve_host, resolve_timeout)
190
230
  if probe.get("import_ok"):
191
231
  check(results, "OK", "DaVinciResolveScript import", str(probe.get("module")))
192
232
  if probe.get("resolve_connected"):
193
233
  detail = f"{probe.get('product')} {probe.get('version')}"
194
234
  check(results, "OK", "Resolve scripting connection", detail)
235
+ elif probe.get("connection_error"):
236
+ check(
237
+ results,
238
+ "FAIL",
239
+ "Resolve scripting connection",
240
+ str(probe["connection_error"]),
241
+ )
195
242
  else:
196
243
  check(
197
244
  results,
198
245
  "WARN",
199
246
  "Resolve scripting connection",
200
- 'Module import worked, but scriptapp("Resolve") returned no object. Open DaVinci Resolve Studio, set Preferences > General > External scripting using = Local, and restart Resolve.',
247
+ "Module import worked, but scriptapp returned no object. Use "
248
+ "External scripting = Local, or Network with --resolve-host "
249
+ "set to the Resolve host IP, then restart Resolve.",
201
250
  )
202
251
  else:
203
252
  check(results, "FAIL", "DaVinciResolveScript import", str(probe.get("error")))
@@ -211,9 +260,18 @@ def collect() -> list[dict[str, str]]:
211
260
  def main() -> int:
212
261
  parser = argparse.ArgumentParser(description=__doc__)
213
262
  parser.add_argument("--json", action="store_true", help="Print machine-readable JSON")
263
+ parser.add_argument(
264
+ "--resolve-host",
265
+ help="Resolve host IP for Network scripting mode",
266
+ )
267
+ parser.add_argument(
268
+ "--resolve-timeout",
269
+ type=float,
270
+ help="Network connection timeout in seconds (default: 5)",
271
+ )
214
272
  args = parser.parse_args()
215
273
 
216
- results = collect()
274
+ results = collect(args.resolve_host, args.resolve_timeout)
217
275
  if args.json:
218
276
  print(json.dumps({"checks": results}, indent=2))
219
277
  else:
@@ -44,6 +44,7 @@ from src.utils.media_analysis_jobs import (
44
44
  run_batch_job_slice,
45
45
  )
46
46
  from src.utils.platform import setup_environment
47
+ from src.utils.resolve_connection import connect_resolve
47
48
  from src.utils.analysis_memory import read_panel_state, write_panel_state
48
49
  from src.utils import brain_edits as _brain_edits
49
50
  from src.utils import timeline_versioning as _timeline_versioning
@@ -11838,7 +11839,7 @@ def _connect_resolve_read_only() -> Tuple[Any, Optional[str]]:
11838
11839
  except Exception as exc:
11839
11840
  return None, f"Resolve scripting API unavailable: {exc}"
11840
11841
  try:
11841
- resolve = dvr_script.scriptapp("Resolve")
11842
+ resolve = connect_resolve(dvr_script)
11842
11843
  except Exception as exc:
11843
11844
  return None, f"Resolve connection failed: {exc}"
11844
11845
  if resolve is None:
@@ -44,6 +44,7 @@ from src.utils.layout_presets import (
44
44
  )
45
45
  from src.utils.object_inspection import inspect_object, print_object_help
46
46
  from src.utils.platform import get_platform, get_resolve_paths
47
+ from src.utils.resolve_connection import connect_resolve
47
48
  from src.utils.project_properties import (
48
49
  get_all_project_properties,
49
50
  get_color_settings,
@@ -80,7 +81,7 @@ if not logging.getLogger().handlers:
80
81
  handlers=[logging.StreamHandler()],
81
82
  )
82
83
 
83
- VERSION = "2.63.2"
84
+ VERSION = "2.64.0"
84
85
  logger = logging.getLogger("davinci-resolve-mcp")
85
86
  logger.info(f"Starting DaVinci Resolve MCP Server v{VERSION}")
86
87
  logger.info(f"Detected platform: {get_platform()}")
@@ -233,7 +234,7 @@ dvr_script = None
233
234
  try:
234
235
  import DaVinciResolveScript as dvr_script # type: ignore
235
236
 
236
- resolve = dvr_script.scriptapp("Resolve")
237
+ resolve = connect_resolve(dvr_script)
237
238
  if resolve:
238
239
  logger.info(
239
240
  f"Connected to DaVinci Resolve: {resolve.GetProductName()} {resolve.GetVersionString()}"
@@ -311,7 +312,7 @@ def _try_connect():
311
312
  """Attempt to connect to Resolve once. Returns resolve object or None."""
312
313
  global resolve
313
314
  try:
314
- candidate = dvr_script.scriptapp("Resolve")
315
+ candidate = connect_resolve(dvr_script)
315
316
  if candidate and _is_resolve_handle_live(candidate):
316
317
  resolve = candidate
317
318
  logger.info(f"Connected: {resolve.GetProductName()} {resolve.GetVersionString()}")
package/src/server.py CHANGED
@@ -11,7 +11,7 @@ Usage:
11
11
  python src/server.py --full # Start the 341-tool granular server instead
12
12
  """
13
13
 
14
- VERSION = "2.63.2"
14
+ VERSION = "2.64.0"
15
15
 
16
16
  import base64
17
17
  import os
@@ -97,6 +97,7 @@ from src.utils.media_analysis_jobs import (
97
97
  run_batch_job_slice as run_media_analysis_batch_job_slice,
98
98
  )
99
99
  from src.utils.platform import get_resolve_paths, get_resolve_plugin_paths
100
+ from src.utils.resolve_connection import connect_resolve
100
101
  from src.utils.lut_paths import master_lut_dir, ensure_lut_in_master
101
102
  from src.utils import fuse_templates, dctl_templates, script_templates
102
103
  from src.utils.timeline_title_text import (
@@ -804,7 +805,7 @@ def _try_connect():
804
805
  if dvr_script is None:
805
806
  return None
806
807
  try:
807
- candidate = dvr_script.scriptapp("Resolve")
808
+ candidate = connect_resolve(dvr_script)
808
809
  if candidate and _is_resolve_handle_live(candidate):
809
810
  resolve = candidate
810
811
  logger.info(f"Connected: {resolve.GetProductName()} {resolve.GetVersionString()}")
@@ -3,35 +3,66 @@
3
3
  DaVinci Resolve Connection Utilities
4
4
  """
5
5
 
6
- import os
7
6
  import logging
7
+ import math
8
+ import os
9
+
8
10
  from .platform import get_platform, get_resolve_paths, setup_environment
9
11
 
10
12
  logger = logging.getLogger("davinci-resolve-mcp.connection")
11
13
 
14
+ DEFAULT_RESOLVE_SCRIPT_TIMEOUT = 5.0
15
+
16
+
17
+ def _network_timeout():
18
+ value = os.environ.get(
19
+ "RESOLVE_SCRIPT_TIMEOUT",
20
+ str(DEFAULT_RESOLVE_SCRIPT_TIMEOUT),
21
+ )
22
+ try:
23
+ timeout = float(value)
24
+ except ValueError as exc:
25
+ raise ValueError(
26
+ "RESOLVE_SCRIPT_TIMEOUT must be a positive finite number"
27
+ ) from exc
28
+ if not math.isfinite(timeout) or timeout <= 0:
29
+ raise ValueError(
30
+ "RESOLVE_SCRIPT_TIMEOUT must be a positive finite number"
31
+ )
32
+ return timeout
33
+
34
+
35
+ def connect_resolve(dvr_script):
36
+ """Create a Resolve handle, optionally targeting an explicit network host."""
37
+ host = os.environ.get("RESOLVE_SCRIPT_HOST")
38
+ if host:
39
+ return dvr_script.scriptapp("Resolve", host, _network_timeout())
40
+ return dvr_script.scriptapp("Resolve")
41
+
42
+
12
43
  def initialize_resolve():
13
44
  """Initialize connection to DaVinci Resolve application."""
14
45
  try:
15
46
  # Import the DaVinci Resolve scripting module
16
47
  import DaVinciResolveScript as dvr_script
17
-
48
+
18
49
  # Get the resolve object
19
- resolve = dvr_script.scriptapp("Resolve")
20
-
50
+ resolve = connect_resolve(dvr_script)
51
+
21
52
  if resolve is None:
22
53
  logger.error("Failed to get Resolve object. Is DaVinci Resolve running?")
23
54
  return None
24
-
55
+
25
56
  logger.info(f"Connected to DaVinci Resolve: {resolve.GetProductName()} {resolve.GetVersionString()}")
26
57
  return resolve
27
-
58
+
28
59
  except ImportError:
29
60
  platform_name = get_platform()
30
61
  paths = get_resolve_paths()
31
-
62
+
32
63
  logger.error("Failed to import DaVinciResolveScript. Check environment variables.")
33
64
  logger.error("RESOLVE_SCRIPT_API, RESOLVE_SCRIPT_LIB, and PYTHONPATH must be set correctly.")
34
-
65
+
35
66
  if platform_name == 'darwin':
36
67
  logger.error("On macOS, typically:")
37
68
  logger.error(f'export RESOLVE_SCRIPT_API="{paths["api_path"]}"')
@@ -47,24 +78,25 @@ def initialize_resolve():
47
78
  logger.error(f'export RESOLVE_SCRIPT_API="{paths["api_path"]}"')
48
79
  logger.error(f'export RESOLVE_SCRIPT_LIB="{paths["lib_path"]}"')
49
80
  logger.error(f'export PYTHONPATH="$PYTHONPATH:{paths["modules_path"]}"')
50
-
81
+
51
82
  return None
52
-
83
+
53
84
  except Exception as e:
54
85
  logger.error(f"Unexpected error initializing Resolve: {str(e)}")
55
86
  return None
56
87
 
88
+
57
89
  def check_environment_variables():
58
90
  """Check if the required environment variables are set."""
59
91
  resolve_script_api = os.environ.get("RESOLVE_SCRIPT_API")
60
92
  resolve_script_lib = os.environ.get("RESOLVE_SCRIPT_LIB")
61
-
93
+
62
94
  missing_vars = []
63
95
  if not resolve_script_api:
64
96
  missing_vars.append("RESOLVE_SCRIPT_API")
65
97
  if not resolve_script_lib:
66
98
  missing_vars.append("RESOLVE_SCRIPT_LIB")
67
-
99
+
68
100
  return {
69
101
  "all_set": len(missing_vars) == 0,
70
102
  "missing": missing_vars,
@@ -72,6 +104,7 @@ def check_environment_variables():
72
104
  "resolve_script_lib": resolve_script_lib
73
105
  }
74
106
 
107
+
75
108
  def set_default_environment_variables():
76
109
  """Set the default environment variables based on platform."""
77
- return setup_environment()
110
+ return setup_environment()