Skip to content

Commit d9eff91

Browse files
committed
release Repair missing JSFX files in current project
1 parent 01a050e commit d9eff91

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
-- @description Repair missing JSFX files in the current project
2+
-- @author cfillion
3+
-- @version 1.0
4+
-- @link https://cfillion.ca
5+
-- @donation https://www.paypal.me/cfillion/10
6+
-- @about
7+
-- # Repair missing JSFX files in the current project
8+
--
9+
-- This script scans the current project file for broken JSFX references
10+
-- and prompts for the new location of each unique missing JSFX found.
11+
--
12+
-- A fixed copy of the project file is created (OriginalName-jsfix.RPP).
13+
--
14+
-- This script supports JSFX located either in the resource folder or
15+
-- in the project directory.
16+
17+
local global_dir = reaper.GetResourcePath() .. '/Effects/'
18+
local title = ({reaper.get_action_context()})[2]:match('([^/\\_]+).lua$')
19+
local bucket = {}
20+
21+
-- no undo point for this script
22+
reaper.defer(function() end)
23+
24+
function file_exists(fn)
25+
local file = io.open(fn, 'rb')
26+
27+
if file then
28+
io.close(file)
29+
return true
30+
else
31+
return false
32+
end
33+
end
34+
35+
function saw(jsfx)
36+
for i,entry in ipairs(bucket) do
37+
if jsfx == entry.name then
38+
return true
39+
end
40+
end
41+
42+
return false
43+
end
44+
45+
-- http://stackoverflow.com/a/34953646
46+
function escape(pattern)
47+
return pattern:gsub("([^%w])", "%%%1")
48+
end
49+
50+
if reaper.IsProjectDirty(0) ~= 0 then
51+
local btn = reaper.ShowMessageBox([[Project is modified. Do you want to save changes before repairing missing JSFX files?
52+
Unsaved changes will not be included in the fixed copy.]], title, 3)
53+
54+
if btn == 6 then
55+
reaper.Main_SaveProject()
56+
elseif btn == 2 then
57+
return
58+
end
59+
end
60+
61+
local _, project_fn = reaper.EnumProjects(-1, '', 0)
62+
local project_dir = project_fn:match('^(.-)[^/\\]+$') .. 'Effects/'
63+
64+
local project_io, error = io.open(project_fn, 'rb')
65+
if not project_io then
66+
reaper.ShowMessageBox(
67+
string.format('Could not open project file "%s" (%s).',
68+
project_fn, error), title, 0)
69+
return
70+
end
71+
72+
local chunk, modified = project_io:read('*all'), false
73+
project_io:close()
74+
75+
function scan(pattern, start, stop)
76+
local from, to
77+
78+
while true do
79+
from, to = chunk:find('<JS ' .. pattern, (from or 0) + 1)
80+
if not from then break end
81+
82+
local token = chunk:sub(from, to):sub(5)
83+
local jsfx = token:sub(start, stop)
84+
local file, dir
85+
86+
if jsfx:sub(1, 10) == "<Project>/" then
87+
dir = project_dir
88+
file = jsfx:sub(11)
89+
else
90+
dir = global_dir
91+
file = jsfx
92+
end
93+
94+
if not saw(jsfx) and not file_exists(dir .. file) then
95+
table.insert(bucket, {name=jsfx, path=dir, token=token})
96+
end
97+
end
98+
end
99+
100+
scan('"[^\n]-"', 2, -2)
101+
scan('[^"\x20]+', 1, -1)
102+
103+
if #bucket == 0 then
104+
reaper.ShowMessageBox('No missing JSFX were found. Nothing to do!', title, 0)
105+
return
106+
end
107+
108+
for i,old in ipairs(bucket) do
109+
local title = string.format('Looking for "%s"', old.name)
110+
local ok, new = reaper.GetUserFileNameForRead(old.path, title, '*.jsfx')
111+
112+
if ok then
113+
new = new:sub(old.path:len() + 1)
114+
if old.path == project_dir then
115+
new = '<Project>/' .. new
116+
end
117+
118+
old_pt = string.format('<JS %s', old.token)
119+
new_pt = string.format('<JS "%s"', new)
120+
121+
chunk = chunk:gsub(escape(old_pt), new_pt)
122+
modified = true
123+
end
124+
end
125+
126+
if not modified then
127+
reaper.ShowMessageBox('Repair process aborted by user request.', title, 0)
128+
return
129+
end
130+
131+
new_fn = project_fn:gsub('%.(%w+)$', '-jsfix.%1')
132+
local new_io, error = io.open(new_fn, 'wb')
133+
if not new_io then
134+
reaper.ShowMessageBox(
135+
string.format('Could not write project file "%s" (%s).',
136+
new_fn, error), title, 0)
137+
return
138+
end
139+
new_io:write(chunk)
140+
new_io:close()
141+
142+
reaper.Main_openProject(new_fn)

0 commit comments

Comments
 (0)