Hey @Kitch
We currently use a program called Airtable, which is where we have all our Mix Projects request come in to see what is needed, who is working on the mix etc etc.
We currently have successfully been using Soundflow to trigger things in the program, as an example, we have a macro that bounces/exports/emails when a job is complete, which will then also in turn mark off the relevant fields we need to fill out in Airtable.
I was wondering if you could give me an insight into whether we could get better access to the program through the API through Soundflow?
At the moment we are using UI elements, but the elements line of code are very very long.
Is there a way for me to have the API in Soundflow to better write and implement the code similar to the Pro Tools API?
Apologies if I’m not explain very well.
Cheers
Mitch
- SSoundFlow Bot @soundflowbot
Thanks for contacting SoundFlow support.
Please note, that the best way to get help with a script, macro or other content installed from the Store or content that you've made yourself, is to select the script/macro, then click the red Need help button, and then click "Get help with this script or macro".
By using this method, we will get access to more information and so should be able to help you quicker.
You can read more about how this works here: bit.ly/sfscripthelpIf you're seeing an error that isn't related to scripts or macros, and you think this is a bug in SoundFlow, please file a Help/Issue bug report.
You can see how to do this by going to bit.ly/sfhelpissue - In reply toMitch_Willard_the2nd⬆:Kitch Membery @Kitch2023-10-13 00:48:08.095Z
Hi Mitch,
Can you provide an example of some code that you are working with where the lines are very long?
Thanks in advance.
Mitch Willard @Mitch_Willard
Sure thing @Kitch
Here it is below.
Having no trouble with the script, however, AIRTABLE will update semi regularly and the lines change ever so slightly. sometimes in the middle of the line which can be a matter of deleting something tiny like
groups.first
or changing.first
toallItems[0]
orallItems[1]
etcWould having access to the API help this issue at all?
function updateAirtableTicket(mixer, audioUpdate, sessionPath, ticketName, ticketNumber, ticketsLength) { function openHiddenAirtableFields() { const mixerFieldHeader = sf.ui.app("com.FormaGrid.Airtable").mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[4].buttons.first.groups.allItems[1].children.whoseRole.is("AXStaticText").first; const hiddenFieldsOpen = sf.ui.app("com.FormaGrid.Airtable").mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].buttons.allItems[2].children.whoseRole.is("AXStaticText").first; if (!mixerFieldHeader.exists) { try { hiddenFieldsOpen.elementClick(); } catch (err) { hiddenFieldsOpen.elementClick(); } finally { sf.wait({ intervalMs: 2000 }) } }; }; function updateAirtableTicket(mixer, audioUpdate, sessionPath) { const airtable = sf.ui.app("com.FormaGrid.Airtable").mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups; const airtableTicket = airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups; const airtableMixerBtn = airtableTicket.allItems[4].groups.allItems[1].groups.first.groups.first.buttons.first const airtableMixerfield = airtableTicket.allItems[4].groups.allItems[1].groups.first.groups.first.buttons.first.groups.first.groups.first.children.whoseRole.is("AXStaticText").first; const airtableAudioUpdatesBtn = airtableTicket.allItems[4].groups.allItems[3].groups.first.groups.first.buttons.first const airtableAudioUpdatesfield = airtableTicket.allItems[4].groups.allItems[3].groups.first.groups.first.buttons.first.groups.first.groups.first.children.whoseRole.is("AXStaticText").first; function updateAirtableElement(update, field, btn) { const airtable = sf.ui.app("com.FormaGrid.Airtable").mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups; const airtableUpdateText = airtable.allItems[35].groups.first.comboBoxes.first; const airtableUpdateSelect = airtable.allItems[35].groups.first.children.whoseRole.is("AXList").first.groups.first.children.whoseRole.is("AXStaticText").allItems[0] function updateField(update, field, btn) { btn.elementClick(); sf.wait({ intervalMs: 200 }) airtableUpdateText.elementSetTextFieldWithAreaValue({ value: update, }); if (airtableUpdateText.value.value != update) { sf.wait({ intervalMs: 200 }) airtableUpdateText.elementSetTextFieldWithAreaValue({ value: update, }); } sf.wait({ intervalMs: 500 }) airtableUpdateSelect.elementClick(); }; if (field.exists) { if (field.value.value != update) { try { updateField(update, field, btn); } catch (err) { sf.wait({ intervalMs: 500 }); updateField(update, field, btn); } finally { } }; } else if (!field.exists) { try { updateField(update, field, btn); } catch (err) { sf.wait({ intervalMs: 500 }); updateField(update, field, btn); } finally { } }; }; try { if (mixer != null) updateAirtableElement(mixer, airtableMixerfield, airtableMixerBtn); if (audioUpdate != null) updateAirtableElement(audioUpdate, airtableAudioUpdatesfield, airtableAudioUpdatesBtn) if (sessionPath != null) { airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.elementSetTextFieldWithAreaValue({ value: sessionPath }); sf.wait({ intervalMs: 200 }); if (airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.value.value != sessionPath) { airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.elementSetTextFieldWithAreaValue({ value: sessionPath }); }; }; } catch (err) { if (mixer != null) updateAirtableElement(mixer, airtableMixerfield, airtableMixerBtn); if (audioUpdate != null) updateAirtableElement(audioUpdate, airtableAudioUpdatesfield, airtableAudioUpdatesBtn) if (sessionPath != null) { airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.elementSetTextFieldWithAreaValue({ value: sessionPath }); sf.wait({ intervalMs: 200 }); if (airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.value.value != sessionPath) { airtable.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.allItems[1].groups.allItems[3].groups.first.groups.first.textAreas.first.elementSetTextFieldWithAreaValue({ value: sessionPath }); }; }; } finally { } }; const airtable = sf.ui.app("com.FormaGrid.Airtable"); const airtableMainWindow = airtable.mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups const allTicketsInColumns = airtableMainWindow.allItems[2].groups.first.groups.allItems[1].groups.allItems[1].groups.first .groups.first.groups.first.groups.first.groups.first.groups.first; sf.app.launch({ path: "/Applications/Airtable.app", }); airtable.appActivate(); airtable.appActivateMainWindow(); sf.wait({ intervalMs: 200 }); for (var i = 0; i < ticketsLength; i++) { if (allTicketsInColumns.groups.allItems[+ticketNumber].groups.first.groups.first.groups.first.groups.first.groups.allItems[i].children.whoseRole.is("AXHeading").first.children.whoseRole.is("AXLink").first.children.whoseRole.is("AXStaticText").whoseValue.is(ticketName).first.exists) { allTicketsInColumns.groups.allItems[+ticketNumber].groups.first.groups.first.groups.first.groups.first.groups.allItems[i].children.whoseRole.is("AXHeading").first.children.whoseRole.is("AXLink").first.children.whoseRole.is("AXStaticText").whoseValue.is(ticketName).first.elementClick(); break; }; }; sf.wait({ intervalMs: 2000 }); openHiddenAirtableFields(); updateAirtableTicket(mixer, audioUpdate, sessionPath); sf.wait({ intervalMs: 200 }); sf.ui.app("com.FormaGrid.Airtable").mainWindow.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO").first.groups.first.groups.first.groups.first.groups.first.groups.first.children.whoseRole.is("AXWebArea").whoseTitle.is("AUDIO LIST: AUDIO - Airtable").first.groups.first.groups.allItems[1].groups.allItems[34].groups.first.groups.whoseDescription.is("Detail view dialog").first.groups.first.groups.first.buttons.whoseDescription.is("Close dialog").first.children.whoseRole.is("AXImage").first.elementClick(); };
Kitch Membery @Kitch2023-10-13 02:26:13.924Z
Thanks for providing that Mitch.
I can see that AIRTABLE's UI element paths are quite bloated and have many children to deal with. There is however still a lot of room for refactoring your script, which would make the code much easier to manage.
With that said, I understand your desire to have access to the AIRTABLE API through SoundFlow.
Do you know if AIRTABLE has a REST API with good documentation? If so we may be able to help.
@chrscheuer do you have any thoughts on this?
Mitch Willard @Mitch_Willard
Cheers @Kitch
You're right, very bloated, and seems to change all the time., wrote it only a few weeks ago and working on getting it down to be easier to manage, but any suggests would be awesome.
Airtable does in fact have a REST API
https://airtable.com/developers/web/api/introductionIf there is anyway to help, it would be much appreciated.
Cheers
Mitch
Christian Scheuer @chrscheuer2023-10-13 09:23:04.732Z
You can generally talk to a REST API through
sf.net.httpRequest
Mitch Willard @Mitch_Willard
OMG! this has saved me a world of pain!
Thanks @chrscheuer and @KitchKitch Membery @Kitch2023-10-17 01:46:30.048Z
Awesome, Mitch!! Go get em!