# &app; Extensions

&app; supports the creation of custom extensions to ActionScript. This allows you to integrate any conceivable system or library function into ActionScript execution.

Extensions do not represent a general alteration of the ActionScript language. They are designed to allow &app; to be more flexible and powerful where it is required. They allow you to customize &app; for your own purposes and to distribute those changes to other users who need them. They are not intended for use in normal SWF execution or internet browsing, but rather for executing SWFs designed to use those extensions under controlled conditions.

Some extensions are distributed with &app;, mainly to serve as an example. Extensions are not enabled by default, both for security and compatibility reasons.

## Creating A New Extension

Each new extension should live in its own directory. The extensions included in &app; are all in the gnash/extensions directory. Creating an extension requires a Makefile.am,

If you are adding this extension to the &app; source tree itself, then you need to make two changes to add the new extension. The first change is to add the directory to the list in extensions/Makefile.am. This can be done either by adding the new directory to the SUBDIRS setting, or by wrapping it in a conditional test. The other change is to add it to the AC_OUTPUT list in configure.ac so the new directory will be configured along with the rest of &app;.

Each extension should have an ActionScript source file included that tests the new class, and this file should be referenced in the new Makefile.am in the check_PROGRAMS variable so that "make check" works.

When creating an extension that is a wrapper for an existing development library API, it's often better to make this a thin layer than to get carried away with creating beautiful abstractions. Higher-level classes that offer a lot of new functionality are fine, but this is different from wrapping a library so it can be used from within &app;.

### Crafting an Extension

An extension defines a built-in type of ActionScript object. An ActionScript object may have native type information known as a Relay. This adds an extra layer of complexity and runtime cost, so avoid using it unless necessary.

ActionScript classes consist of a constructor function and a prototype object. The constructor function is called when an instance of your extension class is created. The prototype object contains the properties inherited by instances of the extension class. To create an extension class, you must provide an entry function with the following signature:

    	      void extension_init(as_object& where, const ObjectURI& uri);

This will be called during initialization. The first argument is the object to which your class will be attached. For extensions, this is the Global object, known as _global in ActionScript 2.0. The second argument is ignored for extension classes.

Our extension class will imaginatively be called "Extension". Our extension_init function takes care of attaching the prototype and constructor function to the passed object object. One way to do this is as follows:

              void
              extension_init(as_object& where, const ObjectURI& uri)
              {
                  // Get a reference to the global object.
                  Global_as& gl = getGlobal(where);

                  // Create a prototype object
                  as_object* proto = createObject(gl);

                  // Create the class
                  as_object* cl = gl.createClass(&extension_ctor, proto);

                  // Attach the class's functions to the prototype object.
                  attachInterface(*proto);

                  // Attach static properties to the class itself
                  attachStaticInterface(*cl);

                  // Attach the class to the passed object.
                  where.init_member("Extension", cl);
              }

You will notice three functions in the example above that need definition. The first two are attachInterface() and attachStaticInterface(). This is a convention in &app; to separate ActionScript interface creation from the registration of our Extension class. We will see why this is useful later. The attachInterface function may be defined as follows:

              void
              attachInterface(as_object& obj)
              {
                  Global_as& gl = getGlobal(obj);
                  obj.init_member("ext1", gl.createFunction(&extension_ext1));
              }

This attaches a function called ext1 to the Extension class prototype. When ext1 is called in ActionScript, &app; will execute the C++ function named extension_ext1. This is known as a ActionScript callback function and must have the correct signature. We will deal with this next. The member function function will be inherited by all instances of Extension.

The attachStaticInterface() function looks identical:

              void
              attachStaticInterface(as_object& obj)
              {
                  Global_as& gl = getGlobal(obj);
                  obj.init_member("static1", gl.createFunction(&extension_static1));
              }

This does exactly the same as the previous function, but it attaches "static" properties to the class. Such functions can be called directly, that is, without requiring an instance of Extension:

              Extension.static();

The other undefined function is extension_ctor. Like extension_ext1, this is an ActionScript callback function. Such functions have the signature:

              as_value extension_ctor(const fn_call& fn);

The fn_call type contains information about the ActionScript function call, including the number of arguments, the "this" object (if present), the VM and the Global object. With one small exception, the constructor function extension_ctor, and the ext1 function implementation, extension_ext1, do the same thing.

The function extension_static is the simplest function. A possible implementation is as follows:

              as_value
              extension_static(const fn_call& fn)
              {
                  // Reject any calls with no arguments. We must ensure that
                  // we do not access out-of-range arguments.
                  if (!fn.nargs) return as_value();

                  // Convert the first argument to a double.
                  const double d = fn.arg(0).to_number();

                  // This is the return value of the function.
                  return as_value(d * 6);
              }

The member function implementation extension_ext1 is barely more complex. It could look like this:

              as_value extension_ext1(const fn_call& fn)
              {
                  // This ensures that the function can only be called as a
                  // member function of an object. If not, execution of the
                  // function ends at this point.
                  as_object* this_ptr = ensure<ValidThis>(fn);

                  // Reject any calls with no arguments.
                  if (!fn.nargs) return as_value();

                  const as_value& arg0 = fn.arg(0);

                  // The string table manages all strings; we refer to strings
                  // by their index in the table.
                  string_table& st = getStringTable(fn);

                  // Set a member named "property" on the object to the value of
                  // the first argument.
                  this_ptr->set_member(st.find("property"), arg0);

                  // This is the return value of the function.
                  return as_value("return value");
              }

It is not a very useful function. In ActionScript, this definition will have the following effect:

              var e = new Extension();
              var i = e.ext1(8);
              trace(e.property) // traces "8"
              trace(i) // traces "return value"

The constructor function is very similar, but has a different purpose. When the actionscript "new Extension" is called, this extension_ctor function will be called with a newly-created object as the "this" object. Its job is to attach properties to the "this" object. Unlike the class prototype's propertes that we attached in the attachInterface function, any properties attached here belong directly to the new object.

              as_value
              extension_ctor(const fn_call& fn)
              {
                  // When called as a constructor, there is always a "this" object
                  as_object* this_ptr = ensure<ValidThis>(fn);

                  // The init_member function will never replace an existing
                  // property.
                  this_ptr->init_member("myProperty", true);

                  // A constructor function must not return anything.
                  return as_value();
              }

You may not want to do anything in your constructor. It is perfectly valid to use the following as a constructor function (and indeed this is recommended unless you need more complex behaviour):

              as_value extension_ctor(const fn_call& fn)
              {
              }

If you have defined all the callback functions in the way described above, you can simplify the class registration. &app; provides a convenience function to register a built-in class. In this case, your entry function would look like this:

              void
              extension_init(as_object& where, const ObjectURI& uri)
              {
                  string_table& st = getStringTable(where);
                  registerBuiltinClass(where, extension_ctor, attachInterface,
                      0, st.find("Extension"));
              }

For more advanced extensions, you may want to store extra information in an object. You can do this using a Relay. This imposes type restrictions when using the object in ActionScript. A Relay is a C++ class that could look like this:

              #include "Relay.h"
              #include <complex>

              class Complex : public Relay
              {
              public:
                  typedef std::complex<double> type;
                  Complex(type c = type()) : _c(c) {}
                  type _c;
              };

Using this Relay involves two steps: attaching it, and accessing it. Relays must be attached in the constructor:

              as_value extension_ctor(const fn_call& fn)
              {
                  as_object* this_ptr = ensure<ValidThis>(fn);
                  this_ptr->setRelay(new Complex())
              }

To access this information in ActionScript callback functions, we must ensure that the object has the correct type of Relay attached. A toString function (which must also be attached to the prototype!) could look like this:

              as_value
              extension_toString(const fn_call& fn)
              {
                  // This ensures that the function can only be called as a
                  // member function of a genuine Complex object.
                  Complex* c = ensure<IsNativeType<Complex> >(fn);

                  std::ostringstream s;
                  s << "real:" << c.real() << ",imag: << c.imag();
                  // This is the return value of the function.
                  return as_value(s.str());
              }

## Debugging An Extension

You can resort to the time honored technique of creating a loop before the point you want to set a breakpoint for. &app; will stop playing the movie at this point, and then you can externally attach GDB to the running process, or type ^C to drop into the GDB command console.

          bool stall = true;
          while (stall) {
              sleep 1;
          }

Once you have set the breakpoints you want, reset the value of the stall variable to break out of the loop, and the SWF movie will then continue playing.

          (gdb) set variable stall = false;
          continue

## Included Extensions

&app; has some extensions included in the distribution. This is mostly because they were written by the &app; team. Extensions can be external to gnash, &app; needs no compiled in knowledge to load an extension file.

&gtkext; &fileext; &mysqlext;