Copyright 2002-2015 Rick Mohr
 

To create a Vocola extension, create a .py file in the Vocola extension directory whose name starts with "vocola_ext_". Define one or more top-level Python routines and then add a special comment immediately before each of them that should be callable from Vocola to tell Vocola that they are extension functions/procedures and what name should be used to call them from Vocola. Here's a simple example:

1
2
3
4
5
6
7
8
9
10
11

import os

# Vocola function: Env.Get
def get(name):
    return os.environ[name]

# Vocola procedure: File.Append
def append(filename, line):
    f = open(filename, 'a')
    f.write(line + "\n")
    f.close()

Here we have defined an extension function, Env.Get, with 1 argument that returns the value of the environment variable with that name and an extension procedure, File.Append, with 2 arguments that appends the contents of its second argument to the file with the pathname of its first argument. To keep the example simple, we have omitted any error handling.

Vocola can usually infer how many arguments your routine takes, but you must tell it explicitly when your routine takes a variable number of arguments or your argument list takes up multiple lines. Here's another example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

import os

# Vocola function: Env.Get,1-2
def get(name, if_undefined=None):
    try:
        return os.environ[name]
    except KeyError:
        if if_undefined!=None:
            return if_undefined
        else:
            raise

# Vocola function: Math.Mult,0-
def product(*numbers):
    p = 1
    for n in numbers:
        p = p * long(n)
    return p

# Vocola function: Polynomial.Eval,3
def polynomial(x, y,
               z):
    # compute x^2 + 3y + z:
    return long(x)**2 + long(y)*3 + long(z)

Here, we have an improved version of Env.Get that can take 1 or 2 arguments; if no environment variable with the given name exists, then it throws a runtime error unless it was given a second argument, in which case it just returns that argument instead. The second function, Math.Mult, takes any number of arguments (even zero) and multiplies them together. We had to explicitly give the number of arguments (3) in the last case, Polynomial.Eval, only because its argument list is spread across multiple lines.

Internally all values in Vocola 2 are strings. Extension routines are passed strings (note the use of long(-) in the second example to convert the arguments to long integers) and the results of extension functions are converted back to strings via str(-).

Raising Exceptions

As you can see in the improved Env.Get example, extensions can simply raise normal Python exceptions and Vocola will treat them as a runtime error, stopping the current command sequence and printing an error message to the Messages from NatLink window. If you want to stop the current command sequence without printing an error message (perhaps you have already printed your own somewhere else), you can [as of version 2.8.5] raise VocolaRuntimeAbort, which you import from VocolaUtils.

Modifying Extensions

Once Vocola has loaded an extension, it continues to use its loaded version and thus will not see any changes you make to your extension. To explicitly cause Vocola to load a new version of your extension, use the "Load [Voice] Extensions" command. Note that that command does not reload non-extension modules (i.e., modules whose name does not start with vocola_ext_).