how to wait for RX7 Audio Editor to open before proceeding.
H! I'm working on a script that needs to wait for RX7 Audio editor to be fully open to continue. The way I'm trying to do this is via the availability of the composite button (conveniently the next step in the script I'm writing) but I must have something wrong with the syntax. I'm currently trying this code below, but I get the error:
Object reference not set to an instance of an object
Thoughts?
sf.engine.runInBackground(function () {
while (true) {
sf.engine.checkForCancellation();
sf.wait({ executionMode: 'Background', intervalMs: 100, onError: 'Continue' });
if (sf.ui.izotope.mainWindow.getFirstWithDescription('RX7 Main Window').getFirstWithDescription("Composite View").exists)
break;
}
});
Thanks!
Dustin
- Christian Scheuer @chrscheuer2019-10-21 18:16:55.120Z
It looks circa right as it is so it might be a bug.
I have a fix coming in 3.1.1 that might address this though.Is there a reason why you're running this in the background?
Dustin Harris @Dustin_Harris
Hi Cristian!
No reason other than it was the closest code-snippet I found to what I was trying to do. It's to pause the script while pro tools is sending audio over to RX7 (which can take a while if the files are long and RX7 isn't already open)If there is a better way to achieve this, I'm interested in any suggestions :)
Thanks again,
DustinChristian Scheuer @chrscheuer2019-10-21 18:22:25.224Z
Cool! You definitely don't need the background mode then.
Try my suggestions below. Just for clarity, I'll rewrite your above code to be non-background:
while (true) { sf.engine.checkForCancellation(); if (sf.ui.izotope.exists && sf.ui.izotope.mainWindow.getFirstWithDescription('RX7 Main Window').getFirstWithDescription("Composite View").exists) break; sf.wait({ intervalMs: 100 }); }
Dustin Harris @Dustin_Harris
This particular solution continues in the while loop even when the condition appears to be true.
It might be getting fooled by the appearance of the 'changing audio engine settings' dialogue box that appears on startup?
- In reply tochrscheuer⬆:
Christian Scheuer @chrscheuer2019-10-21 18:19:25.427Z
You might get slightly better results by doing:
if (sf.ui.izotope.exists && sf.ui.izotope.mainWindow.getFirstWithDescription('RX7 Main Window').getFirstWithDescription("Composite View").exists)
Christian Scheuer @chrscheuer2019-10-21 18:20:44.763Z
You might also get inspiration here:
https://forum.soundflow.org/-955#post-12function openFileInIzotope(path) { sf.system.exec({ commandLine: 'open -a "' + izotopeRx + '" "' + path + '"' }); sf.ui.izotope.appWaitForActive(); sf.ui.izotope.windows.whoseTitle.isNullOrEmpty.first.elementWaitFor({ waitForNoElement: true }); }
Christian Scheuer @chrscheuer2019-10-21 18:23:02.596Z
These 2 lines in particular should do what you need:
sf.ui.izotope.appWaitForActive(); sf.ui.izotope.windows.whoseTitle.isNullOrEmpty.first.elementWaitFor({ waitForNoElement: true });
Christian Scheuer @chrscheuer2019-10-21 18:35:47.637Z
@Dustin_Harris check this one. That works for me.
But yes if you get a popup with changing audio engine settings, this one doesn't take care of that.Dustin Harris @Dustin_Harris
I tried this, but I get the error "Requested app is not running (AppActivateMainWindowAction)" pointing at the line with the //THIS ONE comment, which I think means it's not waiting for the app to be open (and/or ready) before continuing the script. Thoughts? :)
sf.ui.proTools.appActivateMainWindow(); var asWin = sf.ui.proTools.getAudioSuiteWindow("RX 7 Connect"); if (!asWin.exists){ log('Please press F13 to open Rx Connect'); throw 0; // var asWin = sf.ui.proTools.audioSuiteOpenPlugin({ // category: 'Noise Reduction', // name: "RX 7 Connect" // }).window; } else {} var renderBtn = asWin.getFirstWithTitle("Analyze"); renderBtn.elementClick(); try { sf.ui.izotope.appActivateMainWindow(); } catch(err) { //log('Waiting for Rx Editor To Open') //sf.wait({ intervalMs: 5000 }); } //sf.wait({ intervalMs: 750 }); sf.ui.izotope.appWaitForActive(); sf.ui.izotope.windows.whoseTitle.isNullOrEmpty.first.elementWaitFor({ waitForNoElement: true }); sf.ui.izotope.appActivateMainWindow(); //THIS ONE var compositeViewBtn = sf.ui.izotope.mainWindow.getFirstWithDescription('RX7 Main Window').getFirstWithDescription("Composite View"); compositeViewBtn.elementClick();
Thanks,
Dustin.Christian Scheuer @chrscheuer2019-10-21 22:02:07.242Z
Hmm that's odd. This script is just trying to send audio from Connect to iZotope, and perform some actions there?
Can you get it to work if iZotope is already running?
Is this about making sure that the script also works in those few cases where iZotope wasn't running initially?Christian Scheuer @chrscheuer2019-10-21 22:03:55.348Z
It's very weird that you're getting a requested app is not running after we've already been calling things with izotope. Do you happen to have more than one version of iZotope installed and SF could be confused about which one? This should only matter if they were both running at the same time.
Dustin Harris @Dustin_Harris
I’ll check my system for other Izotope RX versions... I have all their products so maybe it’s another app interfering?
- In reply tochrscheuer⬆:
Dustin Harris @Dustin_Harris
it has occured to me that the error in question could have been thrown after an RX Audio Editor crash. Having rebooted and restarted both programs, I cannot reproduce that error (but the script still doesn't work as intended)
Log attached. Maybe there is some useful info in there!
Dustinsoundflow20191021mainlog.zip (18.4 kB)
Christian Scheuer @chrscheuer2019-10-22 10:27:18.551Z
How does it not work now then (if the original error didn't show)?
I would start by removing this section and debug from then on.
The appWaitForActive action is waiting for iZotope to become active (when Connect is done doing what it does), so this is sort of preempting that.try { sf.ui.izotope.appActivateMainWindow(); } catch(err) { //log('Waiting for Rx Editor To Open') //sf.wait({ intervalMs: 5000 }); }
Also, I think if this continues to not work, I would wait until 3.1.1 comes out with a potential fix for when apps are loading
Dustin Harris @Dustin_Harris
Heyya! Just in case this is useful, I've made a video of the behavior.
It definitely seems that the script isn't waiting for izotope to be active before continuing, or it's continuing at the very earliest stage of the app initializing.here's the script:
sf.ui.proTools.appActivateMainWindow(); var asWin = sf.ui.proTools.getAudioSuiteWindow("RX 7 Connect"); if (!asWin.exists){ log('Please press F13 to open Rx Connect'); throw 0; } else {} var renderBtn = asWin.getFirstWithTitle("Analyze"); renderBtn.elementClick(); //try { //sf.ui.izotope.appActivateMainWindow(); //} //catch(err) { //log('Waiting for Rx Editor To Open') //sf.wait({ intervalMs: 5000 }); //} //sf.wait({ intervalMs: 750 }); //sf.ui.izotope.appActivateMainWindow(); //THIS ONE sf.ui.izotope.appWaitForActive(); sf.ui.izotope.windows.whoseTitle.isNullOrEmpty.first.elementWaitFor({ waitForNoElement: true }); //sf.ui.izotope.appActivateMainWindow(); //THIS ONE sf.wait({ intervalMs: 750 }); log('This happens before the composite button click') var compositeViewBtn = sf.ui.izotope.mainWindow.getFirstWithDescription('RX7 Main Window').getFirstWithDescription("Composite View"); compositeViewBtn.elementClick(); log('This happens after the composite button click')
and here's a QuickTime of what happens. Note the log('This happens before the composite button click') is occurring before Izotope becomes the active window.
It's still quite possible that I've messed something up in the code, but I'll let you decide that :)
https://www.dropbox.com/s/c74u8gns7mpepa5/ScriptDebug1.mov?dl=0
Cheers,
DustinChristian Scheuer @chrscheuer2019-10-22 16:28:55.022Z
Here's a more fool-proof attempt:
sf.ui.proTools.appActivateMainWindow(); var asWin = sf.ui.proTools.getAudioSuiteWindow("RX 7 Connect"); if (!asWin.exists) { log('Please press F13 to open Rx Connect'); throw 0; } var renderBtn = asWin.getFirstWithTitle("Analyze"); renderBtn.elementClick(); //Wait for iZotope to become responsive sf.ui.izotope.appWaitForActive(); while (true) { try { sf.ui.izotope.windows.whoseTitle.isNullOrEmpty.first.elementWaitFor({ waitForNoElement: true }); break; } catch (err) { } } //Wait for the shuttle button to appear (indicating that we loaded correctly) while (true) { sf.engine.checkForCancellation(); try { var shuttleBtn = sf.ui.izotope.mainWindow.children.whoseDescription.endsWith('Main Window').first.children.whoseDescription.is("Shuttle").first; shuttleBtn.elementWaitFor({ timeout: 10000 }); break; } catch (err) { } sf.wait({ intervalMs: 200 }); } //Now you can click the composite button (note that will only work if more than one clip was selected originally)
Note here I'm waiting on the Shuttle (send back) button instead of the Composite one, since if you're only sending one clip, the Composite won't be available.
Dustin Harris @Dustin_Harris
OOh, this one results in:
an error too long to catch, but here is the associated log bit:
22.10.2019 12:43:49.85 [BackendConnection]: Received msg from backend: { name: '/commands/error',
args:
{ command: 'user:ck127r9d00000gz106x00uh9h:ck20q31wl0003rn1053r1xlg7',
commandName: 'SEND TEST',
error:
'SoundFlow.Shortcuts.AXUIElementException: kAXErrorCannotComplete\n at SoundFlow.Shortcuts.AXUIElement.GetSubElements(String) + 0x222\n at SoundFlow.Shortcuts.Ax.AxNodes.AxElementArrayFromAttribute.get_RawItems() + 0x42\n at SoundFlow.Shortcuts.Ax.AxNodes.AxElementArray.get_Length() + 0x28\n at SoundFlow.Shortcuts.Ax.AxNodes.AxElementArrayObjectWrapper..ctor(Engine, AxElementArray) + 0x69\n at SoundFlow.Shortcuts.Ax.AxNodes.AxElementArrayObjectConverter.TryConvert(Engine, Object, JsValue&) + 0x42\n at Jint.Native.JsValue.FromObject(Engine, Object) + 0xac\n at Jint.Runtime.Descriptors.Specialized.PropertyInfoDescriptor.get_CustomValue() + 0x39\n at Jint.Native.Object.ObjectInstance.UnwrapJsValue(PropertyDescriptor, JsValue) + 0x48\n at Jint.Native.Object.ObjectInstance.Get(Key&) + 0x6e\n at Jint.Engine.GetValue(Reference, Boolean) + 0x14a\n at Jint.Runtime.Interpreter.Expressions.JintMemberExpression.EvaluateInternal() + 0x183\n at Jint.Runtime.Interpreter.Expressions.JintMemberExpression.EvaluateInternal() + 0x13b\n at Jint.Runtime.Interpreter.Expressions.JintMemberExpression.EvaluateInternal() + 0x13b\n at Jint.Runtime.Interpreter.Expressions.JintMemberExpression.EvaluateInternal() + 0x13b\n at Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal() + 0x63\n at Jint.Runtime.Interpreter.Expressions.JintExpression.GetValue() + 0x46\n at Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal() + 0x38\n at Jint.Runtime.Interpreter.JintStatementList.Execute() + 0x279\n at Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal() + 0x2e\n at Jint.Runtime.Interpreter.Statements.JintTryStatement.ExecuteInternal() + 0x98\n at Jint.Runtime.Interpreter.JintStatementList.Execute() + 0x279\n at Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal() + 0x2e\n at Jint.Runtime.Interpreter.Statements.JintWhileStatement.ExecuteInternal() + 0xdf\n at Jint.Runtime.Interpreter.JintStatementList.Execute() + 0x279\n at Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal() + 0x2e\n at Jint.Native.Function.ScriptFunctionInstance.Call(JsValue, JsValue[]) + 0x1c0\n at Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal() + 0x59b\n at Jint.Runtime.Interpreter.Expressions.JintExpression.GetValue() + 0x46\n at Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal() + 0x38\n at Jint.Runtime.Interpreter.JintStatementList.Execute() + 0x279\n at Jint.Engine.Execute(Program) + 0xf5\n at SoundFlow.Shortcuts.Automation.AutomationEngine.<>c__DisplayClass19_0.b__0() + 0x2e\n at SoundFlow.Shortcuts.Automation.AutomationEngine.d__11.MoveNext() + 0x1be\n\n' } }
22.10.2019 12:43:49.85 [BackendConnection]: Received msg from backend: { name: '/commands/completed', args: { r: 0, e: 10 } }Christian Scheuer @chrscheuer2019-10-22 17:07:49.621Z
This is the error that will likely be fixed in 3.1.1. Please stay tuned.
- In reply tochrscheuer⬆:
Dustin Harris @Dustin_Harris
You’re exactly right, it works except for when izotope isn’t initially open and the script passes commands before RX is ready for them. I’m just trying to be a tidy programmer :)
Christian Scheuer @chrscheuer2019-10-21 22:56:55.978Z
Nice haha. It's always good to be tidy. But sometimes the 5% corner cases take up 60% of the development time ;)
I will see if I can repro the bug. Can you send me your log file?