No internet connection
  1. Home
  2. How to

Fade Preset Buttons in any fade window

By Danny @Danny_van_Spreuwel
    2020-10-01 14:31:40.768Z

    I like to assemble a deck with 5 buttons to click the 5 presets elements in a fade window. I noticed that the preset buttons have the same name when i use UI element. What changes is the window title. "Batch Fades", "Fade in", "Fade out" .... How does a script look like if the buttons can used on any window containing in the name "fade"?

    So that "whoseTitle.is" works like "whoseTitle.contains". Not sure if this is the right syntax.

    Additionally it would be great you have this macro as a template. So that the preset button can be choosen from a action.

    The UI element for the first preset button is:

    sf.ui.proTools.windows.whoseTitle.is('Fade Out').first.buttons.whoseTitle.is('Fade Preset Toggle').first.elementClick();
    

    Then for the second preset:

    sf.ui.proTools.windows.whoseTitle.is('Fade Out').first.buttons.whoseTitle.is('Fade Preset Toggle').allItems[1].elementClick();
    

    Etc.

    Solved in post #13, click to view
    • 12 replies

    There are 12 replies. Estimated reading time: 21 minutes

    1. I think @sbiss has something almost ready for this?

      1. I do have this as a template, however I made separate scripts, one for the Batch Fade window, one for the Crossfade window and nothing yet for the Fade In or the Fade Out windows. If it's possible to made a single script that could address all of these windows that would be much more elegant.

        My script basically works, but it can break when certain options are not available under certain conditions. So not sure it is ready for release. I might need some scripting help. Also, mine allows you to select the Standard/S-Curve/Custom buttons, but I haven't figured out how to allow the user to select a specific custom shape (from that sub-menu), which seems really important.

        Originally I had all the Batch Fade options available as buttons on my streamdeck, but I found it's too much information to look at. What I did come up with is some user presets that look like this:

        The number of lines corresponds to how many of the 3 checkbox options options are selected, (create new fade/adjust existing shape& slope/adjust existing length). I'm finding this to be much more usable and useful. But I'd like to be able to specify specific custom fade shapes.

        The shape in, shape x-fade & shape out buttons toggle through the 3 radio button options if you want to adjust a user preset.

        1. Here's the code:

          // FADE IN
          

          const fadeInCreateNew = event.props.fadeInCreateNew;
          const fadeInAdjustExistingShapeAndSlope = event.props.fadeInAdjustExistingShapeAndSlope;
          const fadeInAdjustExistingLength = event.props.fadeInAdjustExistingLength;

          // CROSSFADE
          

          const crossfadeCreateNew = event.props.crossfadeCreateNew;
          const crossfadeAdjustExistingShapeAndSlope = event.props.crossfadeAdjustExistingShapeAndSlope;
          const crossfadeAdjustExistingLength = event.props.crossfadeAdjustExistingLength;

          // FADE OUT
          

          const fadeOutCreateNew = event.props.fadeOutCreateNew;
          const fadeOutAdjustExistingShapeAndSlope = event.props.fadeOutAdjustExistingShapeAndSlope;
          const fadeOutAdjustExistingLength = event.props.fadeOutAdjustExistingLength;

          // SHAPE
          

          const batchFadeCustomFadeInShapeUser = event.props.batchFadeCustomFadeInShapeUser;
          const batchFadeCustomCrossfadeInShapeUser = event.props.batchFadeCustomCrossfadeInShapeUser;
          const batchFadeCustomCrossfadeOutShapeUser = event.props.batchFadeCustomCrossfadeOutShapeUser;
          const batchFadeCustomFadeOutShapeUser = event.props.batchFadeCustomFadeOutShapeUser;

          // SLOPE
          

          const fadeInSlope = event.props.fadeInSlope;
          const fadeOutSlope = event.props.fadeOutSlope;
          const crossfadeSlope = event.props.crossfadeSlope;

          // PLACEMENT
          

          const placement = event.props.placement;

          // LENGTH
          

          const fadeInLength = event.props.fadeInLength;
          const crossfadeLength = event.props.crossfadeLength;
          const fadeOutLength = event.props.fadeOutLength;

          // FADE SLOPES
          

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Slope').first.radioButtons.allItems[fadeInSlope].elementClick();
          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('<<- Link ->>').first.radioButtons.allItems[crossfadeSlope].elementClick();
          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Slope').allItems[1].radioButtons.allItems[fadeOutSlope].elementClick();

          // SHAPE --->
          
          // CUSTOM FADE IN SHAPE
          

          var btn = sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade In Shape').first.popupButtons.whoseTitle.is('PTFadeShapeIcon').first;

          /@param {AxElement} btn */
          function selectNumberedFade(btn, index) {
          const timeout = 2000;
          btn.elementClick({ asyncSwallow: true });
          var pos = btn.position;
          /
          @type {AxElement | null} */
          var el;
          var started = (new Date).valueOf();
          while (true) {
          el = sf.ui.root.getElementAtPosition(pos.x + 50, pos.y + 50);
          if (el && el.role == "AXMenuItem") {
          break;
          }
          sf.wait({ intervalMs: 50 });
          var now = (new Date).valueOf();
          if (now - started > timeout) throw 'Could not find popup after waiting';
          }
          var menu = el.getParentElement();
          if (menu.role !== "AXMenu") throw 'Could not find menu';
          menu.children[index].elementClick();
          }

          selectNumberedFade(btn, batchFadeCustomFadeInShapeUser);

          // CUSTOM CROSFADE IN SHAPE
          

          var btn = sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('In Shape').first.popupButtons.whoseTitle.is('PTFadeShapeIcon').first;

          /@param {AxElement} btn */
          function selectNumberedFade(btn, index) {
          const timeout = 2000;
          btn.elementClick({ asyncSwallow: true });
          var pos = btn.position;
          /
          @type {AxElement | null} */
          var el;
          var started = (new Date).valueOf();
          while (true) {
          el = sf.ui.root.getElementAtPosition(pos.x + 50, pos.y + 50);
          if (el && el.role == "AXMenuItem") {
          break;
          }
          sf.wait({ intervalMs: 50 });
          var now = (new Date).valueOf();
          if (now - started > timeout) throw 'Could not find popup after waiting';
          }
          var menu = el.getParentElement();
          if (menu.role !== "AXMenu") throw 'Could not find menu';
          menu.children[index].elementClick();
          }

          selectNumberedFade(btn, batchFadeCustomCrossfadeInShapeUser);

          // CUSTOM CROSFADE OUT SHAPE

          var btn = sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Out Shape').first.popupButtons.whoseTitle.is('PTFadeShapeIcon').first;

          /@param {AxElement} btn */
          function selectNumberedFade(btn, index) {
          const timeout = 2000;
          btn.elementClick({ asyncSwallow: true });
          var pos = btn.position;
          /
          @type {AxElement | null} */
          var el;
          var started = (new Date).valueOf();
          while (true) {
          el = sf.ui.root.getElementAtPosition(pos.x + 50, pos.y + 50);
          if (el && el.role == "AXMenuItem") {
          break;
          }
          sf.wait({ intervalMs: 50 });
          var now = (new Date).valueOf();
          if (now - started > timeout) throw 'Could not find popup after waiting';
          }
          var menu = el.getParentElement();
          if (menu.role !== "AXMenu") throw 'Could not find menu';
          menu.children[index].elementClick();
          }

          selectNumberedFade(btn, batchFadeCustomCrossfadeOutShapeUser);

          // CUSTOM FADE OUT SHAPE

          var btn = sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade Out Shape').first.popupButtons.whoseTitle.is('PTFadeShapeIcon').first;

          /@param {AxElement} btn */
          function selectNumberedFade(btn, index) {
          const timeout = 2000;
          btn.elementClick({ asyncSwallow: true });
          var pos = btn.position;
          /
          @type {AxElement | null} */
          var el;
          var started = (new Date).valueOf();
          while (true) {
          el = sf.ui.root.getElementAtPosition(pos.x + 50, pos.y + 50);
          if (el && el.role == "AXMenuItem") {
          break;
          }
          sf.wait({ intervalMs: 50 });
          var now = (new Date).valueOf();
          if (now - started > timeout) throw 'Could not find popup after waiting';
          }
          var menu = el.getParentElement();
          if (menu.role !== "AXMenu") throw 'Could not find menu';
          menu.children[index].elementClick();
          }

          selectNumberedFade(btn, batchFadeCustomFadeOutShapeUser);

          // PLACEMENT
          

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Placement').first.radioButtons.allItems[placement].elementClick();

          // FADE IN CHECKBOXES

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade In Operation').first.checkBoxes.whoseTitle.is('Create new fade ins').first.checkboxSet({
          targetValue: fadeInCreateNew,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade In Operation').first.checkBoxes.whoseTitle.is('Adjust existing fade in shape & slope').first.checkboxSet({
          targetValue: fadeInAdjustExistingShapeAndSlope,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade In Operation').first.checkBoxes.whoseTitle.is('Adjust existing fade in length').first.checkboxSet({
          targetValue: fadeInAdjustExistingLength,
          });

          // CROSSFADE CHECKBOXES
          

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Crossfade Operation').first.checkBoxes.whoseTitle.is('Create new crossfades').first.checkboxSet({
          targetValue: crossfadeCreateNew,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Crossfade Operation').first.checkBoxes.whoseTitle.is('Adjust existing crossfade shape & slope').first.checkboxSet({
          targetValue: crossfadeAdjustExistingShapeAndSlope,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Crossfade Operation').first.checkBoxes.whoseTitle.is('Adjust existing crossfade length').first.checkboxSet({
          targetValue: crossfadeAdjustExistingLength,
          });

          // FADE OUT CHECKBOXES
          

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade Out Operation').first.checkBoxes.whoseTitle.is('Create new fade outs').first.checkboxSet({
          targetValue: fadeOutCreateNew,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade Out Operation').first.checkBoxes.whoseTitle.is('Adjust existing fade out shape & slope').first.checkboxSet({
          targetValue: fadeOutAdjustExistingShapeAndSlope,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade Out Operation').first.checkBoxes.whoseTitle.is('Adjust existing fade out length').first.checkboxSet({
          targetValue: fadeOutAdjustExistingLength,
          });

          // SET LENGTHS
          

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade In Operation').first.textFields.first.elementClick();
          sf.keyboard.press({
          keys: "backspace",
          });
          sf.keyboard.type({
          text: fadeInLength,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Crossfade Operation').first.textFields.first.elementClick();
          sf.keyboard.press({
          keys: "backspace",
          });
          sf.keyboard.type({
          text: crossfadeLength,
          });

          sf.ui.proTools.windows.whoseTitle.is('Batch Fades').first.groups.whoseTitle.is('Fade Out Operation').first.textFields.first.elementClick();
          sf.keyboard.press({
          keys: "backspace",
          });
          sf.keyboard.type({
          text: fadeOutLength,
          });

          // TAB TO 1ST LENGTH FIELD
          

          sf.keyboard.press({
          keys: "tab",
          });

          1. In reply tosbiss:

            Also, as I use this more I'd like to have the user preset leave a particular length field selected, depending on the operation. So for instance for crossfade only presets, I'd like the x-fade field selected so I can type the desired x-fade length without having to look.

            1. Here's what the template looks like:

              1. Sure wish there was a better way to share a template that includes everything, the script and the templates so I could hand off my work and have someone more experienced tidy it up.

                1. Hi Steve,

                  Is there a reason you can't share the package this is contained in?
                  That would still allow people to take a look at the source and potentially help improve things :)

                  1. Cleaning up the package and will publish soon!

                    1. Awesome!! And apologies if you had already said that :)

                      1. In reply tosbiss:

                        Check it out...the package is up! Under Steve Bissinger / Pro Tools - Deck - Batch Fades.

                        Here's the issues I've yet to solve:

                        1. I can access all of the fade shapes (1-5) - so the fade shape property that selects Standard - S-Curve - Custom is redundant. EXCEPT for the S-Curve. To have an S-Curve you need to also select Equal Power. Is there a way to make a 6th option that does that?

                        2. Anything that can be done to increase the speed?

          2. Danny @Danny_van_Spreuwel
              2020-10-02 11:25:01.175Z

              Wow, Steve. You made a fantastic project out of these fades. I was allready happy with being able to access the presets buttons.

              The routine i have is mostly pressing a preset to reset or have a quick standard setting. Changing a shape in a fade in/out window or using standard fade times in the batch fades window. For post editing most of the time this will do. Now i have made fade presets actions for the Fade in/out window and Batch presets actions for the batch fades window. It would be nice to have those two buttons (2 rows of 5 buttons) combined in one row of 5 which are working on both the fade in/out window as for the batch fades window. I thought it could be possible to have the script be executed on both windows. Working on windows whos title contains "fade". The button elements are the same i noticed.

              1. Danny @Danny_van_Spreuwel
                  2020-10-03 12:11:29.968Z

                  Got it! The answer was already there in the question :-)

                  Wanted to activate the preset buttons in any fade window. The UI elements of the preset buttons were the same in any fade window so a 1 line script did the trick. As simpel as it could be. And now with the template function in SoundFlow I have it converted to only have that one-line-script for all of the buttons.

                  Great platform, loving it!

                  sf.ui.proTools.windows.whoseTitle.contains('Fade').first.buttons.whoseTitle.is('Fade Preset Toggle').allItems[0].elementClick();
                  ReplySolution