Name: | Medialon Script |
Version: | 6.7.2 |
Available for: | Manager V7 and Manager V6 (Lite & Pro), Showmaster (ST, Pro, LE, XS) |
Limitation In: | |
Device Brand: | |
Positrack Compatible: | No |
Resources type: | TCP/IP Network, UDP/IP Network, Serial, DMX, I/O |
The Medialon Script MxM allows executing JavaScript code inside a Medialon Manager project. The JavaScript code can access, modify and control devices, tasks, variables and UserScreen objects of the running project.
This MXM is also able to support different types of communication like:
Some resources available in the project can be used directly by a Script device. Below the list of supported resources:
This Javascript code can be provided as a Script custom Driver in order to be used easily by everyone.
Otherwise, Medialon programmers who wish to go beyond the programming features provided by the integrated Medialon environnement can create their own Script Driver including a set of commands and device variables.
JavaScript is a very popular and widely used scripting language and it is relatively easy to learn. There are many online resources, tutorials and example source codes available for both beginners and advanced programmers.
The range of applications of this MxM is endless and is up to the imagination and skills of the programmer. The Medialon Script MxM particulary shines where there is a large quantity of objects to manage as it can avoid writing and maintening hundreds of tasks. It is also good at performing complex algorithms quickly in one cue as opposed to executing a lot of StepBased tasks cues. Here are some application examples:
By default, the JavaScript code of a device is edited in the Device Setup dialog box and is saved in the Medialon project. But an interesting feature of the MxM is that it allows loading a new script at run time, that is, while the Medialon project is in Run or Debug mode. This opens the possibility to change the whole behavior or logic of a project by simply updating the script file without modifying the project itself. Even better, the JavaScript code can be modified directly in the Device Control Panel at run-time which is handy for debugging the script.
The MxM also allows creating Device System Variables. This can greatly simplify the implementation and the maintenance of projects using such devices as the devices are “self-contained” and embed both variables and code.
In addition to that, the programmer can write its own set of commands, adjust their parameters types and their definition and even be able to add wizards.
The implementation details of the JavaScript code is fully detailed in the Script Implementation Guidelines section.
To help programmers, a Debugger can be enabled to debug the script during the running mode.
Execute vcredist_x86.exe, which is the Microsoft Visual C++ 2008 Redistributable Package (x86), in order to insall the runtime components of Visual C++ Libraries required by the MXM Medialon Script.
A Script Driver is just a .js file which contains javascript code formatted with the Medialon Script implementation.
During the creation of a Scrip Device, the Setup dialog box allows the user to load a Script file. By clicking on the Load button another dialog box is displayed and provides an easy way to select a Script Driver from the Script library.
This Script library is located to the sub-folder \Medialon\Scripts\ of the Common Documents directory of the Windows, typically in C:\Documents and Settings\All Users\Documents\Medialon\Scripts.
It is possible to Import or Export script files to/from this folder.
Once the Script has been selected, its name and others information such as its version, its description appear in the Setup dialog box. And if the script itself has a custom Setup, this one will be display in order to allow the user to enter Setup information like an IP address, select a resource…
Writing and understanding JavaScript code requires a minimal knowledge of the Javacript syntax. There are numerous JavaScript resources available on the Internet. The following sections are not intended to teach JavaScript but rather to help a moderately skilled JavaScript programmer setting up a script for use in the context of the Medialon Script MxM.
Basically, the script code in a Medialon Script device can:
To access to the Script area, the checkbox named ‘Programming Mode’ in the Setup should be checked.
This section starts by exploring few script examples then goes into a more formal description of Medialon Script codes. Those who prefer formal descriptions can skip the following section an go straight to Script Structure.
The following (over simplified) example is a script which sets the device “Greeter” variable to “Hello World!”. Not very useful but is shows the basics of the Medialon Script scripting.
({
Device: { Message:"" },
SayHello: function() { this.Device.Message="Hello World!"; }
})
The ({
specifies the beginning of the script.
The var Device { Message:"" };
line declares a device variable named Message
. This variable can be accessed by a Medialon cue with Greeter.Message
.
The SayHello: function() { this.Device.Message="Hello World!"; };
line declares a function which puts “Hello World” in the device Message
variable. Note the usage of the this
keyword which tells the JavaScript interpreter that we’re talking about the object defined in the script.
The )}
specifies the end of the script.
A Medialon project can use the above script as in the following task:
Line Device Command
---- ------ -------
1 Greeter Execute Function("SayHello")
2 Manager Expression("TextDisplay.Text=Greeter.Message")
The next example is a little bit more elaborate: the purpose of this script is to compute the average value of the last 10 samples of a rapidly changing slider in order to “smooth” the value sent to a physical device (in our case: another slider). Note that lines beginning with “//” are JavaScript comments.
// script begins
({
// Here are the device variables which can be automatically extracted
// in the Device Setup Dialog
Device: {
Raw:0,
Smooth:0
},
// Below is a local JavaScript "samples" array
samples: [],
// The "Init" script function clears the "samples" array
Init: function() {
this.samples=[];
},
// The main "Process" script function queues the new device input "Raw" value
// in the samples array (making sure there are no more than 10 samples),
// computes the average value of the samples and updates the
// "Smooth" device variable.
Process: function() {
if(this.samples.length>=10){
this.samples.shift();
}
this.samples.push(this.Device.Raw);
var avg=0;
var i=0;
while(i<this.samples.length){
avg=avg+this.samples[i];
i=i+1;
}
avg=avg/this.samples.length;
this.Device.Smooth=avg;
},
// script ends
})
Let’s say the Medialon Script device is called “Smoothie”. A Medialon project would first initialise the script in a startup task:
Line Device Command
---- ------ -------
1 Smoothie Execute Function("Init")
A continuously looping task would then call the “Process” script function regularly
Line Device Command
---- ------ -------
1 Manager Expresssion(Smoothie.Raw=SliderRaw.Status)
2 Smoothie Execute Function("Process")
3 Manager Expression(SliderSmooth.Status=Smoothie.Smooth)
4 Manager Wait(00:00:00/25)
5 Manager GoToLine(,1)
The previous example if nice but it could also be implemented with a regular Medialon programming using enums and expressions. So what is the advantage of using a script? It quickly shows when there are multiple values to process. Let’s say there are 20 sliders to “smooth”…
The following script takes care of updating 20 sliders. Note that this example uses the powerful “QMedialon” object which is described in the QMedialon Object section.
// script begins
({
// Below is a local JavaScript "samples" array
// Each entry of this array is an array of samples
sliderCount: 10,
sampleCount: 25,
sampleArrays: [],
// The "Init" script function clears the "samples" array
Init: function() {
for(var i=0;i<this.sliderCount;i++){
this.sampleArrays[i] = [];
}
},
// The "Process" function processes all of the sliders
Process: function() {
// for each slider
for(var slider=0;slider<this.sliderCount;slider++){
// Make sure that this slider sample queue is not full
var samples=this.sampleArrays[slider];
if(samples.length>=this.sampleCount){
samples.shift();
}
// Push the "raw" value for this slider
var value=QMedialon.GetValueAsInteger("SliderRaw"+(slider+1)+".Status");
samples.push(value);
// Compute the average value for this slider
var avg=0;
for( var i=0;i<samples.length;i++){
avg=avg+samples[i];
}
avg=avg/samples.length;
// Update the "smooth" slider
QMedialon.SetValue("SliderSmooth"+(slider+1)+".Status", avg);
}
},
// script ends
})
Here’s the “Startup” task:
Line Device Command
---- ------ -------
1 Smoothie Execute Function("Init")
And here’s the “Looping” task:
Line Device Command
---- ------ -------
1 Smoothie Execute Function("Process")
2 Manager Wait(00:00:00/05)
3 Manager GoToLine(,1)
Advantages of using this script compared to writing pure Medialon programming tasks and cues:
A function of a script is called when the Medialon Script device “Execute Function” command is executed (either from a task, the Command Lister):
If an “Execute Function” command is triggered while the script engine is busy (device variable “Status” is “busy”) executing a script function. The “Execute Function” request is queued and will be executed when the current script function is done.
The script code should follow the JavaScript syntax. All of the code must be wrapped in a JavaScript object.
The script structure is:
Example:
// 1. Script Begins
({
Info:{
// 2. Information
Title:"Script Title",
Author:"Who create the script",
Version:"1.0.0",
Description:"This is a script example which shows the structure of a JavaScript " +
"implemented in this MxM Script Device",
},
// 3. Device Variables
Device: {
Value1:0,
Value2:""
},
// 4. Local Script Variables
localCount: 0,
// 5. Script Functions
_mStart: function() {
//initializing
this.localCount=4;
},
_mStop: function() {
//de-initializing
},
Test: function() {
this.Device.Value2 = this.Device.Value1 + this.localCount;
}
// 6. Script Ends
})
Note that all script Device variables and local variables must be referenced by the this
keyword as shown in the “Test” function.
The Info section is the place to describe metadata concerning the script like its Title, the Author, its Version and a Description. These fields are optional. Even if they are not set, their Setup area is still displayed.
Info:{
Title:"Script Title",
Author:"Who create the script",
Version:"1.0.0",
Description:"This is a script example which shows the structure of a JavaScript " +
"implemented in this MxM Script Device",
}
A special “Device” object must be declared in order to define Device variables. This object can be ommitted if there’s no device variable. This object is parsed when the Device Setup Dialog is validated. The Medialon Script MxM variable extractor automatically populates the Medialon Script device variables according to the JavaScript variables declared in this section. The name of a Device Variable should be unique, otherwise the last defined Variable will be the one considered.
Device: {
aDeviceVariable: ""
},
The Medialon Script MxM variable extractor uses the variable declaration as a hint for the type of the variable. For example, if the variable is initialized with a string, the variable will be a String variable once extracted from the script.
It is also possible to define a variable as a Real or as a Integer in this section.
Device: {
myIntegerVariable: 182,
myStringVariable: "hello world",
myRealVariable: 10.05
}
Once declared, Device Variables can be accessed by the JavaScript code using the this.Device
prefix.
// declaration:
Device: {
myDeviceVariable: ""
},
// usage:
Test: function() { this.Device.aDeviceVariable="Hello!"; }
A Device variable can be casted in another type of variable as an Enum, a Time or a Date just by adding an ‘Info’ object containing a ‘Variables’ object and few information. The extractor will automatically try to associate the sub-objects from this ‘Variables’ object to the Device variables defined into the ‘Device’ object.
Info: {
Variables: {
myEnumVariable: {
Type:"Enum",
Items:[ "Item 1", "Item 2", "Item 3", "Item 4" ]
},
myTimeVariable: {
Type:"Time"
},
myDateVariable: {
Type:"Date"
}
}
},
Device: {
myEnumVariable:"",
myTimeVariable:"",
myDateVariable:""
}
Depending of the Type, specific properties can be added to Device Variables via the ‘Variables’ object.
String:
- MaxLength: [integer] Max length of the string. By default this value is set to –1 which means that there is no limit.
Integer:
- MinValue: [integer] Min value
- MaxValue: [integer] Max value
Real:
- MinValue: [integer / real] Min value
- MaxValue: [integer / real] Max value
- Precision: [integer] The number of digit after decimal point
Time:
- TimeCodeType: [integer] Timecode type. Without this property, the timecode type is by default set to 4 (Time base is 1/100s).
Enum:
- Items: [array] list of items
Info: {
Variables: {
myStringVariable: {
MaxLength:10
},
myIntegerVariable: {
MinValue:0,
MaxValue:100
},
myRealVariable: {
MinValue:-1.5,
MaxValue:1.5,
Precision:2
},
myEnumVariable: {
Type:"Enum",
Items:[ "Item 1", "Item 2", "Item 3", "Item 4" ]
},
myTimeVariable: {
Type:"Time",
TimeCodeType:1
}
}
},
Device: {
myStringVariable: "hello world",
myIntegerVariable:50,
myRealVariable:-0.25,
myEnumVariable:"Item 2",
myTimeVariable:100
}
From the Setup dialog box, in the ‘Variables tab’, it is possible to choose if the default value of a Device variable is the one which is defined into the script or another one.
This can be useful when the script is loaded in different Devices.
The default value or the script default value will applied to the Device variable when the project is loaded.
Local variables are simple JavaScript variables which are not accessible from the Medialon project side. Once declared, the local variables can be accessed by the JavaScript code with the this
keyword prefix.
// declaration
aLocalVariable: 2,
// usage
Test function() { this.aLocalVariable=2; }
The Setup Tab is fully customisable with different widgets in order to provide a Setup box easy to use for the end user.
A special “Setup” object must be declared to start to fill the Setup Tab with widgets. It is not mandatory to define this object if the Setup Tab must stay empty. This object is parsed each time that the Setup Tab is displayed.
The “Setup” object contains the declaration of local variables. Depending of their types, these variable will be automatically associated to an adapted widget:
Setup: {
myStringSetupVar: "hello world",
myIntegerSetupVar: 50,
myRealSetupVar: 1.5
}
By default, the association between type of local variable and widget type is:
- String: LineEdit
- Integer: SpinBox
- Real: RealSpinBox
- Enum: ComboBox
- Time: TimeEdit
- Date: DateEdit
Based on the same concept than the “Device” object, it is possible to cast a Setup local variable in another type of variable as an Enum, a Time or a Date just by adding an ‘Info’ object containing a ‘Setup’ object and few information.
Info:{
Setup:{
myDateSetupVar:{
Type:"Date",
//Widget:"DateEdit", //already set as default for a Date
Name:"My Date"
},
myTimeSetupVar:{
Type:"Time",
//Widget:"TimeEdit", //already set as default for a Time
TimeCodeType:2,
Name:"My Time"
},
myComboBox:{
Type:"Enum",
Items:[ "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8" ],
//Widget:"ComboBox", //already set as default for an Enum
Name:"My ComboBox"
},
myStringSetupVar:{
//Widget:"LineEdit", //already set as default for a String
MaxLength:10,
Width:100,
Name:"My LineEdit"
},
myIntegerSetupVar:{
//Widget:"SpinBox", //already set as default for an Integer
MinValue:-100,
MaxValue:100,
Prefix:"$",
Name:"My SpinBox"
},
myRealSetupVar:{
//Widget:"RealSpinBox", //already set as default for a Real
MinValue:-1.5,
MaxValue:1.5,
Precision:1,
Suffix:"°C",
Name:"My Real SpinBox"
},
myCheckBox:{
Widget:"CheckBox",
Name:"My CheckBox"
},
myLabel:{
Widget:"Label"
},
myDivider:{
Widget:"Divider"
}
}
},
Setup:{
myLabel:"This is a Label",
myStringSetupVar: "hello world",
myIntegerSetupVar: 50,
myRealSetupVar: 1.5,
myComboBox:1,
myCheckBox:1,
myDivider:0,
myDateSetupVar:"06/08/1984",
myTimeSetupVar:0
}
Available Widget list and their properties:
Label
Divider
When the Widget property is set to Serial, DMXIn, DMXOut, DigitalIn, DigitalOut, AnalogIn, AnalogOut, the appropriated Resource selector will be displayed in the Setup tab.
Function declarations follow the regular JavaScript syntax. Each function is listed in the Device function list and a can be called via a device “Execute Function” cue. The name of a script function should be unique, otherwise the last defined function will be the one considered.
mySuperCoolFunction: function( name ) {
return "Hi " + name + "!";
},
If the function name begins by a ‘_’ character, the script function is not added to the function list exposed by the device for the “Execute Function” command. And thus this makes it available for internal script usage. Callback functions use generally this formatting.
Example of a private function:
_myPrivateFunction: function( a, b ) {
return a + b;
}
Once declared, functions can be called internally by the JavaScript code using the this
keyword.
// calling a private function
var result = this._myPrivateFunction(1,2);
There are two defined functions which will be executed when the project is started/stopped, when the device activity is enabled/disabled, or when a script is loaded or unloaded:
_mStart( Loading ) {//Function's Instructions}
_mStop( Loading ) {//Function's Instructions}
These functions are privates, it means that they are not exposed in the available list of function in Manager.
Loading is a Boolean parameter set by the Script Device which provides additional informations:
The parameter Loading will be true if the function is called by a Load From File or Load From Text command.
The parameter Loading will be false if the function is called by a change of the project running status (Stop, Debug, User, Run), or when the Device is enabled/disabled.
Each javascript functions defined in the script (except the private ones which begin by a _ character) will generate a dynamic command. The dynamic commands are just commands provided by the MXM, they depend of the script itself. So two Script Devices can have a different set of commands.
It is also possible to customise the dynamic commands by completing the Commands section which is placed in the Info node.
Info:{
Commands: {
MyJavascriptFunction: {
Name: "My Command",
GroupName: "Test",
GroupOrder: "0",
GroupCmdOrder: "0"
Params: {
integerParam: {
Name: "my integer parameter",
Type: "Integer",
MaxValue:1000,
MinValue:0
},
realParam: {
Name: "my real parameter",
Type: "Real",
Precision:3,
MinValue:-100.0,
MaxValue:100.0
}
}
}
}
},
MyJavascriptFunction : function( integerParam, realParam ){
// ...
},
Below the list of optional properties which can be defined to customise a Command:
Group management rules:
Example of a typical command grouping and ordering:
({
Info:{
Commands: {
StopCommand: {
Name: "Stop",
GroupName: "Transport",
GroupOrder: "0",
GroupCmdOrder: "0"
},
PlayCommand: {
Name: "Play",
GroupName: "Transport",
GroupOrder: "0",
GroupCmdOrder: "1"
},
MuteCommand: {
Name: "Mute",
GroupName: "Audio",
GroupOrder: "1",
GroupCmdOrder: "0"
},
PowerCommand: {
Name: "Power",
GroupName: "",
GroupOrder:"2",
GroupCmdOrder: "3"
},
}
},
StopCommand : function(){},
PlayCommand : function(){},
MuteCommand : function(){},
PowerCommand : function(){}
})
In addition to that, each parameter of the command can also be customised in order to provide the most adapted commands to the end user. This customisation is optional. Below the list of optional properties which can be defined to customise a command parameter:
Name: [string] The name that you want to display for this parameter.
MinValue: [integer / real] Min value. This property is used only in the case of the Type property is set to ‘Integer’ or ‘Real’.
MaxValue: [integer / real] Max value. This property is used only in the case of the Type property is set to ‘Integer’ or ‘Real’.
Precision: [integer] The number of digit after decimal point. This property is used only in the case of the Type property is set to ‘Real’.
MaxLength: [integer] Max length of the string. This property is not used if the Type property is set to something else than ‘String’. By default this value is set to –1 which means that there is no limit.
TimeCodeType: [integer] Timecode type. This property is used only in the case of the Type property is set to ‘Time’. Without this property, the timecode type is by default set to 4 (Time base is 1/100s).
Wizards: In some circumstance, command parameter values are not very easy to select, mostly due to the complexity of the semantic of that value. A wizard is a feature which helps selecting such value, displaying a selection dialog box.
This wizard is represented by a wand in the manager:
In order to add a Wizard to a parameter, just add Wizard:“NameOfTheWizard” as parameter.
For example:
Info: {
Commands: {
myCommand: {
Params: {
myVariable: {
Wizard: "UserScreenNameSelector"
}
}
}
}
},
myCommand: function( myVariable ) {
}
There is several types of wizards:
UserScreenNameSelector: This wizard is used to display a selector for available UserScreen’s names.
ListNameSelector: This wizard is used to display a selector for available UserScreen’s List object’s names.
ContainerNameSelector: This wizard is used to display a selector for available UserScreen’s Container object’s names.
StepTaskNameSelector: This wizard is used to display a selector for available Step based task’s names.
TimeTaskNameSelector: This wizard is used to display a selector for available Time based task’s names.
AllTaskNameSelector: This wizard is used to display a selector for available task’s names, weither they’re Step or Time based.
TaskLabelNameSelector: This wizard is used to display a selector for available Label’s names of Step based task’s.
DeviceNameSelector: This wizard is used to display a selector for available Device’s names.
ObjectNameWithTextSelector: This wizard is used to display a selector for available UserScreen’s object’s names which have a Text property.
TimeClockSelector: This wizard is used to display a selector for a time value. The selector looks like the following:
For example:
stringVar5: {
Name:"UserScreen Name",
Wizard: "ScreenCoordinatesSelector"
},
stringVar6: {
Name:"Xpos",
Wizard: "ScreenCoordinatesSelector"
},
stringVar7: {
Name:"Ypos",
Wizard: "ScreenCoordinatesSelector"
},
The QMedialon object allows controlling many of the current Medialon project objects like Tasks, Devices, Variables and UseScreen objects. The “QMedialon” object is a global JavaScript object automatically created by the Medialon Script MxM and is made available for use by the scripting code.
For example, the following code starts the task named “NightMode”:
QMedialon.StartTask("NightMode");
This other example sends a “Power Off” command to a projector device named “Projector1”:
QMedialon.Perform("Projector1", "Power", "Default", "Value=Off");
The next example turns 80 projectors off (from “Projector1” to “Projector80”):
for( var i = 1; i <=80; i++ ) {
QMedialon.Perform("Projector"+i, "Power", "Default", "Value=Off");
}
Most of the QMedialon functions require to be registered against a Medialon “Shared Group” in the current project. The only exceptions are the ‘Variable Access’ functions (SetValue, SetValueAsInteger, GetValueAsString, GetValueAsInteger and GetValueAsReal) of QMedialon which don’t require shared group registration. All others functions use a shared group and the RegisterGroup() function must be called at least once before invoking any of these functions. Note that in the Setup, one option allows to automatically register all User Groups.
A typical “shared group” scenario is:
The following sections list all of the functions exposed by the QMedialon object, grouped by categories.
Set the value of a variable defined in the Medialon project.
SetValue( variableName, value )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Set the Status of the DigitalSlider_1 graphic object to 50
QMedialon.SetValue("DigitalSlider_1.Status",50);
Set the value of a variable defined in the Medialon project as an Integer.
SetValueAsInteger( variableName, value )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Set the Status of the MyEnum which is defined as an Enum variable to 4
QMedialon.SetValueAsInteger("MyEnum",4);
Get the value, as a string, of a variable defined in the Medialon project.
GetValueAsString( variableName )
Return: Return the variable value as a string if the operation succeeded otherwise an empty string "".
Example:
// Get the text of the TextEdit_1 object
var text = QMedialon.GetValueAsString("TextEdit_1.Text");
Get the value, as an integer, of a variable defined in the Medialon project.
GetValueAsInteger( variableName )
Return: Return the variable value as an integer if the operation succeed otherwise 0.
Example:
// Get the status (position) of the Slider_1 object as an integer number
var sliderPosition = QMedialon.GetValueAsInteger("Slider_1.Status");
Get the value, as a real, of a variable defined in the Medialon project.
GetValueAsReal( variableName )
Return: Return the variable value as a real if the operation succeed otherwise 0.0.
Example:
// Get the status (position) of the Slider_1 object as a real number
var sliderPosition = QMedialon.GetValueAsReal("Slider_1.Status");
Be notified when a variable changes. All the variables which are in a shared group already registered by the device is concerned. Important note: this function is available only with Overture and Manager version >= 6.7.0.
OnVariableChange( callback )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
_callback: function( variableName, variableValue ){
//..
},
Init: function() {
QMedialon.RegisterGroup( "SharedGroup", true );
QMedialon.OnVariableChange( this._callback );
}
An Enum device variable has 2 functions which allow to set its list of items while the project is running.
The first one allows you to clear all the items of an Enum device variable:
this.Device.EnumClear( "NameOfTheEnumVariable" );
The second provides a way to Add an Item in the Enum device variable:
this.Device.EnumAdd( "NameofTheEnumVariable", newItemValue );
Enum, Date and Time are complexes variables composed of several informations. The functions below can help to interact with them.
Get the index, as an integer, of a item in a list.
EnumStringToIndex( itemList, itemString )
Return: Return the index of the item in the list. This function returns –1 if the item is not found.
Example:
// Get the index in the list
var itemIndex = QMedialon.EnumStringToIndex( this.Info.Variables.enumVar.Items, "Item4" );
Note: “enumVar” is an Enum device variable, and Items is an array of string providing the Enum list.
Extract the day as an integer from a date.
DateStringToDay( date )
Return: Return the day of this date as an integer.
Example:
// Get day (25)
var day = QMedialon.DateStringToDay("12/25/2014");
Note: the date format which been set in windows should be respected.
Extract the month as an integer from a date.
DateStringToMonth( date )
Return: Return the month of this date as an integer.
Extract the year as an integer from a date.
DateStringToYear( date )
Return: Return the year of this date as an integer.
Get the day of week as an integer from a date.
DateStringToDayOfWeekAsNumber( date );
Return: Return the day of the week of this date as an integer.
Extract the hours as an integer from a time.
TimeStringToHours( time, timeCodeType )
Return: Return the hours of this time as an integer.
Example:
// Get hour (1)
var hour = QMedialon.TimeStringToHours( "01:02:03/04", 4 );
Extract the minutes as an integer from a time.
TimeStringToMinutes( time, timeCodeType )
Return: Return the minutes of this time as an integer.
Extract the seconds as an integer from a time.
TimeStringToSeconds( time, timeCodeType )
Return: Return the seconds of this time as an integer.
Extract the frames as an integer from a time.
TimeStringToFrames( time, timeCodeType )
Return: Return the frames of this time as an integer.
Most of the functions exposed by the QMedialon object require the script to be registered to a “Shared Group”. A “Shared Group” is a User Group in the Medialon project which has its “Shared” property set.
The Medialon objects accessed via QMedialon must be part of this shared group. Otherwise the QMedialon functions return the MERR_OBJECTNOTSHARED (49)
error.
All User Groups can be register automatically via the option in the Setup dialog, in this case QMedialon.RegisterGroup and QMedialon.UnregisterGroup calls will be ignored.
Register to a shared group in order to allow accessing objects which are part of the group from the script.
RegisterGroup( groupName, acceptEvent )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Allow the script to access objects which are part of the "MySharedGroup"
QMedialon.RegisterGroup("MySharedGroup");
Unregister from the currently registered group.
UnregisterGroup()
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Open a UserScreen.
OpenUserScreen( userScreenName, positionType, left, top )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// 0pen the the UserScreen_1 UserScreen at position 10,10
QMedialon.OpenUserScreen( "UserScreen_1", 1, 10, 10 );
Close a UserScreen.
CloseUserScreen( userScreenName )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Close the UserScreen_1 UserScreen
QMedialon.CloseUserScreen( "UserScreen_1" );
Go to a page of a UserScreen.
GotoPage( userScreenName, pageNumber )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Goto page 2 of the UserScreen_1 UserScreen
QMedialon.GotoPage( "UserScreen_1", 2 );
Start a task.
StartTask( taskName )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Start task "Task_1"
QMedialon.StartTask( "Task_1" );
Pause a task.
PauseTask( taskName )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Pause task "Task_1"
QMedialon.PauseTask( "Task_1" );
Stop a task.
StopTask( taskName, mode )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Stop task "Task_1"
QMedialon.StopTask( "Task_1" );
Go to the specified label of a task.
GotoLabel( taskName, label )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Go to the label "Loop" of task "Task_1"
QMedialon.GotoLabel( "Task_1", "Loop" );
Goto the specified line of a task.
GotoLine( taskName, lineNumber )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Go to line 12 of task "Task_1"
QMedialon.GotoLine( "Task_1", 12 );
Goto the specified time of a task.
eMResult GotoTime( taskName, time )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Example:
// Go to the 10 second position of task "Task_1"
QMedialon.GotoLine( "Task_1", 1000 );
Perform an action on a object. This command can be used to execute a
Perform( objectName, action, parameterType, param1, ..., param10 )
Return: an empty string "".
Parameter Type:
If the parameter type is “Default”, the syntax of the parameters is: parameterName=parameterValue
. There must be a parameter for each parameter of the command. In the following example, the “Locate” command of a MIP device requires one parameter of name “TimeCode”:
// Locate the video of the device "MIP_1" to 20 seconds
QMedialon.Perform( "MIP1_1", "Locate", "Default", "TimeCode=00:00:20/00" );
If the parameter type is “XML”, the “param1” parameter of the perfom commands contains a full XML description of the parameters of the action to perform. In the following example, the “Locate” command of a MIP device requires one parameter of name “TimeCode”:
// Locate the video of the device "MIP_1" to 20 seconds
QMedialon.Perform( "MIP1_1", "Locate", "XML",
"<parameters><parameter name='TimeCode' value='00:00:20/00'/></parameters>");
When a parameter of the command is supposed to be a time (like the Timecode parameter in the example above), his value will be interpreted as a String. Here few examples of syntaxes which can be used:
value=‘00:00:20/00’ | -> | 00:00:20/00 |
value=‘20’ | -> | 00:00:20/00 |
value=‘720.5’ | -> | 00:07:20/05 |
The Perform function does not support an action which has output parameters (return variables). In that case, the contents of the output parameters are undefined after the function returns.
Important Note: Using Manager 6.1.0 or less, the ‘Perform’ function doesn’t work when the command includes parameters which have a decoration as parameter range, for example: ‘Volume (–100dB to 0dB)’. Manager 6.2.0 or greater is required for a proper handling of such commands.
Insert Perform action:
It is easy to complete a QMedialon.Perform without error in the Setup dialog by right clicking in the Script edition area and ‘Insert QMedialon.Perform’ or by just pressing Alt+P. This dialog box allows to select a Device, one of its commands and set the parameters. When the script line is validate by clicking on the Ok button, this line is added in the script itself. It is also possible to select a Perform Async in order to generate the script line for a QMedialon.PerformAsync.
Perform asynchroniously an action on a object. This command can be used to execute a
PerformAsync( callback, objectName, action, parameterType, param1, ..., param10 )
Return: MERR_SUCCESS if the operation succeeded, an MERR_XXX code otherwise. See MERR Values.
Important note: this function is available only with Overture and Manager version >= 6.7.0.
PostponeResult allows to postpone the end of the command. The cue won’t be terminated while “SetResult” has not be called.
PostponeResult()
Return: Returns an ID (integer) which identify the postponed object. This ID must be specified when the “SetResult” is called.
Notes: - A good pratice consists to use “SetTimeout” to execute a callback after a timeout to be sure that the “SetResult” function is called. - If “PostponeResult” is called multiple times by the same command, it’ll always returns the same ID.
SetResult function must be called when “PostponeResult” has been used in a command in order to terminate it.
SetResult( Id, result )
Example:
_onResponse:function(response, error) {
// do what ever you want here with the response/error
// release the context
this._setResult();
},
_setResult: function() {
QMedialon.ClearTimeout( this.timeoutId );
this.timeoutId = 0;
QMedialon.SetResult(this.contextId, "timeout");
this.contextId = 0;
},
_postponeResult: function() {
// just in case, a timeout is added to terminate the command
this.timeoutId = QMedialon.SetTimeout( this._setResult, 30000 );
this.contextId = QMedialon.PostponeResult();
},
myBlockingCommand: function() {
this._postponeResult();
// below, it's possible to execute an async function and wait for its results
// let's imagine that the callback of this async function is _onResponse
}
Return a list of manager object in XML format.
GetObjectList( objectName, objectType )
Return: Returns a list of manager objects in XML format as a string otherwise an empty string "".
Get an object info XML structure.
GetObject( objectName, objectType )
Return: Returns a manager object in XML format as a string otherwise an empty string "".
Executes a script function, over and over again, at specified time intervals.
SetInterval( function, interval )
Return: Returns the ID of the Interval. This ID can be used by the QMedialon.ClearInterval function.
Example:
// Recall _refreshTime script function every 100ms
QMedialon.SetInterval(this._refreshTime, 100);
Executes a script function, once, after waiting a specified number of milliseconds.
SetTimeout( function, timeout )
Return: Returns the ID of the Timeout. This ID can be used by the QMedialon.ClearTimeout function.
Stop further executions of the script function specified in the QMedialon.SetInterval() method.
ClearInterval( intervalID )
Stop the execution of the script function specified in the QMedialon.SetTimeout() method.
ClearTimeout( timeoutID )
Log a message in the Manager Traces system. The mxmMedialonScript Log option must be enabled in the ‘Preferences’ menu of Manager (Log Traces sub-menu).
TraceMessage( message, messageType )
0 | NORMAL | Message Type is normal (color is lightgray in console). |
1 | NORMALPLUS | Message Type is information (color is green in console). |
2 | INFO | Message Type is information (color is green in console). |
3 | COMMENT | Message Type is comment (color is blue in console). |
4 | ALARM | Message Type is alarm (color is yellow in console). |
5 | ERROR | Message Type is error (color is red in console). |
6 | FATAL | Message Type is fatal error (color is black on background red in console). |
7 | DEBUG | Message Type is debug (color is fushia red in console). |
In the script code below, a function has been implemented in order to convert a MERR_XXX value to an error text:
// Script Begins
({
// Script Functions
_merr_xxx_toText : function( merr_xxx ) {
var s= "";
switch( merr_xxx ) {
// MERR_SUCCESS
case 0: {s="Object Control operation succeed.";}break;
// MERR_INVALIDARGUMENT
case 1: {s="An invalid argument passed to the ControlObject.";}break;
// MERR_BUFFERTOOSMALL
case 2: {s="An insuffisant buffer size passed to the ControlObject.";}break;
// MERR_MISSINGDATA
case 3: {s="Missing data for the ControlObject.";}break;
// MERR_INVALIDID
case 4: {s="An invalid ID passed to the ControlObject.";}break;
// MERR_OPERATIONNOTSUPPORTED
case 16: {s="The requested operation is not supported by ControlObject.";}break;
// MERR_OPERATIONNOTKNOWN
case 17: {s="The requested operation is not known by ControlObject.";}break;
// MERR_OPERATIONTIMEDOUT
case 18: {s="The requested operation has timed out.";}break;
// MERR_OPERATIONFAILED
case 19: {s="The requested operation has failed.";}break;
// MERR_OPERATIONABORTED
case 20: {s="The requested operation has been aborted.";}break;
// MERR_WRONGSTATE
case 32: {s="The object is in wrong state and cannot perform the requested operation.";}
break;
// MERR_ACCESSDENIED
case 33: {s="Object access is denied.";}break;
// MERR_GRANTEDLIMITEXCEDED
case 34: {s="The requested operation cannot be performed, limit reached.";}break;
// MERR_NOTCONNECTED
case 35: {s="The connection is not extablished.";}break;
// MERR_CONNECTIONFAILED
case 36: {s="The connection attempt has failed.";}break;
// MERR_NOTIDENTIFIED
case 37: {s="The connection is not yet identified (need identification).";}break;
// MERR_NETWORKERROR
case 38: {s="A network error occured.";}break;
// MERR_NOTREGISTERED
case 39: {s="The connection is not yet registered.";}break;
// MERR_ALREADYREGISTERED
case 40: {s="The connection is already registered.";}break;
// MERR_REGISTRATIONFAILED
case 41: {s="The connection registration failed.";}break;
// MERR_OBJECTDOESNOTEXIST
case 48: {s="The requested object doesn't exist.";}break;
// MERR_OBJECTNOTSHARED
case 49: {s="The requested object is not shared.";}break;
// MERR_OBJECTUNKNOWNPROPERTY
case 50: {s="The requested property is not part of this object.";}break;
// MERR_OBJECTCANNOTSETGETPROPERTY
case 51: {s="The requested property cannot be set/get on this object";}break;
// MERR_REDIRECTION
case 52: {s="The connection has been redirected.";}break;
// MERR_NOREDIRECTIONDEFINED
case 53: {s="The connection redirection has not been defined.";}break;
/ MERR_BADPROTOCOLVERSION
case 54: {s="The requested protocol version is not supported.";}break;
default: {s="Unknown error." } break;
}
return s;
}
// Script Ends
})
A TCP Client or UDP object can be created from the QMedialon object to manage a TCP connection.
Create a TCP Client or UDP object. This function belongs to the QMedialon object.
CreateSocket( type )
Return: an empty object is returned if it is not possible to create the appropriate object. Otherwise, a TCP Client or an UDP object is returned.
Example:
// create a TCP Client object
this.myTCPClient = QMedialon.CreateSocket();
The TCP Client object provides the methods below:
Opens the connection for a given socket. If port and host are given, then the socket will be opened as a TCP socket, if host is omitted, localhost will be assumed.
This function is asynchronous. When the ‘connect’ event is emitted the socket is established. If there is a problem connecting, the ‘connect’ event will not be emitted, the ‘error’ event will be emitted with the exception.
The connectListener parameter will be added as an listener for the ‘connect’ event.
connect(port, [host], [connectListener])
Example:
// ask to the TCP Client object to establish a connection with a server
// and to prevent via the _OnSocketConnect callback when the connection will be done
this.myTCPClient.connect(4422, '127.0.0.1', this._OnSocketConnect);
Disables the Nagle algorithm. By default TCP connections use the Nagle algorithm, they buffer data before sending it off. Setting true for noDelay will immediately fire off data each time socket.write() is called. noDelay defaults to true.
setNoDelay([noDelay])
Example:
this.myTCPClient.setNoDelay(false);
Sends data on the socket.
write(data)
Example:
this.myTCPClient.write( "my message" );
Close the socket.
end()
Example:
this.myTCPClient.end();
Get address information concerning the socket.
address()
Returns the bound address, the address family name and port of the socket as reported by the operating system. Returns an object with three properties, e.g. { port: 12346, family: ‘IPv4’, address: ‘127.0.0.1’ }
Associate an event to a callback function.
on( event, callback )
Example:
this.myTCPClient.on('close', this._OnSocketDisconnect );
Example:
this.myTCPClient.on('data', this._OnSocketRead );
UDP uses a simple connectionless transmission model with a minimum of protocol mechanism. It has no handshaking dialogues, and thus exposes any unreliability of the underlying network protocol to the user’s program. There is no guarantee of delivery, ordering, or duplicate protection.
The UDP object provides the methods below:
For UDP sockets, listen for datagrams on a named port and optional address. If address is not specified, it will try to listen on all addresses.
A bound datagram socket keeps the process running to receive datagrams.
bind(port, [address])
Example:
//listening all IP at 44444 port.
this.myUDP.bind(44444);
Set exclusive port at false will give the possibility at other sockets to listen to the socket port too, at the same time.
setExclusivePort( exclusivePort )
For UDP sockets, the destination port and address must be specified. A string may be supplied for the address parameter, and it will be resolved with DNS.
If the address is omitted or is an empty string, ‘0.0.0.0’ is used instead. Depending on the network configuration, those defaults may or may not work; it’s best to be explicit about the destination address.
If the socket has not been previously bound with a call to bind, it gets assigned a random port number and is bound to the “all interfaces” address (‘0.0.0.0’ for udp4 sockets)
The maximum size of an IPv4 datagram depends on the MTU (Maximum Transmission Unit) and on the Payload Length field size.
The Payload Length field is 16 bits wide, which means that a normal payload cannot be larger than 64K octets including internet header and data (65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header); this is generally true for loopback interfaces, but such long datagrams are impractical for most hosts and networks.
The MTU is the largest size a given link layer technology can support for datagrams. For any link, IPv4 mandates a minimum MTU of 68 octets, while the recommended MTU for IPv4 is 576 (typically recommended as the MTU for dial-up type applications), whether they arrive whole or in fragments.
Note that it’s impossible to know in advance the MTU of each link through which a packet might travel, and that generally sending a datagram greater than the (receiver) MTU won’t work (the packet gets silently dropped, without informing the source that the data did not reach its intended recipient).
send(data, offset, length, port, address)
Close the underlying socket and stop listening for data on it.
close()
address()
Returns an object containing the address information for a socket. For UDP sockets, this object will contain address , family and port.
Example:
var adressObject = this.myUDP.address();
var adress = adressObject.address;
var family = adressObject.family;
var port = adressObject.port;
Associate an event to a callback function.
on( event, callback )
Example:
this.myUDP.on('error', this._OnSocketError );
Example:
this.myUDP.on('message', this._OnSocketMessage );
_OnSocketMessage : function(msg, rinfo){
this.Device.lastFrame = msg;
this.Device.lastPort = rinfo.port;
this.Device.lastAddress = rinfo.address;
},
A HTTP Client object can be created from the QMedialon object to be able to send HTTP requests.
Create a HTTP Client . This function belongs to the QMedialon object.
CreateHTTPClient()
Return: A HTTP Client object is returned.
Example:
// create a HTTP Client object
this.myHTTPClient = QMedialon.CreateHTTPClient();
HTTP Client allows sending HTTP/HTTPS requests to a HTTP Server. These requests are GET
, POST
, PUT
and DELETE
.
The selection between HTTP and HTTPS is merely done via the URL value indicated in the ‘URL’ parameter of commands.
It also supports the following authentication methods:
- Basic
- Digest-MD5
The HTTPClient object provides the methods below:
Associate an event to a callback function.
on( event, callback )
Example:
this.myHTTPClient.on('response', this._OnHTTPResponse );
_OnHTTPResponse : function(response, error){
this.Device.Data = response.data;
this.Device.StatusCode = response.statusCode;
this.Device.ResponseHeaders = response.headers;
this.Device.HTTPError = error.errorText;
},
Example:
this.myHTTPClient.on('download_progress', this._OnHTTPDownloadProgress);
_OnHTTPDownloadProgress : function(downloadProgress){
this.Device.DownloadProgress = downloadProgress;
},
Requests data to the specified server
get(url, requestHeaders, items, itemsEncoding, userName, password)
Submits data to be processed by the specified server.
post(url, requestHeaders, data, items, itemsEncoding, userName, password)
Uploads data into the specified server.
put(url, requestHeaders, data, items, itemsEncoding, userName, password)
Download a file from the server and save it in a specific directory.
downloadFile(url, requestHeaders, path, items, itemsEncoding, userName, password)
Sends a request to delete the data/document into the specified server..
deleteResource(url, requestHeaders, items, itemsEncoding, userName, password)
Get the Header value, from a list of Headers, matching to a specific Header name.
getHeaderValue(headerList, headerName)
Return: Returns the value of the header. If the header name is not found, an empty string is returned.
Get the name of a Header by specifying its index in the list of Headers.
getHeaderNameByIndex(headerList, headerIndex)
Return: Returns the name of the header. If the header index is not correct, an empty string is returned.
Get the value of a Header by specifying its index in the list of Headers.
getHeaderValueByIndex(headerList, headerIndex)
Return: Returns the value of the header. If the header index is not correct, an empty string is returned.
Get the count of Header in the list.
getHeaderCount(headerList)
Return: Count of Header.
Add a Header in the list.
addHeader(headerList, headerName, headerValue)
Return: Returns a new Header list based on the provided list and containing the new Header.
Note: Each Headers are separted by ‘\r\n’ characters. This variable can be used in a Medialon List. Each Header contains a name and a value which are separated by a ‘:’ character (ex: Connection:Keep-Alive).
A Serial, a DMX or an IO Channel resource can be accessible from the Script.
Gets a resource from its reference. This function belongs to the QMedialon object.
GetResource( reference )
Returns A Serial, a DMX or an IO Channel object if the resource exists and if this resource is not already used. Otherwise, an empty object is returned.
Example:
//Setup definition for a Serial resource
Info:{
Setup:{
iSerialID:{
Widget:"Serial",
Name:"COM Port:"
}
}
},
Setup:{
iSerialID:-1
},
//local script variable
SerialRes:null,
Init: function()
{
//get the Serial resource
this.SerialRes = QMedialon.GetResource( "Serial", this.Setup.iSerialID );
}
The Serial object provides the methods below:
Open the Serial resource
Open( openListener )
Close the Serial resource
Close( closeListener )
Set the BaudRate
SetBaudRate( baudRate )
Set the BaudRate
SetStopBits( stopBits )
Set the data size
SetDataSize( dataSize )
Set the parity
SetParity( parity )
enable or no the sent of a break
SetBreak( break )
Set the DTR
SetDTR( DTR )
Set the RTS
SetRTS( RTS )
Set the DTR Control
SetDTRControl( DTRControl )
Set the RTS Control
SetRTSControl( RTSControl )
Set the DTR Handshake
SetDTRHandshake( DTRHandshake )
Set the DSR Out Flow
SetDSROutFlow( DSROutFlow )
Set the RTS Handshake
SetRTSHandshake( RTSHandshake )
Set the CTS Out Flow
SetCTSOutFlow( CTSOutFlow )
Define the break character which is the character that will be set in the frame for sending a break (low status) on the serial line.
SetBreakCharacter( breakCharacter )
Define the break time which is the time that this break will last.
SetBreakTime( breakTime )
Send a data.
Write( data )
Associate an event to a callback function.
On( event, callback )
Example:
({
Info:{
Setup:{
iSerialID:{
Widget:"Serial",
Name:"COM Port:"
}
}
},
Setup:{
iSerialID:-1
},
SerialRes:null,
_OnReceivedData: function(data) {
//data.toString();
},
Init: function()
{
this.SerialRes = QMedialon.GetResource( "Serial", this.Setup.iSerialID );
this.SerialRes.On('data', this._OnReceivedData );
this.SerialRes.Open();
},
Send: function()
{
this.SerialRes.Write("hello");
}
})
The DMX is splitted in two different resources DMXIn and DMXOut object which provide the methods below:
Open the DMXIn / DMXOut resource
Open( openListener )
Close the DMXIn / DMXOut resource
Close( closeListener )
Sends a block of data.
WriteBlock( data, startChannel, channelCount )
Reads a block of received data.
ReadBlock( startChannel, channelCount )
Returns a new Buffer containing the block asked.
Associate an event to a callback function.
On( event, callback )
Example:
({
Info:{
Setup:{
DMXInRef:{
Widget:"DMXIn",
Name:"DMX In:"
},
DMXOutRef:{
Widget:"DMXOut",
Name:"DMX Out:"
}
}
},
Setup:{
DMXInRef:"",
DMXOutRef:""
},
Device:{
DMXInRed:0,
DMXInGreen:0,
DMXInBlue:0
},
DMXInRes:null,
DMXOutRes:null,
RGBBuff:null,
//this function is called when the DMXIn receives something
_OnReceivedData: function(data) {
//the bits 5, 6 and 7 values are put in the device variables
this.Device.DMXInRed = data[5];
this.Device.DMXInGreen = data[6];
this.Device.DMXInBlue = data[7];
},
_InitDeviceVariables: function() {
//initialize the device variables
this._OnReceivedData( this.DMXInRes.ReadBlock() );
},
_mStart: function()
{
//create a buffer which can contains 3 bits
this.RGBBuff = new Buffer(3);
this.RGBBuff.fill(0);
//get the DMX output resource and open it
this.DMXOutRes = QMedialon.GetResource( this.Setup.DMXOutRef );
this.DMXOutRes.Open();
//get the DMX input resource, associate a callback and open it
this.DMXInRes = QMedialon.GetResource( this.Setup.DMXInRef );
this.DMXInRes.On('data', this._OnReceivedData );
this.DMXInRes.Open( this._InitDeviceVariables );
},
WriteRGB: function()
{
//send the slider values via the RGBBuff Buffer at the position 5, 6 and 7
this.RGBBuff[0] = QMedialon.GetValueAsInteger( "SliderRed.Status" );
this.RGBBuff[1] = QMedialon.GetValueAsInteger( "SliderGreen.Status" );
this.RGBBuff[2] = QMedialon.GetValueAsInteger( "SliderBlue.Status" );
this.DMXOutRes.WriteBlock( this.RGBBuff, 5, 3 );
}
})
The IO Channel is splitted in four different resources DigitalIn, DigitalOut, AnalogIn and AnalogOut object which provide the methods below:
Open the DigitalIn / DigitalOut / AnalogIn / AnalogOut resource
Open( openListener )
Close the DigitalIn / DigitalOut / AnalogIn / AnalogOut resource
Close( closeListener )
Set the value of an IO.
SetValue( value, flush )
Get the value of an IO.
GetValue()
Returns the value as an integer.
Associate an event to a callback function.
On( event, callback )
Example:
({
//define IOChannel1Ref and IOChannel2Ref as Digital Output
Info: {
Setup: {
IOChannel1Ref: {
Widget:"DigitalOut"
},
IOChannel2Ref: {
Widget:"DigitalOut"
}
}
},
Device:{
IOChannel1Val:0,
IOChannel2Val:0
},
Setup: {
IOChannel1Ref:"",
IOChannel2Ref:""
},
//local script variables which are associated to the IO Channel resources
IOChannel1Res:null,
IOChannel2Res:null,
//private script function which is called each time that the IO Channels change
_OnReceivedData: function( val, obj ) {
if( obj == this.IOChannel1Res ) {
this.Device.IOChannel1Val = val;
}
else if( obj == this.IOChannel2Res ) {
this.Device.IOChannel2Val = val;
}
},
//private script function which must be called when a resource is opened
//in order to initialize the Device Variable
_InitValue: function( obj ) {
if( obj == this.IOChannel1Res ) {
this.Device.IOChannel1Val = this.IOChannel1Res.GetValue();
}
else if( obj == this.IOChannel2Res ) {
this.Device.IOChannel2Val = this.IOChannel2Res.GetValue();
}
},
//private script function which is called when the program starts
_mStart: function(){
//get the resources, link the callbacks and open the resources
this.IOChannel1Res = QMedialon.GetResource( this.Setup.IOChannel1Ref );
this.IOChannel1Res.On('data', this._OnReceivedData );
this.IOChannel1Res.Open( this._InitValue );
this.IOChannel2Res = QMedialon.GetResource( this.Setup.IOChannel2Ref );
this.IOChannel2Res.On('data', this._OnReceivedData );
this.IOChannel2Res.Open( this._InitValue );
},
SetAllOutputsToOn: function() {
//the value of each resources will be modified at the same moment
// because only the last SetValue as a its 'flush' parameter set to true
this.IOChannel1Res.SetValue( 1, false );
this.IOChannel2Res.SetValue( 1 );
},
SetAllOutputsToOff: function() {
//the value of each resources will be modified at the same moment
// because only the last SetValue as a its 'flush' parameter set to true
this.IOChannel1Res.SetValue( 0, false );
this.IOChannel2Res.SetValue( 0 );
}
})
A Buffer is similar to an array of integers but corresponds to a raw memory allocation outside the V8 heap. A Buffer cannot be resized.
The Buffer class is a global type for dealing with binary data directly. It can be constructed in a variety of ways.
new Buffer(size)
Allocates a new buffer of size octets.
new Buffer(array)
Allocates a new buffer using an array of octets.
new Buffer(str, [encoding])
Allocates a new buffer containing the given str. Encoding defaults to ‘utf8’.
toString([encoding], [start], [end])
Decodes and returns a string from buffer data encoded with encoding (defaults to ‘utf8’) beginning at start (defaults to 0) and ending at end (defaults to buffer.length)
Converting between Buffers and JavaScript string objects requires an explicit encoding method. Here are the different string encodings:
copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])
Do copy between buffers. The source and target regions can be overlapped.
All values passed that are undefined/NaN or are out of bounds are set equal to their respective defaults.
Example:
//build two Buffers, then copy buf1 from byte 16 through byte 19 into buf2,
// starting at the 8th byte in buf2
buf1 = new Buffer(26);
buf2 = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf1[i] = i + 97; // 97 is ASCII a
buf2[i] = 33; // ASCII !
}
buf1.copy(buf2, 8, 16, 20);
return buf2.toString('ascii');
// !!!!!!!!qrst!!!!!!!!!!!!!
concat a list of buffers in a new buffer.
concat(list, [totalLength])
Returns a buffer which is the result of concatenating all the buffers in the list together. If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
Example:
var buffer1 = new Buffer("Controller");
var buffer2 = new Buffer("Stage");
//var buff = buffer2.concat([buffer1]);
var buff = buffer2.concat([buffer1, buffer2]);
return buff.toString();
//ControllerStage
Writes string to the buffer at offset using the given encoding. Length is the number of bytes to write.
write(string, [offset], [length], [encoding])
Returns number of octets written. This buffer did not contain enough space to fit the entire string, it will write a partial amount of the string. The method will not write partial characters.
Example:
var buf = new Buffer(256);
var len = buf.write('\u00bd + \u00bc = \u00be', 0);
return (len + " bytes: " + buf.toString('utf8', 0, len));
//12 bytes: ½ + ¼ = ¾
left(length)
Returns a buffer that contains the leftmost length bytes of this buffer.
The entire buffer is returned if length is greater than size().
Example:
var buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; //"97" is the ASCII code for "a"
}
var result = buf.left(10));
// result = "abcdefghij"
middle(position, length)
Returns a buffer containing length bytes from this buffer, starting at position position. If length is –1 (the default), or position + length >= buffer size, returns a buffer containing all bytes starting at position until the end of the buffer.
Example:
var buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; //"97" is the ASCII code for "a"
}
var result = buf.middle(10, 5));
// result = "klmno"
right(length)
Returns a buffer that contains the rightmost length bytes of this buffer.
The entire buffer is returned if length is greater than size().
var buf = new Buffer(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97; //"97" is the ASCII code for "a"
}
var result = buf.right(10));
// result = "qrstuvwxyz"
Fills the buffer with the specified value.
buf.fill(value, [offset], [end])
Example:
var buf = new Buffer(10);
buf.fill("a");
var temp = buf.toString();
//temp= "aaaaaaaaaa")
A checksum is a count of the number of bits in a transmission unit that is included with the unit so that the receiver can check to see whether the same number of bits arrived. If the counts match, it’s assumed that the complete transmission was received.
A Checksum object can be constructed easily.
new Checksum()
Allocates a new Checksum object.
Example:
var ck = new Checksum();
Set multiple parameters of the checksum in order to initialize it.
Init( checksumType, countOfBytes, twosComp, ASCIIcoded )
Default values:
Initialize the checksum Type.
SetChecksumType( checksumType )
Initialize the count of bytes in the checksum result. This function is mainly usefull when the checksum type is Sum and if this sum must be done on more than 1 byte.
SetChecksumType( checksumType )
Invert all the bits of the checksum value, and add 1. If the checksum as 2 bytes, the addition will be done on the second byte.
SetTwoComplement( twosComp )
Example:
0010 0111 0100 1111 (0x274f) become: 1101 1000 1011 0001 (0xd8b1)
1010 1100 (0xAC) become: 0101 0100 (0x54)
Allows to code the result in ASCII format.
SetAsciiCoded( ASCIIcoded )
Invert the the 2 bytes of the Crc16 checksum result.
SetHighByteFirst( highByte )
highByte: (boolean) When true the order of the two bytes resulting of the Crc16 is high-low, when false it is low-high.
This parameter will change the order of the checksum bits like this:
Here we have a 2 bytes checksum:
0010 0111 0100 1111 (0x274f)
if SetHighByteFirst is true, the checksum bytes, will become:
1111 0100 0111 0010 (0xf472)
Set the Mask/Polynom of the CRC16 checksum.
SetCRC16Mask( crc16Mask )
Set the initial value of the CRC16 checksum.
SetCRC16InitialValue( crc16Initial )
Set the Mask/Polynom of the CRC8 checksum.
SetCRC8Mask( crc8Mask )
Set the initial value of the CRC8 checksum.
SetCRC8InitialValue( crc8Initial )
Computes the checksum matching with the data provided as parameter and insert the checksum result at a specific position, and return the new buffer (or string) with the checksum inserted.
ComputeChecksum( data, checksumPosition )
Returns a new Buffer containing the initial data and the checksum result inserted to the appropriated position.
Example:
var ck = new Checksum();
ck.SetChecksumType( "Crc16" );
var buff = new Buffer("Hello World!!" );
var result = ck.ComputeChecksum( buff, buff.length - 2 );
return result.toString("hex");
//the returned value is 48656c6c6f20576f726c6468172121
//0x6817 is the checksum result
//it has been inserted 2 bytes before the end of the buff data
//note that 0x21 -> !
Update the checksum result. This allows to compute a checksum with multiple datas.
UpdateChecksumToCompute( data )
Get the computed checksum result.
GetComputedChecksum()
Returns a new Buffer which contains the checksum result.
Example:
var ck = new Checksum();
ck.SetChecksumType( "Crc16" );
var buff = new Buffer("Hello World!!" );
ck.UpdateChecksumToCompute( buff ); //or ck.UpdateChecksumToCompute( "Hello World!!" );
var result = ck.GetComputedChecksum();
return result.toString("hex");
//0x6817 is the checksum result
Reset the checksum parameters with the initializing values. For example, the CRC16 initial value is resetted to the one provided by the user. The previous changes done by a call of the UpdateChecksumToCompute function are ignored.
ResetChecksumToCompute()
A simple, small and minimal XML parser has been integrated into the JavaScript engine. It reads XML and creates objects representing the XML document. The objects can be manipulated, changed, and saved again as XML.
Examples:
var xmlDoc = new XMLDocument();
var xmlEltPlaylist = xmlDoc.CreateElement("playlist");
xmlDoc.AppendChild( xmlEltPlaylist );
var xmlEltItem1 = xmlDoc.CreateElement("item");
xmlEltPlaylist.AppendChild( xmlEltItem1 );
xmlEltItem1.SetAttribute( "id", 1 );
var xmlEltFilename1 = xmlDoc.CreateElement("filename");
xmlEltItem1.AppendChild( xmlEltFilename1 );
xmlEltItem1.SetText( "example_A.mp3" );
var xmlEltTitle1 = xmlDoc.CreateElement("title");
xmlEltItem1.AppendChild( xmlEltTitle1 );
xmlEltItem1.SetText( "Song A" );
var xmlDataToRead =
'<playlist>' +
' <item id="1">' +
' <filename>example_A.mp3</filename>' +
' <title>Song A</title>' +
' </item>' +
' <item id="2">' +
' <filename>example_B.mp3</filename>' +
' <title>Song B</title>' +
' </item>' +
'</playlist>';
var xmlDoc = new XMLDocument();
xmlDoc.Parse( xmlDataToRead );
var rootElt = xmlDoc.DocumentElement();
var itemChild = rootElt.FirstChildElement();
while( !itemChild.IsNull() ) {
var id = itemChild.Attribute("id");
var titleChild = itemChild.FirstChildElement("title");
if( !titleChild.IsNull() ) {
var titleText = titleChild.GetText();
}
itemChild = itemChild.NextSiblingElement();
}
Parse the given block of xml data.
Parse( XMLData )
Get the root element, the only top level element, of the document.
DocumentElement()
Return: Returns the root XMLElement Object.
Create a new XMLElement Object
CreateElement( tagName )
Return: Returns the a new XMLElement Object.
Add a new XMLElement child. The new XMLElement is added at the end of the list.
AppendChild( newChild )
If an error occurs, Error will be set to true.
Error()
Return: Returns true if an error has been detected in this XMLDocument Object.
Convert the XML data from the XMLElement to a string.
ToString()
Return: Returns the XML data from the XMLElement as a string.
Set the tag name of this XMLElement.
SetTagName ( tagName )
Get the tag name of this XMLElement.
GetTagName ()
Return: Returns the XML tag name of this XMLElement.
Set the text of this XMLElement.
SetText ( text )
Get the text of this XMLElement.
GetText ()
Return: Returns the text of this XMLElement.
Define a new attribute.
SetAttribute ( name, value )
Remove an attribute.
RemoveAttribute ( name )
Get the value of a specific attribute of this XMLElement.
Attribute ( name )
Return: Returns the value of the attribute as a string.
Check if the XMLElement is empty.
IsNull()
Return: Returns true if the XMLElement has no tag name, none attribute, no XMLElement child…
Get the first XMLElement child of this object.
FirstChildElement()
Return: Returns the first XMLElement of this Object.
Get the first XMLElement child of this object which has the tag name defined as argument.
FirstChildElement( tagName )
Return: Returns the first XMLElement of this Object.
Get the next sibling XMLElement.
NextSiblingElement()
Return: Returns the next sibling XMLElement.
Get the next sibling XMLElement which has the tag name defined as argument.
NextSiblingElement( tagName )
Return: Returns the next sibling XMLElement.
Append a XMLElement to another one.
AppendChild( newChild )
Several Manager sample projects and scripts can be found here.
In order to facilitate the search in the script area from the Setup or in the Control Panel the access the a Find window is available by pressing Ctrl+F or clicking on ‘Find…’ in the contextual menu. This Find window is pretty basic and allows to search in up or down direction and it can be set as case sensitive.
One Debugger by device is automatically created when the mxmMedialonScript.cfg contains the lines below:
[DEBUGGER]
enable=1
The ‘enable’ option is 0 by default.
The Debugger allows to debug the script in Debug/User Mode/Run Project modes, not in Stop mode. BreakPoints and differentes actions like Continue/Interrupt/Step Into/Step Over/Step Out are available. The value of each variables defined into the script can be read. The Debugger provides also Runtime Error.
Note: All the calls to a Qmedialon.Perform which have an effect on the GUI should be commented when the debugger is enabled, otherwise Manager can be frozen.
The Device setup Dialog is used to:
The “Default Script” of a mxmMedialonScript device is the script which is loaded and executed by default when the device is started (when the project goes into run mode). This script is also saved in the project file and automatically reloaded when the project is loaded. Most of the time this is the only script used by the device (unless the advanced dynamic script loading feature is used: see the Load From File and Load From Text command description).
The Script area is used to edit the Default Script code of the device.
The JavaScript code is saved in the project when the Setup Dialog is closed by clicking the “OK” button.
To easily edit script, this area provides a syntax highlighting system and a contextual menu which allows to quickly insert Medialon Variable, Task, Cue, UserGroup, UserScreen or Device name.
The Variables tab of the setup dialog can be used to adapt the default value of the device variables.
The type of these variables can be:
These variables are automatically extracted from the script during the Setup. See Device Variables in the JavaScript Guidelines section for the JavaScript device variable declaration syntax.
Select a variable a click “Edit…” button to display the Edit dialog which allows changing the type of variable and its value.
The Options tab of the setup dialog provides is a section where specific configuration can be done concerning the Programming and the Control Panel.
In the option tab, there is an option which permits to disable the default commands and value if you don’t need it, in order to clarify the utilization of the script by a final user (in the commands menus for example)
Default Commands are:
Default Variables are:
It is possible to force the value of this option directly in the script:
Info:{
Options:{
RemoveDefaultCommandsAndVariables:[false/true]
},
In this case and because this script line has the priority, the checkbox will be disabled.
One checkbox allows to automatically register all User Groups.
If this option is checked, QMedialon.RegisterGroup and QMedialon.UnregisterGroup calls will be ignored.
A line informs the end user if the Debugger is enabled or not.
The Auto-Completion system allows to automatically complete some words (QMedialon functions, Medialon variables, tasks, user groups…) into the javascript Edit box of the Setup dialog. But for huge project with many Variables and Devices the loading time of the Setup can be long. In this case, it might be useful to disable the Auto-Completion.
Two check boxes allows specifying the Control Panel visibility:
“Visible In User Mode”: if checked, the Device Control Panel is visible in User Mode. Otherwise the Device Control Panel is hidden.
“Visible In Run Mode”: if checked, the Device Control Panel is visible in Run Mode. Otherwise the Device Control Panel is hidden.
These options are useful if the control panel is put in a container in order to display it during the execution.
The purpose of the Control Panel is to allow “live editing” of the JavaScript code for minor modification or debugging while the Medialon project is running. Thus, the Device Control Panel should not be displayed in a normal production environment as it is geared toward people who have some skills in JavaScript and in Medialon programming.
The Device Control Panel has one main area for the script edition:
The Script Edition area is very similar to the one in the Setup Dialog box and supports the same interactions. For example, a script evaluation button allows to verify the script syntax and it is also possible to load or save the script in files.
In addition, a ‘Script Status’ panel indicates whether script displayed in the edition area is the same as the script currently running in the device:
If the script has been modified, it is possible to update the currently running device script by clicking on the ‘Update Device’ button.
The ‘Set as Default Script’ check box allows defining the currently edited script as the Device Default Script when the ‘Update Device’ button is clicked. Note that the current project must be saved in order to store the new Device Default Script in the project.
The ‘Refresh from Device’ button replaces the content of the editing area with the script which is currently running in the device. In that case the Script Status switches back from ‘Modified’ to ‘Loaded’.
Note that a Debugger button is displayed when the Debugger is enabled. Clicking on this button, the Debugger window will open.
Executes a script function.
Script example:
({
Device: { Counter:0},
Increment: function(){
this.Device.Counter++;
}
})
Task Programming Example:
Line Device Command
---- ------ -------
1 Script Execute Function("Increment")
The “Counter” device variable is incremented each time the task is executed.
Executes a script function which accepts parameters and returns a result value.
Script example: String concatenation
({
FormatName: function( firstname, lastname ){
return "Hi! My Name is " + firstname + " " + lastname;
}
})
Task Programming Example:
Line Device Command
---- ------ -------
1 Script Execute Function With Params("FormatName",ResultString,"John","")
All parameters except “Script Function Name” are optional. If no value is specified for a parameter, an empty string is passed to the script function.
Parameters are passed as “String” values to the script functions. This means that parameter values must be converted to numbers if the script functions expects numbers instead of strings. A typical way of converting a string to a number in JavaScript is to use the parseInt() or parseFloat() JavaScript functions as shown in the following example:
Script example: Computing an average value
({
Average: function( a, b, c ){
a = parseInt(a,10);
b = parseInt(b,10);
c = parseInt(c,10);
return (a + b + c)/3;
}
})
Dynamically loads a script from a file.
The current script of the device is replaced by the file content. The script is parsed and the device “Error” variable is set to an empty string is the script syntax is correct. Otherwise, the “Error” variable indicates the syntax error and the line where the error occured.
Note that the device script is reset to the default script when the project is switched from “Stop” mode to “Debug”,“User Mode” or “Run” mode.
Dynamically loads a script from a text string.
The current script of the device is replaced by the string content. The script is parsed and the device “Error” variable is set to an empty string is the script syntax is correct. Otherwise, the “Error” variable indicates the syntax error and the line where the error occured.
Note that the device script is reset to the default script when the project is switched from “Stop” mode to “Debug”,“User Mode” or “Run” mode.
[Enum] Current status of the device.
[String] Current error of the device.
[String] Current loaded script file name.
[String] Current loaded script text.
[String] List of the available script functions.