No internet connection
  1. Home
  2. How to

Automated Music cue sheet

By Kensuke Matsui @Kensuke_Matsui
    2020-10-16 16:05:11.842Z

    Hello @samuel_henriques,

    I watched your cool macro "Automated Music cue sheet" on Facebook.
    This is a macro I've been trying to find out if I could do with SF for a long time and I gave up on it to my knowledge.
    If you'd like to share how to do it?

    Solved in post #27, click to view
    • 46 replies

    There are 46 replies. Estimated reading time: 48 minutes

    1. samuel henriques @samuel_henriques
        2020-10-16 18:07:46.767Z2020-10-17 16:21:18.623Z

        Hello @Kensuke_Matsui I've been thinking about putting this script on the shop. But between exporting and getting to openOffice, I made a folder action with automator and an applescript to filter the lines of text I need. I guess would be better to be easy to share if this bit was preformed by Soundflow and maybe save it as txt. . This way anyone can place it on the file format they need.
        @chrscheuer, if this is something that is possible to do with SoundFlow, and you could help me with it let me know and I'll send the script and the automator thing ? And I guess the script can be reviewed to fix some of my apprentice mistakes.

        If not, @Kensuke_Matsui bare with me a few days so I can clean it up a bit and write some instructions to set it up.

        Thank you

        1. JJohn Warrin @John_Warrin
            2020-10-17 22:52:34.508Z

            Hello @samuel_henriques - I'd gladly pay for a copy of it. This would be so useful.

            1. samuel henriques @samuel_henriques
                2020-10-17 23:35:29.447Z

                Unless it's a million bucks, lets see if Kitch can help make this simpler to share on the shop.

                and thank you!

                1. samuel henriques @samuel_henriques
                    2020-10-19 14:49:50.606Z2020-10-20 09:57:28.569Z

                    Here you go, It's working for me, I guess it still needs a bit of testing and making sure the filter is right.
                    @Kitch, thank you so much, if you can, please review the code to find the faults.

                    
                    
                    
                    /*
                    ///////////////// Auto Music List /////////////////////
                    
                    This script will:
                    
                    save as.. and append _MUSIC LIST to Session name
                    show all tracks
                    hide inactive tracks
                    select tracks by key word in the comments section of each track, the word can be changed on the "SELECT TRACKS BY WORDS IN COMMENTS" section.
                    clean clip groups
                    delete fades
                    export session info as text to the session folder
                    
                    filtered to include only:
                    session name
                    clip nme, start time, end time, duration of Unmuted clips on channel 1
                    
                    create clean txt on session folder
                    soundflow will create new spreadsheet and paste (this is setup for my NeoOffice)
                    save as the same name as pro tools session on session folder
                    
                    if you need to use adiferent spreadsheet application you need to change the "WAIT AND PASTE ON NEOOFFICE" section
                    and the "SAVE NEOOFFICE" for your application
                    
                    Close NeoOffice and Pro tools
                    
                    
                    enjoy!
                    
                    */
                    
                    
                    
                    sf.ui.proTools.appActivate();
                    sf.ui.proTools.invalidate();
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["File","Save As..."],
                    });
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.elementWaitFor({
                        failIfNotFound: true,
                    });
                    
                    
                    
                    //////////////////////////////// SAVE AS SESSION NAME -OPERATOR NAME +LISTA MUSICA///////////////
                    var sessionPath = sf.ui.proTools.mainWindow.sessionPath;
                    var sessionName = sessionPath.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
                    var newname = sessionName + "_" + "MUSIC LIST";
                    
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.textFields.first.elementSetTextFieldWithAreaValue({
                        value: newname,
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.buttons.whoseTitle.is('Save').first.elementClick();
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.elementWaitFor({
                        waitType: "Disappear",
                        timeout: -1,
                    });
                    
                    
                    /////////////////////////////////////////////////////SHOW All/HIDE INACTIVE TRACKS/////////////////
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["Options","Link Track and Edit Selection"],
                        targetValue: "Enable",
                    });
                    
                    sf.ui.proTools.menuClick({
                         menuPath: ["View", "Other Displays", "Track List"],
                         targetValue: "Enable",
                    });
                    sf.ui.proTools.mainWindow.buttons.whoseTitle.is('Track List pop-up').first.popupMenuSelect({
                           menuPath: ["Show All Tracks"]
                    });  
                    sf.ui.proTools.mainWindow.buttons.whoseTitle.is('Track List pop-up').first.popupMenuSelect({
                           menuPath: ["Hide", "Inactive Tracks"]
                    });  
                    
                    
                    //////////////////////////////////SELECT TRACKS BY WORDS IN COMMENTS/////////////////////////
                    
                    
                    
                    // Make sure comments are visible
                    if (!sf.ui.proTools.getMenuItem("View","Edit Window Views","Comments").isMenuChecked) {
                        sf.ui.proTools.menuClick({
                        menuPath: ["View","Edit Window Views","Comments"],
                    });
                    }
                    
                    function selecttrackbywordincomments(){
                    
                    const visibleTracks = sf.ui.proTools.trackGetVisibleTracks().names;
                    var firstTrackFound;
                    let foundTracks = [];
                    
                    // Make sure we're on the Edit window. Required to scroll to first selected track.
                    if (!sf.ui.proTools.getMenuItem("Window", "Edit").isMenuChecked) {
                        sf.ui.proTools.menuClick({
                            menuPath: ["Window", "Edit"],
                        })
                    }
                    
                    // Make sure comments are visible
                    if (!sf.ui.proTools.getMenuItem("View", "Edit Window Views", "Comments").isMenuChecked) {
                        sf.ui.proTools.menuClick({
                            menuPath: ["View", "Edit Window Views", "Comments"],
                        });
                    }
                    
                    while (true) {
                        // Ask for search query
                        const searchQuery = 
                        
                    /// example of search list   ("word1 word2 word3")
                        ("MUSICLIST")
                    
                        // Format query to RegEx
                        const searchQueryRegEx = new RegExp(searchQuery.split(" ").join("|").replace(/^/, "\\b(").replace(/$/, ")\\b"), "i");
                    
                        // Deselect all tracks
                        sf.ui.proTools.trackDeselectAll();
                    
                        // Search visible tracks for search query
                        for (var i = 0; i < visibleTracks.length; i++) {
                            var trackCommentHasSearch = sf.ui.proTools.trackGetByName({ name: visibleTracks[i] }).track.textFields.first.value.value.match(searchQueryRegEx);
                    
                            if (trackCommentHasSearch) {
                                if (!firstTrackFound) { // Scroll to first track found
                                    sf.ui.proTools.trackGetByName({ name: visibleTracks[i], }).track.trackScrollToView();
                                    firstTrackFound = !firstTrackFound;
                                } else {
                                    sf.ui.proTools.trackSelectByName({ names: [visibleTracks[i]], deselectOthers: false });
                                }
                                foundTracks.push(visibleTracks[i]);
                            }
                        }
                        if (foundTracks.length !== 0) {
                            break;
                        } else if (!confirm("No tracks found. Try another search?")) {
                            break;
                        }
                    }
                    }
                    selecttrackbywordincomments()
                    
                    //////////////////////////////////////////
                    
                     sf.ui.proTools.mainWindow.buttons.whoseTitle.is('Track List pop-up').first.popupMenuSelect({
                         menuPath: ["Show Only Selected Tracks"],
                     });
                    
                    
                    //////////////////////////////////////////////////////////////////////////////////////
                    
                    ////clean fades and clip groups
                    
                    
                     sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Track View selector').first.popupMenuSelect({
                         menuPath: ["waveform"],
                         isOption: true,  
                     });
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["Edit","Select All"],
                    });
                    sf.ui.proTools.menuClick({
                        menuPath: ["Clip","Ungroup All"],
                    });
                    
                    selecttrackbywordincomments();
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["Edit","Select All"],
                    });
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["Edit","Fades","Delete"],
                    });
                    
                    selecttrackbywordincomments();
                    
                    
                    ////////////////////////////////////////////////////////
                    ////Close Comments so next open sessions doesn't show them
                    if (sf.ui.proTools.getMenuItem("View","Edit Window Views","Comments").isMenuChecked) {
                        sf.ui.proTools.menuClick({
                        menuPath: ["View","Edit Window Views","Comments"],
                    });
                    }
                    
                    ////////////////////////////////  EXPORT AS TEXT   //////////////////
                    
                    
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["File","Export","Session Info as Text..."],
                    });
                    
                    sf.wait({
                        intervalMs: 100,
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Include File List').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Include Clip List').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Include Markers').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Include Plug-In List').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseDescription.is('').allItems[4].checkboxSet({
                        targetValue: "Enable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.radioButtons.whoseDescription.is('').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.radioButtons.whoseTitle.is('Selected Tracks Only').first.checkboxSet({
                        targetValue: "Enable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Show Subframes').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.checkBoxes.whoseTitle.is('Include User Timestamps').first.checkboxSet({
                        targetValue: "Disable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.radioButtons.whoseDescription.is('').allItems[3].checkboxSet({
                        targetValue: "Enable",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.popupButtons.whoseDescription.is('').first.popupMenuSelect({
                        menuPath: ["Timecode"],
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.popupButtons.whoseDescription.is('').allItems[1].popupMenuSelect({
                        menuPath: ["UTF-8 'TEXT'"],
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Export Session Text').first.buttons.whoseTitle.is('OK').first.elementClick();
                    
                    sf.wait();
                    
                    ///////////////////////// SAVE text LOCATION  ///////////////////////////
                    sf.ui.proTools.invalidate();
                    var sessionPath = sf.ui.proTools.mainWindow.sessionPath;
                    var folderPath = sessionPath.split(".").slice(0,-1).join().split("/").slice(1 ,-1).join("/");
                    var sessionName = sessionPath.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
                    
                    sf.keyboard.type({ text: '/' });
                    
                    sf.keyboard.type({ text: folderPath });
                    
                    sf.keyboard.press({ keys: 'enter' });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.sheets.first.elementWaitFor({
                        waitType: "Disappear",
                    });
                    
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.getElement('AXDefaultButton').elementClick();
                    
                    sf.ui.proTools.windows.whoseTitle.is('Save').first.sheets.first.elementWaitFor({
                        waitType: "Disappear",
                    });
                    ///////////////////////////////////////// Kitch Clean TXT /////////////////////////////
                    ///////////////////////////////////////// Kitch Clean TXT /////////////////////////////
                    
                    var sessionPath = sf.ui.proTools.mainWindow.sessionPath;
                    var sessionName = sessionPath.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
                    //const outputPath = folderPath + '/' + sessionName + '_' + 'CLEAN' + '.' + 'txt';
                    
                    const inputPath =  folderPath + '/' + sessionName  + '.' + 'txt';
                    
                    function convertTextFile(inputPath, outputPath) {
                        let data = sf.file.readText({ path: inputPath }).text;
                    
                        let sessionNameHeading = data.toString().split(':')[0].trim() + ':';
                        let sessionName = data.toString().split(':')[1].split('\n')[0].trim();
                    
                        let header = data.split('\n').filter(line => line.startsWith('CHANNEL'))[0].split('\t').map(item => item.trim()).slice(2, -1);
                    
                        let textFileLines = data.split(/\n/g).filter(line => line.endsWith('Unmuted'))
                            .filter(line => line.startsWith('1'))
                            .join().split('\t').map(item => item.replace(/\,/g,"").trim())
                            .join().split('Unmuted');
                    
                        let filteredLines = [];
                    
                        for (let i = 0; i < textFileLines.length; i++) {
                            if (textFileLines[i]) {
                                filteredLines[i] = textFileLines[i].split(',').filter(item => item).slice(2).join(',').split(',');
                            }
                        }
                    
                        filteredLines.unshift(header);
                    
                        function convertToArrayOfObjects(data) {
                            var keys = data.shift(),
                                i = 0, k = 0,
                                obj = null,
                                output = [];
                    
                            for (i = 0; i < data.length; i++) {
                                obj = {};
                    
                                for (k = 0; k < keys.length; k++) {
                                    obj[keys[k]] = data[i][k];
                                }
                                output.push(obj);
                            }
                            return output;
                        }
                    
                        let sortArray = convertToArrayOfObjects(filteredLines);
                    
                        sortArray.sort(function (a, b) {
                            var nameA = a["START TIME"]
                            var nameB = b["START TIME"]
                            if (nameA < nameB) {
                                return -1;
                            }
                            if (nameA > nameB) {
                                return 1;
                            }
                            return 0;
                        });
                    
                        sortArray.forEach((e, i, array) => {
                            sortArray[i] = e["CLIP NAME"] + '\t' + e["START TIME"] + '\t' + e["END TIME"] + '\t' + e["DURATION"] + '\n';
                        });
                    
                        sortArray.unshift("CLIP NAME" + '\t' + "START TIME" + '\t' + "END TIME" + '\t' + "DURATION" + '\n');
                        sortArray.unshift(sessionNameHeading + '\t' + sessionName + '\n');
                    
                        sf.clipboard.setText({
                           // path: outputPath,
                            text: sortArray.join(''),
                        })
                    }
                    
                    convertTextFile(inputPath);
                    /////////////////////////////////////////////////////////
                    
                    ////////////////////////////// WAIT AND PASTE ON NEOOFFICE  /////////////////
                    
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').appActivate();
                    
                    sf.app.launch({
                        path: "/Applications/NeoOffice.app",
                    });
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').menuClick({
                        menuPath: ["File","New", "Spreadsheet"],
                    });
                     sf.wait({
                        intervalMs: 2000,
                    })
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').menuClick({
                        menuPath: ["Edit","Paste Special..."],
                    });
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').windows.whoseTitle.is('Paste Special').first.elementWaitFor({
                        waitType: "Appear",
                        failIfNotFound: true,
                        timeout: -1,     
                    });
                    sf.keyboard.press({
                        keys: "down",
                        fast: true,
                    });
                    
                    sf.keyboard.press({
                        keys: "tab",
                        fast: true,
                    });
                    
                    sf.keyboard.press({
                        keys: "ctrl+o",
                        fast: true,
                    });
                    
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').windows.whoseTitle.is('Text Import').first.elementWaitFor({
                        waitType: "Appear",
                    });
                    
                    sf.keyboard.press({
                        keys: "tab",
                        repetitions: 2,
                        fast: true,
                    });
                    
                    sf.keyboard.press({
                        keys: "ctrl+o",
                        fast: true,
                    });
                    
                    sf.wait();
                    
                    
                    
                    
                    ////////////////SAVE NEOOFFICE FILE////////
                    
                    
                    
                     sf.keyboard.press({
                          keys: "cmd+s",
                      });
                    
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').mainWindow.sheets.first.elementWaitFor({
                        waitType: "Appear",
                    });
                    
                    ////Destination
                    
                    ///Set Destination Folder
                    
                    
                    //////Navigate to destination Folder
                    sf.keyboard.type({text: `/`,}); 
                    
                    sf.keyboard.type({ text: folderPath });
                    
                     sf.wait({
                        intervalMs: 1000,
                    })
                    sf.keyboard.press({ keys: 'enter' });
                    
                    
                    ///////Name the file
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').mainWindow.sheets.first.elementWaitFor({
                        waitType: "Appear",
                    });
                    
                    sf.keyboard.type({
                        text: newname,
                    });
                    
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').mainWindow.sheets.first.buttons.whoseTitle.is('Save').first.elementClick();
                    
                    ////////////////////// close neoOffice, Pro Tools Session
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').appActivate();
                    
                    sf.ui.app('org.neooffice.NeoOfficeSecureEdition').menuClick({
                        menuPath: ["File","Close"],
                    });
                    
                    sf.ui.proTools.appActivate();
                    
                    sf.ui.proTools.menuClick({
                        menuPath: ["File","Save"],
                    });
                    sf.ui.proTools.menuClick({
                        menuPath: ["File","Close Session"],
                    });
                    
                    

                    And here is a tool to write "MUSICLIST" on all selected tracks' comments. This is a separate tool only for the already existing sessions, all the new ones I'm already adding the keyword to the comments.

                    sf.ui.proTools.appActivateMainWindow();
                    
                    // Make sure comments are visible
                    if (!sf.ui.proTools.getMenuItem("View","Edit Window Views","Comments").isMenuChecked) {
                        sf.ui.proTools.menuClick({
                        menuPath: ["View","Edit Window Views","Comments"],
                    });
                    }
                    
                    
                    
                    function selectTracks(trackNames = []) {
                    
                    
                        var allNames = sf.ui.proTools.selectedTrackNames;
                    
                        var namesToSelect = allNames.filter(n => trackNames);
                        
                    
                        //Make sure the first track is in view
                        var firstTrack = sf.ui.proTools.trackGetByName({ name: namesToSelect[0] }).track;
                        firstTrack.trackScrollToView();
                    
                        //Now select all of them
                        sf.ui.proTools.trackSelectByName({
                            names: namesToSelect,
                            deselectOthers: true,
                        });
                    }
                    
                    selectTracks()
                    
                    var size = 'small';
                    var f = sf.ui.proTools.selectedTrack.frame;
                    var popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({
                        relativePosition: { x: f.w - 10, y: 5 },    
                        isOption: true,
                        isShift: true,
                    }).popupMenu;
                    popupMenu.menuClickPopupMenu({
                        menuPath: [size]
                    });
                    
                    
                       function setComment(trackHeader, text) {
                           var commentsField = trackHeader.textFields.whoseTitle.startsWith('Comments').first;
                           commentsField.mouseClickElement();
                           sf.keyboard.press({ keys: 'cmd+a' });
                           sf.keyboard.type({ text: "MUSICLIST" });
                           sf.keyboard.press({ keys: 'return' });
                       }
                    
                       function setCommentsToTrackNames() {
                           var tracks = sf.ui.proTools.selectedTracks.trackHeaders;
                           for (var i = 0; i < tracks.length; i++) {
                               var track = tracks[i];
                               setComment(track, track.normalizedTrackName);
                           }
                       }
                    
                       setCommentsToTrackNames();
                    
                    
                    

                    Have fun!!

                    Reply1 LikeSolution
                    1. KKensuke Matsui @Kensuke_Matsui
                        2020-10-20 05:41:38.716Z

                        Hi @samuel_henriques @Kitch
                        thank you so much for sharing ! It works well on my system.
                        It would be even better if this could be extened to sessions with the stem track.
                        I'll try to find out a good way.
                        If you have any good ideas, please let me know....

                        1. samuel henriques @samuel_henriques
                            2020-10-20 07:30:51.433Z

                            Hello @Kensuke_Matsui, I'm happy it works for you. Could you elaborate on what actions you would like the script to to?

                            1. KKensuke Matsui @Kensuke_Matsui
                                2020-10-20 08:46:32.782Z

                                I edit the music with stem files. like this

                                and then,
                                I want it to look like this in the text file.

                                music cue_MUSIC LIST.txt (715 B)

                                Do you think you can do it this way?

                                1. samuel henriques @samuel_henriques
                                    2020-10-20 09:29:02.194Z

                                    I get it.....let me think about it.
                                    And you only want these tracks to be as one line and duration, on the list or there are other tracks you want to include?

                                    1. samuel henriques @samuel_henriques
                                        2020-10-20 10:01:15.919Z

                                        If it's only these, I would propose create a clip group fro each "song" and name it the song name. That way there is duration and name.
                                        type "MUSICLIST" on the comments of one of the tracks only.

                                        then delete from script:

                                        
                                        ////clean fades and clip groups
                                        
                                        
                                         sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Track View selector').first.popupMenuSelect({
                                             menuPath: ["waveform"],
                                             isOption: true,  
                                         });
                                        
                                        sf.ui.proTools.menuClick({
                                            menuPath: ["Edit","Select All"],
                                        });
                                        sf.ui.proTools.menuClick({
                                            menuPath: ["Clip","Ungroup All"],
                                        });
                                        
                                        selecttrackbywordincomments();
                                        
                                        sf.ui.proTools.menuClick({
                                            menuPath: ["Edit","Select All"],
                                        });
                                        
                                        sf.ui.proTools.menuClick({
                                            menuPath: ["Edit","Fades","Delete"],
                                        });
                                        
                                        
                                        selecttrackbywordincomments();
                                        
                                        
                                        

                                        The problem with this is that it wont be a "open session and click" operation...

                                        1. KKensuke Matsui @Kensuke_Matsui
                                            2020-10-21 09:29:55.170Z

                                            Hello @samuel_henriques
                                            Thank you for your advice! And , There are a lot of editing points in my music session. so need to consolidate each song.
                                            It would be great If I could. I'll try to dig more.

                                            1. KKensuke Matsui @Kensuke_Matsui
                                                2020-10-21 09:39:18.253Z

                                                or create the region group of in and out points on the another track like this.

                                                1. samuel henriques @samuel_henriques
                                                    2020-10-21 09:56:07.119Z

                                                    That could work as well. I have a script to select all regions with same name, you could do a clip group from there, or on a new track, problem, as is, is if you have the same song more than once.

                                                    Untitled.mov (0.98 MiB)

                                                    1. samuel henriques @samuel_henriques
                                                        2020-10-21 10:18:33.329Z

                                                        but if you need to go one by one, better solution is to write a script to take selection start time, end time, duration and name and paste it on a spreadsheet one by one, as you select and press a button.
                                                        You need the list to have all the information of start, end and duration of each? Or you need only duration of all clips with same name?

                                                        1. KKensuke Matsui @Kensuke_Matsui
                                                            2020-10-21 14:54:16.831Z

                                                            Awesome!
                                                            I need all the information of name ,start and end,duration.

                                                            1. samuel henriques @samuel_henriques
                                                                2020-10-21 16:04:06.469Z

                                                                I think the idea I was proposing takes longer than what you proposed.

                                                                you can find the script to select all clips by same name here:

                                                                hope it helps

                                                                1. KKensuke Matsui @Kensuke_Matsui
                                                                    2020-10-22 08:59:40.063Z

                                                                    Wow This is really helpful macro. Thanks!

                                                2. In reply toKensuke_Matsui:
                                                  Kitch Membery @Kitch2020-10-20 10:50:14.965Z

                                                  My pleasure!

                                                3. Kitch Membery @Kitch2020-10-20 10:54:16.617Z

                                                  Nice work mate. If I find some time this week I’ll have a look through it :-)

                                                  1. samuel henriques @samuel_henriques
                                                      2020-10-20 16:22:51.965Z

                                                      Not sure if this is an a weird request, but the reason I had the original script on the automator, was so I could use the filter on computers I don't have yet or can't have SoundFlow. But now I really like the filter you made. Could you point me in the right direction to figure out how I could run/adapt your filter to javascript on automator? I'm having really hard time to even write stuff I thought was general javascript on the automator javascript. Thank you so much and I'm sorry if this is too weird.

                                                      1. Kitch Membery @Kitch2020-10-20 19:27:16.976Z

                                                        Hi @samuel_henriques,

                                                        My knowledge of javascript it quite SoundFlow focused. Although I have used automator before I gave up on it as I found SoundFlow more than met all my needs.

                                                        1. samuel henriques @samuel_henriques
                                                            2020-10-20 19:36:51.145Z

                                                            I see what you mean...although I'm just starting to learn about javascript, I'm exited to continue because I keep figuring out how stuff works in SoundFlow. Every time I try anything on automator, I get frustrated so fast, I guess I need more coding bases to start doing anything.
                                                            Anyway, thank you so much, you rock!!

                                                            1. Kitch Membery @Kitch2020-10-20 19:40:05.557Z

                                                              You are totally welcome mate. Keep up the great work. Rock on!!!

                                                      2. Curtis Macdonald @Curtis_Macdonald
                                                          2022-02-24 15:45:39.745Z

                                                          Wow what an amazing Script !!! Really want to use this, but when I try running this script I get an error: ClickButtonAction requires UIElement (line 273)

                                                          1. samuel henriques @samuel_henriques
                                                              2022-02-24 16:08:26.975Z

                                                              Hello Curtis,

                                                              I've made several changes to this script, you can find the latest version in the store

                                                              https://soundflow.org/store/lista-de-musica

                                                              You need change some details for you

                                                              on line 327 change what you would like appended to the save as pro tools and new saved list file:

                                                              const appendToName = "LISTA DE MUSICA"
                                                              

                                                              on line 367 change the word you add to comments so those tracks are included in the list:

                                                              let musicTracks = selecttrackbywordincomments("LISTADEMUSICA")
                                                              

                                                              line 339 change location to saved list file

                                                              const cueParentFolder = "~/MEOCloud/CUE SHEET";
                                                              
                                                              

                                                              there are other custom bits, but try this for now, and then we can figure out how to set it up to for your preference.

                                                      3. Kitch Membery @Kitch2020-10-17 22:58:23.421Z

                                                        Hi @samuel_henriques,

                                                        What are the steps that the automator applescript takes? I'm sure there would be a way to do it with SoundFlow.

                                                        1. samuel henriques @samuel_henriques
                                                            2020-10-17 23:16:41.797Z

                                                            Hey Kitch,

                                                            Soundlow does all the funny stuff and export of txt file, and saves on a folder with the automator action.

                                                            Automator has a applescript (long story) to clean unwanted lines of text. Would you like me to send it, and you can figure out how to get it to work with sound flow?

                                                            It filters lines starting with "1" and ending with "Unmuted" and deletes the first two words and last word.
                                                            filters lines staring with Channel. deletes the first two words and last word and keeps only one.

                                                            Then it gets the cleaned text to clipboard, opens OpenOffice and pastes the text.

                                                            Soundflow waits for the import text menu and takes care of the sorting and save to destination folder, it knows the destination because all the info is on the session name(I love this part).

                                                            1. Kitch Membery @Kitch2020-10-17 23:22:32.582Z

                                                              I can take a look at it... No promises yet though :-) Along with the applescript, can you also share a sample of a text file exported by pro tools that I can work with?

                                                              1. samuel henriques @samuel_henriques
                                                                  2020-10-17 23:32:46.133Z

                                                                  Here you go,

                                                                  on run {input, parameters}
                                                                  	-- Automator's "Run AppleScript" actions appear always to receive their input in list form.
                                                                  	-- If the input here contains only one item, and it's text, get a list of the text's 'paragraphs'.
                                                                  	if (((count input) is 1) and (class of item 1 of input is text)) then
                                                                  		set input to paragraphs of item 1 of input
                                                                  	end if
                                                                  	
                                                                  	set unwanteds to {"SAMPLE RATE:", "BIT DEPTH:", "SESSION START TIMECODE", ¬
                                                                  		"TIMECODE FORMAT:", "# OF AUDIO TRACKS:", "# OF AUDIO CLIPS:", ¬
                                                                  		"# OF AUDIO FILES:", "T", "TRACK NAME:", ¬
                                                                  		"COMMENTS:", "USER DELAY:", "STATE:", "2"}
                                                                  	
                                                                  	set output to {}
                                                                  	repeat with thisLine in input
                                                                  		set OKSoFar to true
                                                                  		repeat with thisBeginning in unwanteds
                                                                  			if (thisLine begins with thisBeginning) then
                                                                  				set OKSoFar to false
                                                                  				exit repeat
                                                                  			end if
                                                                  		end repeat
                                                                  		if (OKSoFar) then
                                                                  			if ((thisLine begins with "CHANNEL") or (character 1 of thisLine is in "0123456789")) then
                                                                  				set thisLine to text from word 3 to word -2 of thisLine
                                                                  			end if
                                                                  			if (thisLine is not in output) then set end of output to thisLine as text
                                                                  		end if
                                                                  	end repeat
                                                                  	
                                                                  	-- The following four lines convert the list of output lines to a single text.
                                                                  	-- Delete them if not wanted.
                                                                  	set astid to AppleScript's text item delimiters
                                                                  	set AppleScript's text item delimiters to linefeed
                                                                  	set output to output as text
                                                                  	set AppleScript's text item delimiters to astid
                                                                  	
                                                                  	return output
                                                                  end run
                                                                  
                                                                  
                                                                  

                                                                  SoundFlow_2020_PGM 00_LISTA DE MUSICA.txt (59.98 KiB)

                                                                  1. Kitch Membery @Kitch2020-10-18 00:17:15.859Z

                                                                    Thanks @samuel_henriques, Can you post what you want the text to look like after the applescript has run?

                                                                    1. samuel henriques @samuel_henriques
                                                                        2020-10-18 00:38:20.942Z

                                                                        this one is also sorted by start time. the sorting is not done by the script.

                                                                        SoundFlow_2020_PGM 00_LISTA DE MUSICA_clean and sorted by start time.xlsx (61.01 KiB)

                                                                        1. samuel henriques @samuel_henriques
                                                                            2020-10-18 00:44:11.352Z

                                                                            the sorting is not done by the script, but if it's possible, I guess would make sense to do. that way we would end up with clean and sorted text to place on any program anyone might need.

                                                                            1. Kitch Membery @Kitch2020-10-18 08:47:41.637Z

                                                                              @samuel_henriques... This my first attempt. It doesn't sort for you but will do the rest!

                                                                              Rock on! :-)

                                                                              const inputPath = '~/Desktop/SoundFlow_2020_PGM 00_LISTA DE MUSICA.txt';
                                                                              const outputPath = '~/Desktop/Cue Sheet.txt';
                                                                              
                                                                              function convertTextFile(inputPath, outputPath) {
                                                                                  let text = sf.file.readText({ path: inputPath }).text;
                                                                              
                                                                                  let sessionNameHeading = text.toString().split(':')[0].trim() + ':';
                                                                                  let sessionName = text.toString().split(':')[1].split('\n')[0].trim();
                                                                              
                                                                                  let textFileLines = text.split(/\n/g).filter(line => line.endsWith('Unmuted'))
                                                                                      .filter(line => line.startsWith('1'))
                                                                                      .join().split('\t').map(item => item.trim())
                                                                                      .join().split('Unmuted');
                                                                              
                                                                                  for (let i = 0; i < textFileLines.length; i++) {
                                                                                      if (textFileLines[i]) {
                                                                                          textFileLines[i] = textFileLines[i].split(',').filter(item => item).slice(2).join('\t');
                                                                                      }
                                                                                  }
                                                                              
                                                                                  let outputText = `${sessionNameHeading}\t${sessionName}\nCLIP NAME\tSTART TIME\tEND TIME\tDURATION\n${textFileLines.join('\n')}`;
                                                                              
                                                                                  sf.file.writeText({
                                                                                      path: outputPath,
                                                                                      text: outputText,
                                                                                  });
                                                                              }
                                                                              
                                                                              convertTextFile(inputPath, outputPath);
                                                                              
                                                                              1. samuel henriques @samuel_henriques
                                                                                  2020-10-18 11:26:13.682Z

                                                                                  Nice one @Kitch, already found an error on the applescript.

                                                                                  1. samuel henriques @samuel_henriques
                                                                                      2020-10-18 11:49:26.029Z

                                                                                      so far so good, but. if the name of song has a "," on the name, your script will replace it with a "tab" and when importing to openOffice will ad a column on those lines

                                                                                      1. samuel henriques @samuel_henriques
                                                                                          2020-10-18 11:55:19.373Z

                                                                                          this:
                                                                                          1 29 Big Sean - Blessings ft. Drake, Kanye West 00:22:04:18 00:22:07:16 00:00:02:23 Unmuted

                                                                                          will become:

                                                                                          Big Sean - Blessings ft. Drake Kanye West 00:22:04:18 00:22:07:16 00:00:02:23

                                                                                          notice the "," on "Drake, Kanye"

                                                                                          1. Kitch Membery @Kitch2020-10-18 12:18:09.311Z

                                                                                            Darn it!!!

                                                                                            I'll have to see how I can fix that tomorrow....

                                                                                            For now... Here is a version that sorts by start time :-)

                                                                                            const inputPath = '~/Desktop/SoundFlow_2020_PGM 00_LISTA DE MUSICA.txt';
                                                                                            const outputPath = '~/Desktop/Cue Sheet.txt';
                                                                                            
                                                                                            function convertTextFile(inputPath, outputPath) {
                                                                                                let data = sf.file.readText({ path: inputPath }).text;
                                                                                            
                                                                                                let sessionNameHeading = data.toString().split(':')[0].trim() + ':';
                                                                                                let sessionName = data.toString().split(':')[1].split('\n')[0].trim();
                                                                                            
                                                                                                let header = data.split('\n').filter(line => line.startsWith('CHANNEL'))[0].split('\t').map(item => item.trim()).slice(2, -1);
                                                                                            
                                                                                                let textFileLines = data.split(/\n/g).filter(line => line.endsWith('Unmuted'))
                                                                                                    .filter(line => line.startsWith('1'))
                                                                                                    .join().split('\t').map(item => item.trim())
                                                                                                    .join().split('Unmuted');
                                                                                            
                                                                                                let filteredLines = [];
                                                                                            
                                                                                                for (let i = 0; i < textFileLines.length; i++) {
                                                                                                    if (textFileLines[i]) {
                                                                                                        filteredLines[i] = textFileLines[i].split(',').filter(item => item).slice(2).join(',').split(',');
                                                                                                    }
                                                                                                }
                                                                                            
                                                                                                filteredLines.unshift(header);
                                                                                            
                                                                                                function convertToArrayOfObjects(data) {
                                                                                                    var keys = data.shift(),
                                                                                                        i = 0, k = 0,
                                                                                                        obj = null,
                                                                                                        output = [];
                                                                                            
                                                                                                    for (i = 0; i < data.length; i++) {
                                                                                                        obj = {};
                                                                                            
                                                                                                        for (k = 0; k < keys.length; k++) {
                                                                                                            obj[keys[k]] = data[i][k];
                                                                                                        }
                                                                                                        output.push(obj);
                                                                                                    }
                                                                                                    return output;
                                                                                                }
                                                                                            
                                                                                                let sortArray = convertToArrayOfObjects(filteredLines);
                                                                                            
                                                                                                sortArray.sort(function (a, b) {
                                                                                                    var nameA = a["START TIME"]
                                                                                                    var nameB = b["START TIME"]
                                                                                                    if (nameA < nameB) {
                                                                                                        return -1;
                                                                                                    }
                                                                                                    if (nameA > nameB) {
                                                                                                        return 1;
                                                                                                    }
                                                                                                    return 0;
                                                                                                });
                                                                                            
                                                                                                sortArray.forEach((e, i, array) => {
                                                                                                    sortArray[i] = e["CLIP NAME"] + '\t' + e["START TIME"] + '\t' + e["END TIME"] + '\t' + e["DURATION"] + '\n';
                                                                                                });
                                                                                            
                                                                                                sortArray.unshift("CLIP NAME" + '\t' + "START TIME" + '\t' + "END TIME" + '\t' + "DURATION" + '\n');
                                                                                                sortArray.unshift(sessionNameHeading + '\t' + sessionName + '\n');
                                                                                            
                                                                                                sf.file.writeText({
                                                                                                    path: outputPath,
                                                                                                    text: sortArray.join(''),
                                                                                                })
                                                                                            }
                                                                                            
                                                                                            convertTextFile(inputPath, outputPath);
                                                                                            
                                                                                            
                                                                                            1. samuel henriques @samuel_henriques
                                                                                                2020-10-18 12:42:03.022Z

                                                                                                Cool, thank you,

                                                                                                this one is deleting the time codes when the "," separation exists to compensate for columns.

                                                                                                and it's converting special characters like "á" and probably all others to "�".

                                                                                                1. and it's converting special characters like "á" and probably all others to "�".

                                                                                                  SoundFlow reads/writes files in the global standard UTF-8. Make sure to set the export to use UTF-8 encoding instead of TextEdit encoding when exporting data from Pro Tools.

                                                                                                  1. samuel henriques @samuel_henriques
                                                                                                      2020-10-18 14:09:00.879Z

                                                                                                      Nice one, fixed it. Thank you

                                                                                                      1. Kitch Membery @Kitch2020-10-18 16:40:12.433Z

                                                                                                        Awesome. Is it all working now @samuel_henriques?

                                                                                                        1. samuel henriques @samuel_henriques
                                                                                                            2020-10-18 17:08:30.805Z

                                                                                                            The special characters yes. The "," thing is the same

                                                                                                            1. samuel henriques @samuel_henriques
                                                                                                                2020-10-19 10:12:21.582Z

                                                                                                                Hello Kitch, if an easy solution is delete all "," from the hole text, I'm not seeing any problem with that. Even if the words glue. Ex "yadda,yadda" will be "yaddayadda". Does anyone see a problem with that?

                                                                                                                1. Kitch Membery @Kitch2020-10-19 10:15:50.809Z

                                                                                                                  Removing the “,” completely is certainly possible. I’ll take a look in the morning. There is also a way to paste the document into OpenOffice where it will ignore the “,” and only delimit by the tab “\t”

                                                                                                                  1. samuel henriques @samuel_henriques
                                                                                                                      2020-10-19 10:24:25.554Z

                                                                                                                      I think you're right. I tried some stuff but failed. I'll check it out again as soon as I get to computer. In the mean time I made it Automator free and the output of your filter goes to the clipboard, that way anyone can past it on a spreadsheet by changing the neoofice steps to whatever they are using. It also keeps the export from protools txt and final file on session folder. Seems easier to implement to anyone.

                                                                                                                    • Kitch Membery @Kitch2020-10-19 10:21:53.457Z2020-10-19 10:27:54.507Z

                                                                                                                      Here you go @samuel_henriques :-)

                                                                                                                      const inputPath = '~/Desktop/SoundFlow_2020_PGM 00_LISTA DE MUSICA.txt';
                                                                                                                      const outputPath = '~/Desktop/Cue Sheet.txt';
                                                                                                                      
                                                                                                                      function convertTextFile(inputPath, outputPath) {
                                                                                                                          let data = sf.file.readText({ path: inputPath }).text;
                                                                                                                      
                                                                                                                          let sessionNameHeading = data.toString().split(':')[0].trim() + ':';
                                                                                                                          let sessionName = data.toString().split(':')[1].split('\n')[0].trim();
                                                                                                                      
                                                                                                                          let header = data.split('\n').filter(line => line.startsWith('CHANNEL'))[0].split('\t').map(item => item.trim()).slice(2, -1);
                                                                                                                      
                                                                                                                          let textFileLines = data.split(/\n/g).filter(line => line.endsWith('Unmuted'))
                                                                                                                              .filter(line => line.startsWith('1'))
                                                                                                                              .join().split('\t').map(item => item.replace(/\,/g,"").trim())
                                                                                                                              .join().split('Unmuted');
                                                                                                                      
                                                                                                                          let filteredLines = [];
                                                                                                                      
                                                                                                                          for (let i = 0; i < textFileLines.length; i++) {
                                                                                                                              if (textFileLines[i]) {
                                                                                                                                  filteredLines[i] = textFileLines[i].split(',').filter(item => item).slice(2).join(',').split(',');
                                                                                                                              }
                                                                                                                          }
                                                                                                                      
                                                                                                                          filteredLines.unshift(header);
                                                                                                                      
                                                                                                                          function convertToArrayOfObjects(data) {
                                                                                                                              var keys = data.shift(),
                                                                                                                                  i = 0, k = 0,
                                                                                                                                  obj = null,
                                                                                                                                  output = [];
                                                                                                                      
                                                                                                                              for (i = 0; i < data.length; i++) {
                                                                                                                                  obj = {};
                                                                                                                      
                                                                                                                                  for (k = 0; k < keys.length; k++) {
                                                                                                                                      obj[keys[k]] = data[i][k];
                                                                                                                                  }
                                                                                                                                  output.push(obj);
                                                                                                                              }
                                                                                                                              return output;
                                                                                                                          }
                                                                                                                      
                                                                                                                          let sortArray = convertToArrayOfObjects(filteredLines);
                                                                                                                      
                                                                                                                          sortArray.sort(function (a, b) {
                                                                                                                              var nameA = a["START TIME"]
                                                                                                                              var nameB = b["START TIME"]
                                                                                                                              if (nameA < nameB) {
                                                                                                                                  return -1;
                                                                                                                              }
                                                                                                                              if (nameA > nameB) {
                                                                                                                                  return 1;
                                                                                                                              }
                                                                                                                              return 0;
                                                                                                                          });
                                                                                                                      
                                                                                                                          sortArray.forEach((e, i, array) => {
                                                                                                                              sortArray[i] = e["CLIP NAME"] + '\t' + e["START TIME"] + '\t' + e["END TIME"] + '\t' + e["DURATION"] + '\n';
                                                                                                                          });
                                                                                                                      
                                                                                                                          sortArray.unshift("CLIP NAME" + '\t' + "START TIME" + '\t' + "END TIME" + '\t' + "DURATION" + '\n');
                                                                                                                          sortArray.unshift(sessionNameHeading + '\t' + sessionName + '\n');
                                                                                                                      
                                                                                                                          sf.file.writeText({
                                                                                                                              path: outputPath,
                                                                                                                              text: sortArray.join(''),
                                                                                                                          })
                                                                                                                      }
                                                                                                                      
                                                                                                                      convertTextFile(inputPath, outputPath);
                                                                                                                      
                                                                                • K
                                                                                  In reply toKensuke_Matsui:
                                                                                  Kensuke Matsui @Kensuke_Matsui
                                                                                    2020-10-18 01:22:50.274Z

                                                                                    Thanks @samuel_henriques , @Kitch !!
                                                                                    I really appreciate your help!!