ManuScript is a simple, music-based programming language developed to write plug-ins for the Sibelius music processor.
It is based on Simkin, an embedded scripting language developed by Simon Whiteside (www.larts.co.uk/simkin.html), and has been extended by him and Graham Westlake. (Simkin is a spooky pet name for Simon sometimes found in Victorian novels.)
In adding a plug-in language to Sibelius we were trying to address several different issues:
Music notation is complex and infinitely extensible, so some users will sometimes want to add to a music notation program to make it cope with these new extensions.
It is useful to allow frequently repeated operations (e.g. opening a MIDI file and saving it as a score) to be automated, using a system of scripts or macros.
Certain more complex techniques used in composing or arranging music can be partly automated, but there are too many to include as standard features in Sibelius.
There were several conditions that we wanted to meet in deciding what language to use:
The language had to be simple, as we want normal users (not just seasoned programmers) to be able to use it.
We wanted plug-ins to be usable on any computer, as the use of PC?s, Macs and other platforms is widespread in the music world.
We wanted the tools to program in the language to be supplied with Sibelius.
We wanted musical concepts (pitch, notes, bars) to be easily expressed in the language.
We wanted programs to be able to talk to Sibelius easily (to insert and retrieve information from scores).
We wanted simple dialog boxes and other user interface elements to be easily programmed.
C/C++, the world?s ?standard? programming language(s), were unsuitable as they are not easy for the non-specialist to use, they would need a separate compiler, and you would have to recompile for each different platform you wanted to support (and thus create multiple versions of each plug-in).
The language Java was more promising as it is relatively simple and can run on any platform without recompilation. However, we would still need to supply a compiler for people to use, and we could not express musical concepts in Java as directly as we could with a new language.
So we decided to create our own language which is interpreted so it can run on different platforms; is integrated into Sibelius without any need for separate tools, and can be extended with new musical concepts at any time.
The ManuScript language that resulted is very simple. The syntax and many of the concepts will be familiar to programmers of C/C++ or Java. Built into the language are musical concepts (Score, Staff, Bar, Clef, NoteRest) which are instantly comprehensible.
Do we have to use ManuScript?
No: if you don?t want to write in ManuScript you can write a plug-in in any other language, provided you supply as a dynamically linked library (dll) in Sibelius?s Plugins folder. This is useful for writing complex plug-ins, which may need features not in ManuScript: for instance, the PhotoScore scanning plug-in is written in C. However, people who aren?t professional programmers will probably want to use ManuScript.
Since the ManuScript language is more the province of our programmers than our technical support team (who are not in the main programmers), we can?t provide detailed technical help on it, any more than Sun will help you with Java programming. This document and the sample plug-ins should give you a good idea of how to do some simple programming fairly quickly. We would welcome any useful plug-ins you write (email them to emailprotected and we may put them on our website).
Although only a subset of the notations Sibelius supports are available from ManuScript, we will extend it as time goes on with the features people need for the type of plug-ins they need to write. For instance, Sibelius itself has many more ways to insert notes than ManuScript currently provides; for instance, ManuScript does not allow you to insert tuplets or notes in subsidiary voices. This is mostly to sidestep delicate issues (What if you insert a tuplet that would cross a barline? How do you specify the position of a note in a tuplet?) that we may tackle when it becomes clearer what types of plug-in people actually need. Many plug-ins won?t need to touch the notes in a score at all. Your comments and any ideas for plug-ins that could be made possible by adding new features to ManuScript will be welcome.
A simple plug-in
Let?s start a simple plug-in. You are assumed to have some basic experience of programming (e.g. in BASIC or C), so you?re already familiar with ideas like variables, loops and so on.
Start Sibelius. In the Plug-ins menu, click on Edit plug-ins?, then click New. You are asked to type the internal name of your plug-in and the name that should appear on the menu. These are often different because the plug-in?s internal name isn?t allowed spaces or punctuation; in fact it can only consist of letters and digits (as long as it doesn?t start with a digit). The name that appears on the menu can be anything (as long as it doesn?t contain single or double quotes).
Type Test as the internal name and Test plug-in as the menu name, then click OK. You?ll see Test added to the list in the Edit plug-ins dialog. Click Close. If you look in the Plug-ins menu again you?ll see Test plug-in at the bottom. Click on Test plug-in and the plug-in will run. What does it do? It just pops up a dialog which says ?Test? (whenever you start a new plug-in, Sibelius fills in a 1-line program to do this). Click OK on the dialog and the plug-in stops.
Let?s look at what?s in the plug-in so far. Click Edit plug-ins again, then in the dialog box click on Test and click Edit (alternatively you can just double-click on Test to edit it). You?ll see a dialog box showing the 3 types of information that can make up a plug-in:
Methods: similar to procedures, functions or routines in some other languages.
Dialogs: the layout of any special dialog boxes you design for your plug-in.
Data: variables whose value is remembered between running the plug-in. These are quite like global variables in languages like C, but are most like member variables in C++ and Java or properties in Visual BASIC.
The actual program consists of the methods. As you can see, plug-ins normally have at least two methods, which are created automatically for you when you create a new plug-in:
Initialize: this method is called automatically whenever you start up Sibelius. Normally it does nothing more than add the name of the plug-in to the Plug-ins menu.
Run: this is called when you run the plug-in, you?ll be startled to hear (it?s like main() in C/C++ and Java). In other words, when you click on Test plug-in in the Plug-ins menu, its Run method is called. If you write any other methods, you have to call them from the Run method ? otherwise how can they ever do anything?
Click on Run and click Edit (or you can just double-click Run to edit it). This shows a dialog where you can edit the Run method. In the top field you can edit the name; in the next field you can edit the parameters (i.e. variables where values passed to the method are stored); and below is the code itself:
This calls a method MessageBox which pops up the dialog box that says Test1 when you run the plug-in. Notice that the method name is followed by a list of parameters in parentheses. In this case there?s only one parameter: because it?s a string (i.e. text) it?s in double quotes. Notice also that the statement ends in a semicolon, as in C/C++ and Java. If you forget to type a semicolon, you?ll get an error when the plug-in runs.
What is the role of the word Sibelius in Sibelius.MessageBox? In fact it?s a variable representing the Sibelius program; the statement is telling Sibelius to pop up the message box (C++ and Java programmers will recognize that this variable refers to an ?object?). If this hurts your brain, we?ll go into it later.
Now try amending the code slightly. You can edit the code just like in a word processor, using the mouse and arrow keys, and you can also also use Ctrl+X, Ctrl+C and Ctrl+V for cut, copy and paste. If you right-click you get a menu with these basic editing operations on them too.
Change the code to this:
x = 1;
x = x + 1;
Sibelius.MessageBox(“1 + 1 = ” & x);
You can check this makes sense (or, at least, some kind of sense) by clicking the Check syntax button. If there are any blatant mistakes (e.g. missing semicolons) you?ll be told where they are.
Then close the dialogs by clicking OK, OK again then Close. Run your amended plug-in from the Plug-ins menu and a dialog box with the answer 1 + 1 = 2 should appear.
How does it work? The first two lines should be obvious. The last line uses & to stick two strings together. You can?t use + as this works only for numbers (if you try it in the example above, you?ll get an interesting answer!).
One pitfall: try changing the second line to:
x += 1;
then click Check syntax. You?ll get an error: this syntax (and the syntax x++) is allowed in various languages but not in ManuScript. You have to do x = x+1; .
Where plug-ins are stored
Plug-ins are stored in the folder called Plugins inside your Sibelius folder (typically C:Program FilesSibelius SoftwareSibeliusPlugins). This is worth knowing if you want to give a plug-in to someone else. The filename is the plug-in?s internal name plus the ?.plg? extension, e.g. ?Test.plg?.
Line breaks and comments
As with C/C++ and Java, you can put new lines wherever you like (except in the middle of words), as long as you remember to put a semicolon after every statement. You can put several statements on one line, or put one statement on several lines.
You can add comments to your program, again like C/C++ and Java. Anything after // is ignored to the end of the line. Anything between /* and */ is ignored, whether just part of a line or several lines:
// comment lasts to the end of the line
/*you can put
several lines of comments here
Sibelius.MessageBox(“Hi!”);// print the active score
Sibelius /* this contains the application */ .MessageBox(“Hi!”);
?x? in the Test plug-in is a variable. In ManuScript a variable can be any sequence of letters, digits or _ (underscore), as long as it doesn?t start with a digit.
A variable can contain an integer (whole number), a string (text) or an object (e.g. a note) ? more about objects in a moment. Unlike most languages, in ManuScript a variable can contain any type of data ? you don?t have to declare what type you want. Thus you can store a number in a variable, then store some text instead, then an object. Try this:
x = 56;
x = x+1;
Sibelius.MessageBox(x);// prints ?57? in a dialog box
x = “now this is text”;// the number it held is lost
Sibelius.MessageBox(x);// prints ?now this is text? in a dialog
x = Sibelius.ActiveScore;// now it contains a score
Sibelius.MessageBox(x);// prints nothing in a dialog
Converting between numbers, text and objects
Notice that the method MessageBox is expecting to be sent some text to display. If you give it a number instead (as in the first call to MessageBox above) the number is converted to text. If you give it an object (such as a score), no text is produced.
Similarly, if a calculation is expecting a number but is given some text, the text will be converted to a number:
x = 1 + “1”;// the + means numbers are expected
Sibelius.MessageBox(x);// displays ?2?
If the text doesn?t start with a number (or if the variable contains an object instead of text), it is treated as 0:
x = 1 + “fred”;
Sibelius.MessageBox(x);// displays ?1?
The while loop
ManuScript has a while loop which is does the same duties as while, do and for loops in other languages. Create a new plug-in called Potato. This is going to amuse one and all by writing the words of the well-known song ?1 potato, 2 potato, 3 potato, 4?. Type in the following for the Run method of the new plug-in (if you?re lazy and you?re reading this as a Word document, you could just copy and paste the code):
x = 1;
text = x & ” potato,”;
x = x+1;
Run it. It should display ?1 potato?, ?2 potato?, ?3 potato?, ?4 potato?, which is a start, though annoyingly you have to click OK after each message.
The while statement is followed by a condition in ( ) parentheses, then a block of statements in } braces (you don?t need a semicolon after the final } brace). While the condition is true, the block is executed. Unlike some other languages, the braces are compulsory (you can?t omit them if they only contain one statement). We did say that ManuScript was a simple language.
In this example you can see that testing the value of x at the start of the loop, and increasing the value at the end, gives the same effect as for loops in other languages. You can use other simple techniques (such as if statements) to simulate the do loops and break/continue statements you thought you couldn?t do without.
Notice the use of & to add strings. Because a string is expected on either side, the value of x is turned into a string.
Notice also that I?ve typed the Tab key to indent the statements inside the loop. This is a good habit to get into as it makes the structure clearer. If you have loops inside loops you should indent the inner loops even more.
The if statement
Now we can add an if statement so that the last phrase is just ?4?, not ?4 potato?:
x = 1;
text = x & “.”;
text = x & ” potato,”;
x = x+1;
The rule for if takes the form if (condition) statements }. You can also optionally add else statements } which is executed if the condition is false. As with while, the parentheses and braces are compulsory, though you can make the program shorter by putting braces on the same line as other statements:
x = 1;
text = x & “.”;
text = x & ” potato,”;
x = x+1;
The position of braces is entirely a matter of taste.
You can put any expressions in parentheses after an if or while statement, but typically they will contain conditions such as = and <. The available conditions are very simple:
a = bequals (for numbers, text or objects)
a < bless than (for numbers)
a > bgreater than (for numbers)
c and dboth are true
c or deither are true
not cinverts a condition, e.g. not(x=4)
Note that you use = to compare for equality, not the barbaric == found in C/C++ and Java.
Instead of != or <> in other languages, use not(a=b).
Instead of a <= b, use not(a > b). Or you could try (a<b or a=b).
Instead of a >= b, use not(a < b). Or you could try (a>b or a=b).
Now let?s make this plug-in really cool. We can build up the four messages in a variable called text, and only display it at the end, saving valuable wear on your mouse button. We can also switch round the if and else blocks to show off the use of not:
x = 1;
text = “”;// start with no text
text = text & x & ” potato, “;// add some text
text = text & x & “.”;// add no. 4
x = x+1;
Sibelius.MessageBox(text);// finally display it
We?ve been using + without comment, so here?s a complete list of the available arithmetic operators:
a + badd
a ? bsubtract
a * bmultiply
a / bdivide
a % bremainder
The normal precedence for these operators applies; in other words, 2+3*4 is 14, not 20, because * is evaluated before +. To make this clearer you could write 2+(3*4). To get the answer 20, you?d have to write (2+3)*4.