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.120ZIt 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_HarrisHi 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,
Dustin
Christian Scheuer @chrscheuer2019-10-21 18:22:25.224ZCool! 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_HarrisThis 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.427ZYou 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.763ZYou 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.596ZThese 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_HarrisI 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.242ZHmm 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.348ZIt'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_HarrisI’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_Harrisit 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.551ZHow 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_HarrisHeyya! 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=0Cheers,
Dustin
Christian Scheuer @chrscheuer2019-10-22 16:28:55.022ZHere'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_HarrisOOh, 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.621ZThis is the error that will likely be fixed in 3.1.1. Please stay tuned.
- In reply tochrscheuer⬆:
Dustin Harris @Dustin_HarrisYou’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.978ZNice 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?