/* mmr.js by Warren Porter Multi Measure Rest Tool This tool gives the user the ability to convert consecutive measures of whole rests into Multi-Measure Rests. When hidden, the user can choose to show bars and rests, bars only, rests only, or neither. If a "conductor" or "tempo" staff is being layered into a part to be printed, the "LayerHide" option will prevent any MMR on that part from being displayed. Boundary collapse and cancel collapse commands are created around the multi measure rests. Changes made can be backed out with the "Undo" prompt. All options on the 2nd prompt are ignored. The above boundary commands are removed and MMRs are replaced by the approprate number of whole rests separated by bar lines. This tool can operate on ONLY a selected part of a staff, or, if nothing has been selected, the entire staff. */ rc=0, errMsg=""; function doProcess(clip) { var result=new Array(), nlines=new Array(), ii=0, lastBar=-1,cntRest=0,lastRest=0; var mmrOption = "|PrintOnce:Y"; if (WScript.Arguments.Item(1) == "ShowAll") mmrOption += "|WhenHidden:ShowBars,ShowRests"; else if (WScript.Arguments.Item(1) == "ShowBar") mmrOption += "|WhenHidden:ShowBars"; else if (WScript.Arguments.Item(1) == "ShowRst") mmrOption += "|WhenHidden:ShowRests"; else if (WScript.Arguments.Item(1) == "LayerHide") mmrOption = "|PrintOnce:N|Visibility:Never"; // Used for hiding tempo or conductor stave. lines = clip.split("\r\n"); // lines === existing lines; nlines === lines to be created for (var i=0; i < lines.length; i++) { // Main processing loop switch (cntRest) { case 0 : if (lines[i].slice(0,15) == "|Rest|Dur:Whole") { //Found first rest cntRest++; lastRest = i; } else { nlines[ii++] = lines[i]; } // Didn't find a rest and have no backlog, copy line to OP array. break; case 1 : // Have found exactly one whole rest if (lines[i].slice(0,15) == "|Rest|Dur:Whole") { cntRest++; lastBar = 0; } else if ((lines[i].slice(0,4) == "|Bar") && (lines[i].slice(4,11) != "|Style:")) { lastBar = i; } else { // Found whole rest not followed by bar or another rest if (lastRest) { for ( ; lastRest <= i; lastRest++) { nlines[ii++] = lines[lastRest] } cntRest=0,lastBar=0; } } break; default: // cntRest is 2 or more. if (lines[i].slice(0,15) == "|Rest|Dur:Whole") { cntRest++; lastBar = 0; } else if ((lines[i].slice(0,4) == "|Bar") && (lines[i].slice(4,11) != "|Style:")) { lastBar = i; } else { // Found whole rest not followed by bar or another rest, must create MMR nlines[ii++] = "|Boundary|Style:Collapse"; nlines[ii++] = "|RestMultiBar|NumBars:" + cntRest + mmrOption; if (lines[i].slice(0,27) != "!NoteWorthyComposerClip-End" || lastBar) { nlines[ii++] = "|Boundary|Style:EndCollapse"; } cntRest = 0; if (lastBar) // If MMR was followed by a barline and something else nlines[ii++] = lines[lastBar]; // first move the barline over lastBar = 0; nlines[ii++] = lines[i] // Move the non-rest non-bar over to OP buffer. } } //End of switch } //End main processing loop /* Next loop will place the Boundary Collapse BEFORE a bar line and the Cancel Collapse AFTER a bar line. This will stop empty bars from being displayed when a part begins or ends on a complete system. The loop after that will remove EndCollapse and Collapse when they are next to each other. */ for (i=1; (i+1) < nlines.length; i++) { // Start fixit loop. if ((nlines[i].slice(0,4) == "|Bar") && (nlines[i+1].slice(0,24) == "|Boundary|Style:Collapse")) { var tempi = nlines[i]; nlines[i] = nlines[i+1]; nlines[++i] = tempi; } else if ((nlines[i].slice(0,27) == "|Boundary|Style:EndCollapse") && (nlines[i+1].slice(0,4) == "|Bar")) { tempi = nlines[i]; nlines[i] = nlines[i+1]; nlines[++i] = tempi; } } //End fixup loop for (i=1; (i+1) < nlines.length; i++) { if ((nlines[i].slice(0,27) == "|Boundary|Style:EndCollapse") && (nlines[i+1].slice(0,24) == "|Boundary|Style:Collapse")) { nlines[i] = "#"; //Turn both lines into a comment nlines[++i] = "#"; } else if (WScript.Arguments.Item(1) == "LayerHide" && nlines[i].slice(0,5) =="|Rest" && nlines[i].indexOf("|Visibility:Never") == -1) nlines[i]+= "|Visibility:Never"; } return nlines; } /* !NoteWorthyComposerClip(2.51,Single) |Rest|Dur:Half |Tempo|Tempo:70|Pos:10 |Rest|Dur:4th|Visibility:Never |Tempo|Tempo:67|Pos:10 |Rest|Dur:4th |Bar|Visibility:Never |Rest|Dur:Whole|Visibility:Never !NoteWorthyComposerClip-End */ function doUndo(clip) { var result=new Array(), nlines=new Array(), ii=0, lastRest=0,cntRest=0; var restLit = "|Rest|Dur:Whole", barLit = "|Bar"; lines = clip.split("\r\n"); // lines === existing lines; nlines === lines to be created for (var i=0; i < lines.length; i++) { // Main processing loop if (lines[i].match(/Boundary.*Collapse/) != null) continue; result = lines[i].match(/(RestMultiBar\|NumBars:)(\d+)(\|PrintOnce)/) if (result == null) { nlines[ii++] = lines[i]; } else { lastRest = Number(result[2]) for (cntRest=0; cntRest < lastRest; cntRest++) { nlines[ii++] = restLit; if ((cntRest + 1) < lastRest) nlines[ii++] = barLit; } } } //End main processing loop if (WScript.Arguments.Item(1) == "LayerHide") { for (i = 0; i < nlines.length; i++) if (result = nlines[i].match(/Rest.*Never/)) nlines[i] = nlines[i].replace("|Visibility:Never","") } return nlines; } var myLines; if (WScript.Arguments.length != 2) { errMsg="NO Prompt read."; rc=1; } else { if (WScript.Arguments.Item(0).slice(0,4) == "Undo") myLines=doUndo(WScript.StdIn.ReadAll()).join("\r\n"); else myLines=doProcess(WScript.StdIn.ReadAll()).join("\r\n"); } if (rc == 0) WScript.StdOut.Write(myLines); else WScript.StdErr.Write(errMsg); WScript.quit(rc);