Creating a Simple Controller

The fastest and easiest way to get acquainted with writing Controllers is to walk through the steps of creating a simple one.

Example Project

Unzip this template project exampleTemplate into a project development folder of your choosing.

Once unzipped, explore the project folders…

At the top level is the “Example App” folder and a batch file for installing the app (we will use this later.)

Click on the Example App folder.

common includes two Javascript files necessary for communicating with the API. These must be installed with the app.

exampleSRC carries the source for this example.

example.xml defines this controller. Captivate reads this to set things up, so you will need to create one of these for each Controller you write.

Example.xml

Let’s start by looking in example.xml:

<inputBehavior
  name="Example App: Date and Time"
  url="exampleSrc/exampleApp.html"
  iconOn="exampleSrc/alien.png"
  UIGroups="General">
  <variable name="Date" type="text" />
  <variable name="Time" type="text" />
</inputBehavior>

name: This sets the name of the controller. Note that the part before the colon, “Example App,” must match the name of the parent folder. The part after the colon will be used in the Captivate UI menu, in this case, “Date and Time.” The whole string that identifies this input, must be unique among all controller inputs and should be used in subsequent API calls.

url: This provides the location of the actual web page to load. If this were running off a cloud server, it would provide the full URL. In this case, it provides a relative path.

iconOn: This is an optional icon file used to display the icon for this controller in the Captivate title/layer list.

Next, this file lists all the variables that this input will provide to any title it is controlling. In this case, there are two variables, “Date” and “Time.” Both are “text” variables, meaning they provide text values.

ExampleApp.html

Now, go into the examplesSrc folder where you will find the aliens.png and the exampleApp.html file.

Open exampleApp.html in your code editor:

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="../common/js/qwebchannel.js"></script>
    <script type="text/javascript" src="../common/js/servicehandler.js"></script>
    <script type="text/javascript">
      window.onload = function () {
        // Initiate the server connection.
        ServiceHandler.init();
        // Retrieve the name of this input.
        var inputName = ServiceHandler.inputName;

        // We should handle error conditions, such as network loss or something else unexpected.
        ServiceHandler.onclose = function () {
          console.warn('ServiceHandler disconnected');
        };

        ServiceHandler.onerror = function (error) {
          console.error('ServiceHandler error', error);
        };

        // This is our callback when the server is connected and we're ready to access the APIs.
        ServiceHandler.onready = function () {
          // Set up responses to the three button clicks.

          // When the user clicks on the Play In button, set the time and date variables and fly the title in.
          document.getElementById('schedulePlayIn').onclick = function () {
            // Create a json object for variables to set.
            var variables = {};
            // Set the current time and date.
            var timeNow = new Date();
            variables['Time'] = timeNow.toLocaleTimeString();
            variables['Date'] = timeNow.toLocaleDateString();
            // Send the AnimateIn action with this input as the sender, and the new variable settings.
            ServiceHandler.scheduler.scheduleAction('animateIn', ServiceHandler.inputName, '', variables);
          };

          // When the user clicks on the Update button, update with the current time and date.
          document.getElementById('scheduleUpdate').onclick = function () {
            // Create a json object for variables to set.
            var variables = {};
            // Set the current time and date.
            var timeNow = new Date();
            variables['Time'] = timeNow.toLocaleTimeString();
            variables['Date'] = timeNow.toLocaleDateString();
            // Send the update action with this input as the sender, and the new variable settings.
            ServiceHandler.scheduler.scheduleAction('update', ServiceHandler.inputName, '', variables);
          };

          // When the user clicks on the Play Out button, fly the title out.
          document.getElementById('schedulePlayOut').onclick = function () {
            // Send the AnimateIn action with this input as the sender, and no variables.
            ServiceHandler.scheduler.scheduleAction('animateOut', ServiceHandler.inputName, '', {});
          };

          console.info('ServiceHandler connected, ready to send/receive messages!');
        };
      };

      window.onbeforeunload = function () {
        ServiceHandler.scheduler.pageClosed(inputName);
      };
    </script>
  </head>
  <body>
    <div class="w3-container w3-small ">
      <h4>Date and Time</h4>
      <p>Click on buttons to trigger actions:</p>
      <input type="submit" id="schedulePlayIn" value="Play In" />
      <input type="submit" id="scheduleUpdate" value="Update" />
      <input type="submit" id="schedulePlayOut" value="Play Out" />
    </div>
  </body>
</html>

As you can see, this is a minimal application.

It has three buttons which will play a title in, update its values, and play it out.

Let’s see what each of these does.

Start by looking at the code for the first button:

// When the user clicks on the Play In button, set the time and date variables and fly the title in.
document.getElementById('schedulePlayIn').onclick = function () {
  // Create a json object for variables to set.
  var variables = {};
  // Set the current time and date.
  var timeNow = new Date();
  variables['Time'] = timeNow.toLocaleTimeString();
  variables['Date'] = timeNow.toLocaleDateString();
  // Send the AnimateIn action with this input as the sender, and the new variable settings.
  ServiceHandler.scheduler.scheduleAction('animateIn', ServiceHandler.inputName, '', variables);
};

This creates a JavaScript object where each key is the name of an input variable and each value assigned to it is the string value for that Variable.

Then, it calls the scheduleAction API. scheduleAction is the core API function used to schedule “actions” on a title. Actions are special commands that manage title playback.

The parameters are:

Parameter
Description

action

The action to take, for example ‘render’ to prepare a title or ‘update’ to update the title with new values.

inputName

Name of this Controller’s Input. If provided, the action applies to all Titles connected to this Input; if omitted, it applies to all Titles in the project.

titleId

The ID of a specific Title. If an Input is connected to multiple Titles, use this to specify which one to update (see the API on scheduleCommand to get Title IDs)

variables

The Javascript object with any variable values to assign.

Take a look at the code for the other two buttons. It’s very similar, with the primary difference being the action itself.

Note: The function calling animateOut doesn’t modify the variables, and instead sends an empty object to the scheduler ({}). Captivate will only modify variable values when it receives new data for them, so you only need to send variable values when data in Captivate should change.

Okay, now let’s install this and run it!

Installing ExampleApp.html

Go back up to the top level and, if you are on Windows, simply double-click on copyfiles.bat. This script copies all XML, HTML and other related files in a sub-folder under C:\Program Files\NewBlueFX\Titler Content\Resources\Service Handlers\HTML

If on a Mac, you can drag and drop the entire Example App folder to /Library/Application Support/NewBlueFX/Titler Content/Resources/Service Handlers/HTML

Run In Captivate

Start Captivate. If it is currently running, you must quit it and restart. This is because it only reads the XML definition file once, on startup.

Once it is running, place any title which has two or more text variables in the Title/Layer list.

Then, in the data controllers column of that title, click to select your new input from the popup menu.

Once selected, it should show up as the input with the little green alien icon to the left of it.

Next, assign the Date and Time variables to your title in the preview pane.

Simply drag and drop each to the desired text fields in the title.

Now it is ready for testing. Try the three buttons.

Debugging

Next, directly debug the app right here in the browser. Right mouse click to access the DevTools option.

This opens a Chromium debugger window.

Choose the sources tab and select the source file in the file view on the left.

Now you are ready to debug.

If you click to the left of a line number, it inserts a break point.

Now, click on the button and the debugger will stop at this break point. You can now step through the code and see how it works.

If you make changes to the source code, it’s easy to update the code live in Captivate. Just copy the files in again and then right mouse click in the browser and choose reload.

Now that you are up and running, go to Sample Controllers Tour and dive deeper into the programming samples. Be sure to check out the JSON Command Tester, which offers a quick way to discover and explore over two dozen API commands.

Last updated