jambient script

Jambient script lets you extend jambient by automating tasks and responding to events that happen in jambient's user interface. It is an extension of MicroSoft's VBScript—it is VBScript with one special object, called jam, which lets you make calls to jambient's engine.

The following documentation introduces jambient script and its integration into jambient, and provides a reference to jambient script calls. Together with the sample scripts, this should get you started in scripting.

The documentation assumes knowledge of programming, either in Microsoft's VB language family, or general programming proficiency.

Basic notes to all programmers:

To use jambient script you need the following:

Familiarity with jambient and its terminology.

Some familiarity with Microsoft's VBScript (or related languages such as Visual Basic or Visual Basic for applications). If you are familiar with other computer or scripting languages, this won't be very hard to pick up. Complete documentation of VBScript is available from Microsoft.

Basic familiarity with principles of object oriented and event based programming. You make calls to the jambient engine using the properties and methods of the jam object. You write handlers for events in the user interface. The document contains a crash course on object syntax. (Note that you don't need to program in an object oriented style, other than to make calls to the jam object.)

An installation of the Microsoft Scripting Engine for VBScript, available free from Microsoft. It might already be included if you have the right version of Explorer, but who can keep track of these things. You'll get a message from jambient if you need to install it.

A text editor suitable for editing code. We recommend ConTEXT, a freeware programmer's editor available at www.download.com, or any similar programmer's editor—display of line and column numbers is crucial, since jambient uses these numbers to tell you about errors in your code.

The Scripting Engine and documentation for VBScript are currently available at msdn.microsoft.com/scripting. Look for both under the heading VBScript.

Performance issues

Scripting is the most processor intensive part of jambient, since jambient, via the Microsoft Scripting Engine, has to interpret it, and make calls from events to your script. Try to avoid scripts that are heavy on the script clock. Space out clock based updates. For example, move all loop positions on sequential clock firings, rather than moving them all on one clock firing. Make sure your user can control the clock firing rate, by attaching a slider that controls jam.ClockInterval. Using the scripts subtab of the options tab, users can adjust the update frequency of events that are called when knobs are twiddled or looptracks are moved around.

Constants for identifying LoopTracks, etc.

In jambient script, LoopTracks are identified by an index number 1-16 for loops A to P, and 17 for the Gang. The Listener is also identified as LoopTrack 17 in the methods that position loops.

There are other sets of constants that are used to enumerate play states, play modes, fade directions and the types of objects you can add to the script window.

For a list of these constants and their values, see the top of the example files. It is a good idea to include these constants in each script, to make them more readable.

Structure of this documentation

Section 1 documents the structural components of a jambient script—special subroutines that jambient knows when to run, so that your scripts can do something. It also documents the way that you ask jambient to build interface objects in the script window. Using these object,  you can in effect pass parameters to your script with a nice set of controls that extend the jambient interface.

Section 2 is a reference to all the methods and properties of the jam object. Use these methods and properties throughout your code

1) The basic components of a jambient script

A jambient script is a set of subroutines. You can write special subroutines with special names that are automatically run when jambient loads a script or that respond to events in the main and scripting windows of jambient. Use these special subroutines to get something to happen in jambient and get the ball rolling—otherwise your script will be loaded, but jambient will never call any of it.

There are three sorts of special subroutines that you can write:

Event handlers: These are called each time certain events happen in the main window, such as a user changing a volume knob or moving a looptrack position.  There is also a scripting clock that you can control, and that fires an OnClock event on each tick. There nine event handlers, with nine prespecifed names.

Initializers: These are automatically run when a script is loaded. Use them to intialize global variables and construct interface objects in the script window, or to start an ongoing automation process. Jambient lets you add buttons, sliders, check boxes and dropdown lists to the scripting window. Any sub that begins with the letters Init (case insensitive) is an initializer and will be run when a script is loaded.

Script Interface handlers: These are called each time one of the script interface objects you've constructed is manipulated by the user. When you construct a script interface object, you also specify which handler to call. You specify the name of these handlers when you attach controls to the scripting window. Your handlers have to have the form (parameters) appropriate to handling events from the different controls.

Generally, jambient scripts are organized into blocks of related subroutines. For example, code to handle clock events might be grouped together with: an initializer that builds script interface objects that allow the user to adjust parameters of the clock event handler; and script interface handlers that deal with those script interface objects. The intializer should be placed after the other bits of code, especially interface handlers for objects constructed by the initializer, so the handler is already loaded when the initializer is run. Also, interface objects are placed in the scripting window in the order in which they are created. So the order of components in a script is important to the look of the interface it creates, and to the reusability of bits of code.

1.A) Event handlers:

There are nine event handlers, which are identified by preset names. If jambient loads a script containing a subroutine that has one of these special names, it will call the subroutine whenever the associated event occurs, unless the user has disabled that event using the events menu, or your script disables it using the jam.EnableEvent method (with false passed for the Enabled parameter). The subroutines must have the parameters defined below.

Uses for the event handlers

By attaching code to event handlers, you can, e.g., set processes that happens every few milliseconds, each time OnClock is fired or, that happen at specific times during a session. Or you can set up relations between knobs, for example when the master knob in one bands goes up, the master knob in another band goes down (use the delta parameters to do this). You can also make loops follow one another around in the the 3d map using the the OnPositionScroll event, or make them move in circles, etc. by writing an OnClock event that moves them every few milliseconds. See the example scripts.

Sub OnVolChange(LoopIndex, Vol)

This sub is called when the user releases the mouse after dialing the volume knob. LoopIndex is the index of the looptrack, Vol is the volume value for the looptrack, from 0-500.

Sub OnVolScroll(LoopIndex, Vol, DVol)

This sub is called while the user dials the volume knob. LoopIndex is the index of the looptrack, Vol is the volume value for the looptrack, from 0-500, DVol is the delta from the previous volume setting.

Sub OnPitchChange(LoopIndex, Pitch)

This sub is called when the user releases the mouse after dialing the pitch knob. LoopIndex is the index of the looptrack, Pitch is the pitch value for the looptrack, from 1-400 (percent).

Sub OnPitchScroll(LoopIndex, Pitch, DPitch)

This sub is called while the user dials the pitch knob. LoopIndex is the index of the looptrack, Pitch is the pitch value for the looptrack, from 1-400 (percent), DPitch is the delta from the previous pitch.

Sub OnPanChange(LoopIndex, Pan)

This sub is called when the user releases the mouse after dialing the pan knob. LoopIndex is the index of the looptrack, Pan is the pan value for the looptrack, from –500-500 where 0 is centred.

Sub OnPanScroll(LoopIndex, Pan, DPan)

This sub is called while the user dials the pan knob. LoopIndex is the index of the looptrack, Pan is the pan value for the looptrack, from –500-500 where 0 is centred, DPan is the delta from the previous pan.

Sub OnPositionChange(LoopIndex, X, Y)

This sub is called when the user has finished moving a looptrack position or the listener with the mouse. LoopIndex is the index of the looptrack  (=17 for the listener), X and Y the new x and y coordinates. (Note that the OnPositionChange event is not triggered by joystick movement of the Listener—this is because there is no good way to determine when this has finished.)

Sub OnPositionScroll(LoopIndex, X, Y, DX, DY)

This sub is called as the user moves a looptrack position or the listener with the mouse, and while the listener is moved with the joystick. LoopIndex is the index of the looptrack  (=17 for the listener), X and Y the new x and y coordinates, DX and DY are the deltas from the previous position. 

Sub OnClock(DeltaMilliSeconds, SessionSeconds, SessionMilliSeconds)

This is call each time the scripting clock fires. The scripting clock is controlled through the properties jam.Clock and jam.ClockInterval. DeltaMilliSeconds is the number of millisseconds since the last firing, SessionSeconds and SessionMilliseconds are the seconds and milliseconds since jambient was started.

 

1.B) Initializers:

Any sub that begins with the letters Init (case insensitive) is an initializer and is run as soon as jambient loads a script. Use these to initalize variables and build a user interface. Initializers are run in the order in which they appear in your script, and the order in which control objects are displayed follows the order in which they are created in initializers.

 

1.C) Script interface controls and script interface handlers:

jambient script lets you create checkboxes, buttons, dropdown lists and sliders in the scripting window, and specify subroutines that will handle events produced when the user manipulates these controls. Typically controls are created in an initializer for a related set of subroutines. For example, an initializer that creates checkboxes and sliders that let you control the scripting clock, would follow the handlers for these controls and follow an OnClock handler that does some something at every clock tick.

 

The basic procedure for creating controls is as follows: call the method jam.AttachControl, specifying the handler you want the control to call, the type of control you want to create, and a unique name for the control object. If AttachControl returns true, then the control object was successfully created, and you can call the control object's methods and properties to customize it. Try and keep the number of controls to a minimum—they are processor intensive.

 

Attaching a control—the details

The syntax for jam.AttachControl method is as follows:

 

jam.AttachControl(ProcName As String, ControlType As Integer, ControlName As String) as Boolean

ControlType specifies what kind of control to create. ProcName is the name of the subroutine that will be called when events happen in the created control. ControlName is a unique name for the control object. You use this name to access the object in subsequent code.

The following is a table of the allowable control types and the form of procedure to handle them.

ControlType

Creates a…

which calls a handler of the following form (choose your own name for the  handler)…

Explanation of the handler

0

Slider

Sub MySlider (Value,Scrolling)

Value is the value of the slider, scrolling is true if the user has the mouse down, false if the user has finished moving the slider. Called whenever the user moves or finishes moving a slider.

1

Button

Sub MyButton

No parameter. Called whenever the user clicks the button.

2

CheckBox

Sub MyCheckBox (Checked)

Checked is true if the check box is checked, otherwise false. Called whenever the user clicks the checkbox

3

DropDown

Sub MyDropDown (ListIndex, ItemText)

ListIndex is the index of the selected item. The first item is 0. ItemText is the text of the selected item. Called whenever the user clicks in the dropdown.

Examples of creating and modifying controls

Once a control has been created, you can modify it using its properties and methods. The comments in the following examples document AttachControl calls together with the properties that you would typically use, and examples of handlers and the usage of initializers.

(For those who want to do further customization, the buttons, checkboxes and dropdowns are the standard CommandButton, CheckBox and ComboBox controls used in Microsoft's Visual Basic and Visual Basic for Applications forms. You can refer to documentation of these controls for further methods and properties. The slider is General Majic's LGauge, and you can get documentation by downloading their demo version. You shouldn't fiddle with the position or size of controls—jambient handles this. And there really aren't further useful customizations to make.)

Example of Button

Sub ScrambleWires() 'handler for Scramble

    Dim Lp

    for Lp =0 to 16

        jam.Wire(Lp)=int(4*rnd+1) ' assign a random wire to each LoopTrack

    next

End sub

 

Sub InitScramble

    'ask jambient to make a button control called Scramble, which will call the ScrambleWires handler

    if jam.AttachControl("ScrambleWires",1, "Scramble") then

       'if the Scramble button is successfully attached, do something with Scramble.

       with Scramble

            .tooltiptext ="Click to generate a random wire assignment" 'set its tooltip

            .caption = "Scramble Wires" 'set the caption of the button

       end with

       Scramble.caption = "Scramble Wires" 'this is equivalent to the .caption above,

                                           'but without using the with construct      

    end if

end sub

 

Example of CheckBox

Sub ToggleClock (Checked) 'handler for the clockcheck object

    'respond to check box toggling by toggling clock

    jam.Clock = checked

end sub

 

Sub InitClock

    'ask jambient to make a checkbox control called ClockCheck, which will call the ToggleClock handler

    if jam.AttachControl("ToggleClock", 2 , "ClockCheck") then

       'if successfully created, let's do something with the ClockCheck object

       with ClockCheck

            .caption = "Clock On" 'set its caption

            .tooltiptext ="Toggle clock on and off to trigger events in time" 'set its tooltip

 

       end with

    end if

end sub

 

Example of Slider

Sub ClockInterval (Value, Scrolling)  'handles events in the ClockSlider Control

    jam.Readout "Clock interval: " & Value & "ms"  'display the value in the scripting window status bar

    if not Scrolling then

       jam.ClockInterval = Value ' if finished moving the slider, change the clock interval to the value

    end if

end sub

 

Sub InitClock

    'ask jambient to make a slider control called ClockSlider, which will call the ClockInterval handler

    if jam.AttachControl("ClockInterval",0, "ClockSlider") then

       'if successfully created, let's do something with the ClockSlider object

       with ClockSlider

            .tooltiptext ="Set clock interval"  'set its ToolTip

            'set its caption--have to use this routine to get the right caption position

      jam.SetSliderCaption ClockSlider, "Clk Interval" 

            .ScaleMin =20        'set the minimum and maximum value of the scale. Use decimals if you want

            .ScaleMax = 200    'scalemin and max determine the range of values passed to the handler

            .PointerValue 20    'set the value of the pointer

            jam.ClockInterval = .PointerValue 'initialize the clock value

       end with

    end if

end sub

 

Example of DropDown

Sub PositionType(ListIndex, ItemText) 'handle events in the PosDropDown control

     'set a numeric variable to indicate what sort of positioning is to be done

     PositionBehaviour = ListIndex

     'display the text of this option in the script window status bar    

     jam.ReadOut LIstIndex & "  " & ItemText

End Sub

 

Sub InitScrolling

    'ask jambient to make a slider control called PosDropDown, which will call the PositionType handler

    if jam.AttachControl("PositionType",3 , "PosDropDown") then

       'if successfully created, let's do something with the PosDropDown object

       with PosDropDown

         .Clear   'clear the list of items in the drop down

         .AddItem "XY Mirror" 'add a series of items

         .AddItem "X Mirror"

         .AddItem "Y Mirror"

         .AddItem "Flying Wedge"

         .AddItem "Red band follow listener"

         .AddItem "None"

         .ToolTipText = "Choose behaviour for scrolling routines." 'set its tooltip

         .ListIndex = 5 'chose the last item in the list as a default

       end with

    end if

End Sub

2) Reference: Methods and properties of the jam object

Crash course in objects and object syntax.

jambient defines one object, named jam, that defines methods and properties that let you access the jambient engine. In code that uses a method or property, you refer to the jam object, followed by a period, and then the name of the method or property.

A method is a subroutine or function belonging to the object.

A subroutine method is called using the syntax

jam.Method parm1, parmN…

A fuction method is called using the syntax

result = jam.Method (parm1, parmN…)

Think of a property as a special variable belonging to the object. You can get or set the value of this variable (some properties are read or write only, however). For example, the ClockInterval property is used to get and set the value of the clock interval. It is manipulated using the following syntax:

CurrentClockInterval = jam.ClockInterval

jam.ClockInterval = 20

Some properties are indexed, especially the properties for the multiple LoopTracks. The index is  1-16 for LoopTracks A-P. 17 refers to the Gang, and to the Listener for position properties. In the documentation the index for a LoopTrack is always passed in a parameter called LoopIndex. Example

jam.Volume(17) = 0 'set the volume of the gang to 0,

                   'which will set the volume of all gang controlled looptracks to 0

Pt = jam.Pitch(1)    'store the pitch of LoopTrack A in variable Pt

For all LoopTrack properties, if you set the property in the gang, it is transmitted to all gang controlled LoopTracks. Similarly with setting a property in the master LoopTrack of a band block.

If you are making a lot of calls to the jam object in a row, you can use the with structure:

with jam

      .Pitch(1)=150

      .Vol(1) = 300

      'etc.

end with

Constants

The example scripts contain constants that give meaningful names to the indices of loops and to the various numbers that you need to pass to the jambient object (such as the ones that determine different play states).  You should copy these constants to use in your own scripts.

Reference

Properties

jam.PlayState (LoopIndex)

Use this property to get or set the play state of a looptrack. Setting the play state stops or starts the looptrack. The values for the play state are 0 to stop, 1 to play, 2 to pause, 3 to unpause.

jam.PlayMode (LoopIndex)

Use this property to get or set the play mode of a looptrack. The values for the play mode are 1 for One Shot, 2 for Looping, 3 for Stepping, 4 for Drum.

jam.Pos(LoopIndex)

Use this property to get or set the play position within a sample's looptrack. Doesn't work on the gang. The value of this property is a double precision number that specifies position as a percentage within the sample: 0 is start of the sample, 50 mid way, and 100 the end.

jam.Sample(LoopIndex)

Use this property to get or set the sample of a looptrack. The value of this property is a string that specifies the full file name of the sample.

jam.Vol(LoopIndex)

Use this property to get or set the volume of a looptrack.  The value of this property is an integer from 0 to 500.

jam.Pitch(LoopIndex)

Use this property to get or set the pitch of a looptrack.  The value of this property is a double precision number 1 to 400, specifying the pitch of the looptrack as a percentage of the original pitch of the sample.

jam.Pan(LoopIndex)

Use this property to get or set the pan of a looptrack.  The value of this property is an integer from –500 to 500, where –500 is full left, 0 is centre, 500 is full right.

jam.Fade(LoopIndex)

Use this property to set a looptrack fade (Write only).  The value of this property is 0 to stop the fade, 1 to fade up, 2 to switch fade, 3 to fade down.

jam.PatternSteps(LoopIndex)

Use this property to get or set the number of steps in a pattern.  The value of this property is an integer from 1 to 32.

jam.Pattern(LoopIndex, PatternType, Step)

Use this property to get or set the value for a step in a pattern, or set its randomizer. PatternType determines which pattern you are accessing, 1 for volume, 2 for pitch, 3 for pan. Step determines which step in the pattern you are accessing, 1-32, and 33 for the randomizer.

jam.Wire(LoopIndex)

Use this property to get or set the wire of a looptrack.  The value of this property is an integer from 1 to 4 for the four different wires, and 4 to 8 for the corresponding disabled wires.

jam.Distance(LoopIndex1, LoopIndex2)

Use this property to get or set the distance between the positions of two looptracks.  The value of this property is a double precision number that specifies the distance between the two loops in the units of the 3d map, nominally meters. When you set this property, the looptrack indexed by loopindex1 stays in place, and the other looptrack is moved along the line between the two; if the property is set to a positive value, it is moved to the right of the anchor looptrack, otherwise to the left.

jam.Clock

Use this property to get or set the script clock's state.  The value of this property is a boolean, true if the script timer is on, false if not. Set it to true to enable the script timer and use the OnClock event.

jam.ClockInterval

Use this property to get or set the script clock's interval.  The value of this property is an integer 10 to 500000 specifying the clock interval in milliseconds.

Methods

jam.SetXY LoopIndex, X, Y

Use this method to position a looptrack in the 3d Map.  X and Y are double precision values, with negative values to the left and above the centre of the map. The default size of the map is 1.5x1.5, but you can pass any value to X and Y—you just won't be able to see it if it is off the map, unless you change the map size. Calling with a LoopIndex of 17 positions the listener.

jam.GetXY LoopIndex, X, Y

Use this method get the position a looptrack in the 3d Map.  The position is stored in the variables X and Y that you pass to the subroutine. Call with a LoopIndex of 17 to get the position of the listener.

jam.PosPolar LoopIndex, Degree, R, [Xorg, Yorg]

Use this method set the position a looptrack in the 3d Map using polar coordinates, where degree specifies the direction from the origin, and r the distance from the centre. Using the optional parameters XOrg and YOrg to specify a different origin. Calling with a LoopIndex of 17 positions the listener. Useful for moving positions in circles.

jam.SelectRange LoopIndex1, LoopIndex2

Use this method to select all looptracks in the indexed range.

jam.UnSelectRange LoopIndex1, LoopIndex2

Use this method to unselect all looptracks in the indexed range.

jam.IsSelected(LoopIndex)

This function returns true if the indexed LoopTrack is selected.

jam.IsGanged(LoopIndex)

This function returns true if the indexed LoopTrack is under the control of the gang. Use this as a test condition in a for..next statement to apply a set of operations to all ganged loops.

jam.BandOf(LoopIndex)

This function returns the band number of the indexed LoopTrack, 1 for the first band, 6 for the last.

jam.BandFirst(BandIndex)

This function returns the loopindex of the first member of a band. Bands are identified by number, from 1 to 6.

jam.BandLast(BandIndex)

This function returns the loopindex of the last member of a band. Bands are identified by number, from 1 to 6.

jam.IsFirstInBand(BandIndex)

This function returns true if the looptracked indexed by loopindex is the first in its band.

jam.PadXY X, Y

Use this method to set the position of the mix blender. X and Y are in a coordinate system from –1,-1 (top left) to 1,1 (bottom right)

jam.PadPolar Degree, R, [Xorg, Yorg]

Use this method set the position of the mix blender, where degree specifies the direction from the origin, and r the distance from the centre (max 1). Use the optional parameters XOrg and YOrg to specify a different origin. Useful for moving the blender in circles.

jam.InitSessionTime

Use this method to reset the session time to 0. Useful for write OnClock events that do things at particular times—you can start the script clock and zero the session time with one procedure triggered by a button, and start your timing from there.

jam.JamOpen FileName

Use this method to open the .jam file specified by FileName, using the elements to open settings specified in the save/open dialogue. Returns true if succesful.

jam.JamSave FileName

Use this method to save the current jam to a .jam file specified by FileName, using the elements to save settings specified in the save/open dialogue. Returns true if succesful.

jam.ReadOut S

Use this method to display string S in the status bar of the scripting window.

jam.AttachControl(ProcName, ControlType, ControlName)

Use this method to create new controls in the scripting window and attach them to handlers in your script. See section 1.C for full details. Procname is the name of your handler, which must have parameters appropriate to the type of control created; ControlType is 0 for Sliders, 1 for Buttons, 2 for CheckBoxes and 3 for DropDowns. ControlName is a unique name for the control object to be created; the object is of type LGauge  (from General Majic), CommandButton, CheckBox or ComboBox (from Microsoft) depending on the ControlType. AttachControl returns true if the control was successfully created. The control can be referenced anywhere in your script as ControlName, once it has been created.

jam.SetSliderCaption LGauge, Caption

Use this method to set the caption of a slider. LGuage is the slider object, Caption the caption. For example, if you used AttachControl to create a slider call "MySlider" you now have an object MySlider, referenced without quotes. jam.SetSliderCaption MySlider, "Ticks" gives it the caption "Ticks".

jam.EnableEvent ProcName, Enabled

Use this method to enable or disable event handling for one of the preset event handlers listed in 1.A. ProcName is the name of the preset event. Set enable to true if you want it enabled, to false if not. Equivalent to using the event menu in the script window to check or uncheck events. This is a more efficient way of turning off certain events—instead of setting parameters that your script checks in order to decide whether to process events, disabling the event means that jambient doesn't call the script for it.