6
Using two screens, the key combination CTRL+F8 that is defined as "repeat Last User Tool" doesn't work for me since Windows intercepts my command and manipulates my screen settings.
But, I found a useful little tool that let me assign a specific key to a sequence of keystrokes: AutoHotKey (https://autohotkey.com/)
After installation of the AutoHotKey program, create a little text based script, right click on it and choose "run script" (or double click on it if it has the .ahk extension, because then running is the default action). As soon as you touch the hotkey, your bunch of keystrokes is executed.
This little script defines function key F12 as my "repeat Last User Tool":
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
if WinExist("ahk_exe NWC2.exe")
WinActivate, ahk_exe NWC2.exe
f12::
send, {alt down}t{alt up}e
Return
Following the information in the AutoHotKey documentation, even combination of different key definitions (also for different programs) is possible in one ahk.script.
Bart
7
"This tool mutes the active staff and adds 2 copies with all its relevant information into 2 new sibling staves with two different instrument patches." -- added as suggested --
For the people who want to learn LUA as a scripting language for Noteworthy Composer, I can distribute a LUA script I made myself a few months ago. I didn't publish it because it is all hard coded and therefore only usable for people who can make their own customization. I created this tool to speed up things, and didn't want it to slow down with user input boxes, etc.
Therefore it is not usable as a universal user tool. If you want to "tune" the tool, you will have to hack the code.
I must admit that it took a lot of time. There are only a few examples in the documentation and it was - for me - not the most comprehensive source of information. For creating my script, I combined the LUA documentation (https://lua.noteworthycomposer.com/) with the examples I found in the cloud. But most of my knowledge I got from examples that Rick G and Opagust posted in the forum. Without their work I wouldn't be able to create this script.
As far as I understand, LUA is the preferred scripting language for user tools. I am not aware if it is also a good choice for user objects.
There are different modes for LUA scripts and the mode should correspond with the option how a user tool should run. In this example FileText mode is used. A check for this mode is made with the method "nwcut.getprop('Mode')" in the first line of the main processing module.
LUA is a nested table oriented tool and has more flexibility in (nested) table manipulation as in text strings. These nested tables (also defined as objects) can be mapped on the structure of NWC files.
If "nwc.setlevel(2)" is specified, nwcobjects are interpreted as objects (or nested tables). You can force your script with a lower level (1) in text mode but it turned out - for me - that this is less flexible.
The structure of my script is as follows:
(1) check mode and returnmode
(2) define an object (or empty nested table) "mt" where the whole existing nwc-file will be staged and which can be printed out at the end of the script.
(3) loop over the nwc-file and collect interesting properties in variables, modify the properties - if desired -, and stage the result (original or modified) in "mt"
(3.1) all non-current staves are staged (almost) unmodified in "mt"
(3.2) the "current" staff is staged modified (muted) in "mt"
(3.3) the "current" staff is twice duplicated as "siblings" and - with modified visual and sound properties - staged in table "ST1" and "ST2".
(3.4) existing siblings of the "current" staff are skipped.
(4) at the end, all staged staves are "printed out". If nwcut.status is rc_succes the existing score is overwritten, if nwcut.status = rc_Report, the output is sent to the log window - wich is very useful in debugging mode.
I make a detour to strings before using "newItem.new" to achieve real duplicates and not new pointers to the same content. This was a real pitfall for me!
-- $NWCUT$CONFIG: FileText $
nwcut.setlevel(2)
nwcut.status = nwcut.const.rc_Succes
--nwcut.status = nwcut.const.rc_Report
local progname = 'Sibling'
local ASI = 0 -- Active Staff Parameters
local ASN = "UnDefined";
local CSI = 0 -- Current Staff Parameters
local CSN = "UnDefined";
local DSG = "SIBLINGS"
local DSPN = "SiblingInstrument"
local HelpMsg = [[
This tool mutes the active staff and adds 2 copies all its relevant information into 2 new sibling staves.
The active staff is slightly modified if it is not already in this state: the instrument is explicitely specified [line 33] and the staff is muted [line 34].
If staves with sibling name <original_name>_Sibling1 or <original_name>_Sibling1 already exist, they will be removed [line 36].
2 (hidden) sibling staves are added at the end of the score based on the ActiveStaff (named : <original_name>_sibling<i>) [line 67 and line 68].
The midi channels used for sibling staves are 15 and 16 [line 48] and since they are at the end of the score, they will override midi definitions for staves that were assigned earlier to these channels.
The sibling staves are made invisible to avoid sibling them again [line 52].
The sibling staves receive Instrument Patches 00 (piano) and 89 (Pad 2 warm) [line 56].
Instrument changes in the ActiveStaff are skipped in the sibling [line 58].
]]
--------------------------------------
-- Main processing -------------------
--------------------------------------
assert(nwcut.getprop('Mode') == nwcut.const.mode_FileText, "Input type must be 'File Text'")
assert(nwcut.getprop('ReturnMode') == nwcut.const.mode_FileText, "Under 'Options', check 'Returns File Text'")
mt = {} ; mt[0]={}
for item in nwcut.items() do
if item:Is('Editor') then ASI = item.Opts.ActiveStaff + 0 ; end--if
if item:Is('AddStaff') then CSI = CSI + 1 ; mt[CSI] = {} ; CSN = item.Opts.Name.Text ; CSOGN = item.Opts.Group.Text ; if CSI == ASI then ASN = CSN end ; end--if
if item:Is('StaffInstrument') then if not item.Opts.Patch then item.Opts.Patch=0 end ; if not item.Opts.Name then item.Opts.Name="\"NN\"" end ; end--if
if item:Is('StaffProperties') and ( CSI == ASI ) and ( item.Opts.Muted ) then item.Opts.Muted="Y" end--if
if not ( string.gsub(CSN,'%-','_') == string.gsub(ASN,'%-','_').."_sibling1" or string.gsub(CSN,'%-','_') == string.gsub(ASN,'%-','_').."_sibling2" ) then table.insert(mt[CSI],tostring(item)) end--if
if CSI == ASI then
SS1 = nwcItem.new(tostring(item)) ; SS2 = nwcItem.new(tostring(item))
if item:Is('AddStaff') then
SS1.Opts.Name = CSN .. "_sibling1" ; SS2.Opts.Name = CSN .. "_sibling2" ;
SS1.Opts.Group = DSG ; SS2.Opts.Group = DSG
ST1 = {} ; ST2 = {} ;
end--if
if item:Is('StaffProperties') then
if ( item.Opts.Muted or item.Opts.Channel or item.Opts.Volume or item.Opts.StereoPan) then
SS1.Opts.Muted = "N" ; SS2.Opts.Muted = "N"
SS1.Opts.Channel = 15 ; SS2.Opts.Channel = 16
SS1.Opts.Volume = 100 ; SS2.Opts.Volume = 100
SS1.Opts.StereoPan = 64 ; SS2.Opts.StereoPan = 64
elseif item.Opts.Visible then
SS1.Opts.Visible = "N" ; SS2.Opts.Visible = "N"
end--if
end--if
if item:Is('StaffInstrument') then
SS1.Opts.Patch = 89 ; SS2.Opts.Patch = 0 ;
SS1.Opts.Name = DSPN ; SS2.Opts.Name = DSPN
end--if
if item:Is('TempoVariance') and item.Opts.Pause then SS1.Opts.Pause = 0 ; SS2.Opts.Pause = 0 ; end--if
if not item:Is('Instrument') then table.insert(ST1,tostring(SS1)) ; table.insert(ST2,tostring(SS2)) ; end--if
end--if
end--for
for j=0,CSI do
for i=1,#mt[j] do nwcut.writeline (mt[j][i]) end--for
end--for
for i=1,#ST1 do nwcut.writeline (ST1[i]) end--for
for i=1,#ST2 do nwcut.writeline (ST2[i]) end--for
11
In previous versions, when you applied a tie on a chord, the tie for note members did not appear if the following chord did not have that note.
In the newest versions (2.5.1 and 2.5.4) the tie for chord members does appear and remains until that note appears again.
I doubt that this feature was introduced on purpose.
!NoteWorthyComposerClip(2.5,Single)
|Clef|Type:Treble
|Instrument|Name:"String Ensemble 1"|Patch:48|Trans:0|DynVel:10,30,45,60,75,92,108,127|Pos:8
|Chord|Dur:Half|Pos:-6^,-3^,-1^
|Chord|Dur:Half|Pos:-7,-5,-2
|Chord|Dur:Half|Pos:-6,-4,-2
!NoteWorthyComposerClip-End
12
If no specific midi instructions are given, the states from a previous version are kept. So far so good. But, this can lead to unwanted behavior as you will find an example below in nwctxt-format.
F6 or the stop button (sometimes twice) is then a way to reset all the channels.
Is it on purpose that at the beginning of a new score the midi channels are not reset? Are there known disadvantages?
Are there alternatives to avoid the cacaphony in bar 3?
!NoteWorthyComposerClip(2.0,Single)
|Clef|Type:Treble
|SustainPedal|Pos:-8|Wide:Y
|Instrument|Name:"Acoustic Grand Piano"|Patch:0|Trans:0|DynVel:10,30,45,60,75,92,108,127|Pos:7|Wide:Y
|Note|Dur:4th|Pos:-6
|Note|Dur:4th|Pos:-4
|Note|Dur:Half|Pos:-2
|Bar
|Text|Text:"ACTIVE SCORE STOPPED"|Font:StaffItalic|Pos:-10
|Text|Text:"NEW SCORE STARTED"|Font:StaffItalic|Pos:-17
|Rest|Dur:Whole
|Bar
|Instrument|Name:"Church Organ"|Patch:19|Trans:0|DynVel:10,30,45,60,75,92,108,127|Pos:7|Wide:Y
|Note|Dur:4th|Pos:-1
|Note|Dur:4th|Pos:-3
|Note|Dur:Half|Pos:-4
|Bar
|Rest|Dur:Whole
|Bar
|SustainPedal|Status:Released|Pos:-8|Wide:Y
|Text|Text:"WANTED BEHAVIOR"|Font:StaffItalic|Pos:-16
|Rest|Dur:Whole
|Bar
|Instrument|Name:"Church Organ"|Patch:19|Trans:0|DynVel:10,30,45,60,75,92,108,127|Pos:7|Wide:Y
|Note|Dur:4th|Pos:-1
|Note|Dur:4th|Pos:-3
|Note|Dur:Half|Pos:-4
|Bar
!NoteWorthyComposerClip-End
Kind regards,
Bart