I learned the following code
function getGroup(name) {
var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first;
return groupList.childrenByRole("AXRow").allItems.map(function (r) {
return {
row: r,
selectBtn: r.childrenByRole("AXCell").first.children.first,
name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''),
};
}).filter(function (r) { return r.name == name })[0];
}
function selectGroup(name) {
var grp = getGroup(name);
if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; }
grp.selectBtn.mouseClickElement({});
}
selectGroup("AAAA");
And after this I want to create a new playlist of tracks in the AAAA group, but it doesn't work.
Please Help me
- Christian Scheuer @chrscheuer2020-10-23 18:58:01.377Z
What have you tried?
Yujiro Yonetsu @Yujiro_Yonetsu
I tried the following script
sf.ui.proTools.selectedTrack.trackScrollToView(); sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Playlist selector').first.popupMenuSelect({ menuPath: ["New..."], }); sf.keyboard.press({ keys: "numpad enter", });
Christian Scheuer @chrscheuer2020-10-24 12:04:13.576Z
Can you be more specific in describing what doesn't work / what actually happens?
Please follow this guide to learn how to best provide us with information that can help you:
Yujiro Yonetsu @Yujiro_Yonetsu
Sorry for the inconvenience.
I would like to create a script that will automatically progress the recording of the stem mix.
I create a group for each stem mix I want to separate in advance.- Select only tracks that belong to a group
- Solo the selected track.
- Select the audio track for recording
- Create a new playlist of audio tracks for recording
- Naming (I'm fine with the default naming) , Enter.
- Call up the range selection markers.
- recording
- Wait for time of songs
The plan is that multiple stems will be created automatically by repeating this action.
now
4. Create a new playlist of audio tracks for recording
This behavior is not working.Yujiro Yonetsu @Yujiro_Yonetsu
This is the script I'm currently working on.
Where is the problem?function getGroup(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { row: r, selectBtn: r.childrenByRole("AXCell").first.children.first, name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name == name })[0]; } function selectGroup(name) { var grp = getGroup(name); if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; } grp.selectBtn.mouseClickElement({}); } selectGroup("AAAA"); sf.wait({ intervalMs: 30, }); sf.ui.proTools.selectedTrack.trackSetSolo(); sf.wait({ intervalMs: 30, }); function getGroup(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { row: r, selectBtn: r.childrenByRole("AXCell").first.children.first, name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name == name })[0]; } function selectGroup(name) { var grp = getGroup(name); if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; } grp.selectBtn.mouseClickElement({}); } selectGroup("StemRecTrack"); sf.ui.proTools.selectedTrack.trackScrollToView(); sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Playlist selector').first.popupMenuSelect({ menuPath: ["New..."], }); sf.keyboard.press({ keys: "numpad enter", }); sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: 325, }); sf.keyboard.press({ keys: "f12", }); sf.wait({ intervalMs: 180000, });
Christian Scheuer @chrscheuer2020-10-24 13:42:51.135Z
This is good progress!
Couple of things:
You don't need to define the functions twice, you can get rid of the 2nd time this is in your script:
function getGroup(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { row: r, selectBtn: r.childrenByRole("AXCell").first.children.first, name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name == name })[0]; } function selectGroup(name) { var grp = getGroup(name); if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; } grp.selectBtn.mouseClickElement({}); }
The second thing is, you're using keyboard simulation to press enter. I would instead suggest using UI automation.
You can learn more about how to use UI automation instead of keyboard simulation in the following 2 videos:Christian Scheuer @chrscheuer2020-10-24 13:45:08.822Z
Instead of using a manual wait time of 3 minutes, you should consider adding a while loop that waits until Pro Tools is no longer playing.
Yujiro Yonetsu @Yujiro_Yonetsu
Thanks. Using UI automation based on your advice is working out well for me!
It seems to work fine for one lap.
I'd really want to follow your advice and include a script that starts the next action when Protools stops.
How do that?Christian Scheuer @chrscheuer2020-10-24 15:02:42.911Z
You should be able to use something like this:
function waitUntilProToolsStopsPlaying() { while (true) { sf.engine.checkForCancellation(); if (!sf.ui.proTools.isPlaying) break; sf.wait({ intervalMs: 500 }); } } waitUntilProToolsStopsPlaying();
Yujiro Yonetsu @Yujiro_Yonetsu
Thank you!
My life is already very, very happy.
If I had to include more hope, I would say
Now it's going to be [AAAA], [BBBB], [CCCC], and increasing for every stem I want to create.I used to think of it this way until yesterday. 'I'll just make the basic script up to [GGGG].'
But is it possible that this number of times can also be derived from the circumstances of the session?
For example, if the number is small, the script may end at [CCCC], or if
In other cases, when there are a large number of them, it seems to last until [MMMMM]...Christian Scheuer @chrscheuer2020-10-24 15:37:03.987Z
can also be derived from the circumstances of the session
How should it calculate this? Can you give an example on how it could know the number of stems? Is there a specific naming pattern of tracks that we could use as the basis?
Yujiro Yonetsu @Yujiro_Yonetsu
So, let's name the group.
01_Stem
02_Stem
03_Stem
04_Stem
What if I only let the first number add up, as inChristian Scheuer @chrscheuer2020-10-24 15:43:15.778Z
In that case, you could use something like this to get the number:
function getGroupsContaining(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name.includes(name) }); } let numberOfStems = getGroupsContaining('_Stem').length;
Now that you'll then have the number of stems in a number, you could use a for loop to loop code X number of times:
for (let i=0; i<numberOfStems; i++) { //Insert the code to repeat in here }
Yujiro Yonetsu @Yujiro_Yonetsu
Thank you
This is what the code looks like for the one lap I just finished, but where do I put the code I was just taught?
function getGroup(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { row: r, selectBtn: r.childrenByRole("AXCell").first.children.first, name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name == name })[0]; } function selectGroup(name) { var grp = getGroup(name); if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; } grp.selectBtn.mouseClickElement({}); } selectGroup("01_Stem"); sf.wait({ intervalMs: 30, }); sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.counterDisplay.mouseClickElement({ relativePosition: { x: 299, y: 67 } }); sf.keyboard.press({ keys: 'shift+s' }); sf.wait({ intervalMs: 30, }); selectGroup("StemRecTrack"); sf.wait({ intervalMs: 30, }); sf.ui.proTools.selectedTrack.trackScrollToView(); sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Playlist selector').first.popupMenuSelect({ menuPath: ["New..."], }); sf.wait({ intervalMs: 50, }); sf.ui.proTools.windows.whoseTitle.is('').first.buttons.whoseTitle.is('OK').first.elementClick(); sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: 325, }); sf.wait({ intervalMs: 50, }); sf.ui.proTools.mainWindow.groups.whoseTitle.is('Transport View Cluster').first.groups.whoseTitle.is('Normal Transport Buttons').first.buttons.whoseTitle.is('Record Enable').first.elementClick(); sf.ui.proTools.mainWindow.groups.whoseTitle.is('Transport View Cluster').first.groups.whoseTitle.is('Normal Transport Buttons').first.buttons.whoseTitle.is('Play').first.elementClick(); function waitUntilProToolsStopsPlaying() { while (true) { sf.engine.checkForCancellation(); if (!sf.ui.proTools.isPlaying) break; sf.wait({ intervalMs: 500 }); } } waitUntilProToolsStopsPlaying();
Christian Scheuer @chrscheuer2020-10-24 15:59:34.120Z
You could rearrange things like this:
function getGroup(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { row: r, selectBtn: r.childrenByRole("AXCell").first.children.first, name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name == name })[0]; } function selectGroup(name) { var grp = getGroup(name); if (!grp) { log('Error', 'Group "' + name + '" not found'); throw 0; } grp.selectBtn.mouseClickElement({}); } function waitUntilProToolsStopsPlaying() { while (true) { sf.engine.checkForCancellation(); if (!sf.ui.proTools.isPlaying) break; sf.wait({ intervalMs: 500 }); } } function getGroupsContaining(name) { var groupList = sf.ui.proTools.mainWindow.tables.whoseTitle.contains('Group').first; return groupList.childrenByRole("AXRow").allItems.map(function (r) { return { name: r.childrenByRole("AXCell").allItems[1].children.first.title.value.match(/^.+ - ([^(]+)/)[1].replace(/ $/, ''), }; }).filter(function (r) { return r.name.includes(name) }); } function makeStem(stemName) { selectGroup(stemName); sf.wait({ intervalMs: 30, }); sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.counterDisplay.mouseClickElement({ relativePosition: { x: 299, y: 67 } }); sf.keyboard.press({ keys: 'shift+s' }); sf.wait({ intervalMs: 30, }); selectGroup("StemRecTrack"); sf.wait({ intervalMs: 30, }); sf.ui.proTools.selectedTrack.trackScrollToView(); sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Playlist selector').first.popupMenuSelect({ menuPath: ["New..."], }); sf.wait({ intervalMs: 50, }); sf.ui.proTools.windows.whoseTitle.is('').first.buttons.whoseTitle.is('OK').first.elementClick(); sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: 325, }); sf.wait({ intervalMs: 50, }); sf.ui.proTools.mainWindow.groups.whoseTitle.is('Transport View Cluster').first.groups.whoseTitle.is('Normal Transport Buttons').first.buttons.whoseTitle.is('Record Enable').first.elementClick(); sf.ui.proTools.mainWindow.groups.whoseTitle.is('Transport View Cluster').first.groups.whoseTitle.is('Normal Transport Buttons').first.buttons.whoseTitle.is('Play').first.elementClick(); waitUntilProToolsStopsPlaying(); } function main() { let stemGroupNames = getGroupsContaining('_Stem').map(g => g.name); stemGroupNames.forEach(makeStem); } main();
Yujiro Yonetsu @Yujiro_Yonetsu
This is Perrrrrrrrfect!!!!!!!!!!!!!!!
Thank you!
- In reply tochrscheuer⬆:TThomas Gloor @Thomas_Gloor
Hey @chrscheuer ! I hope you're well.
I'm struggling to find a way to determine a track's group assignements.
Is there a way to do such a thing?
Best,
T.