<chapter id="extensions">
  <title>&app; Extensions</title>
  
  <para>
    &app; supports the creation of custom extensions to ActionScript. This
    allows you to integrate any conceivable system or library function into
    ActionScript execution.
  </para>
  <para>
      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.
  </para>
  <para>
      Some extensions are distributed with &app;, mainly to serve
      as an example. Extensions are not enabled by default, both for
      security and compatibility reasons.
  </para>
  
  <sect1 id="newext">
    <title>Creating A New Extension</title>

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

    <para>
      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
      <emphasis>configure.ac</emphasis> so the new directory will be
      configured along with the rest of &app;.
    </para>

    <para>
      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 <emphasis>check_PROGRAMS</emphasis>
      variable so that &quot;make check&quot; works.
    </para>

    <para>
      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;.
    </para>

    <sect1 id="craftext">
      <title>Crafting an Extension</title>

      <para>
          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.
      </para>
      <para>
          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:
      </para>
	  <programlisting>
	      void extension_init(as_object&amp; where, const ObjectURI&amp; uri);
      </programlisting>
      <para>
          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.
      </para>
      <para>
          Our extension class will imaginatively be called
          &quot;Extension&quot;. 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:
      </para>
      <programlisting>
          void
          extension_init(as_object&amp; where, const ObjectURI&amp; uri) 
          {
              // Get a reference to the global object.
              Global_as&amp; gl = getGlobal(where);

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

              // Create the class
              as_object* cl = gl.createClass(&amp;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(&quot;Extension&quot;, cl);
          }
      </programlisting>
      <para>
          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:
      </para>
      <programlisting>
          void
          attachInterface(as_object&amp; obj)
          {
              Global_as&amp; gl = getGlobal(obj);
              obj.init_member(&quot;ext1&quot;, gl.createFunction(&amp;extension_ext1));
          }
      </programlisting> 
      <para>
          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.
      </para>
      <para>
          The attachStaticInterface() function looks identical:
      </para>
      <programlisting>
          void
          attachStaticInterface(as_object&amp; obj)
          {
              Global_as&amp; gl = getGlobal(obj);
              obj.init_member(&quot;static1&quot;, gl.createFunction(&amp;extension_static1));
          }
      </programlisting> 
      <para>
          This does exactly the same as the previous function, but it
          attaches &quot;static&quot; properties to the class. Such functions can
          be called directly, that is, without requiring an instance of
          Extension:
      </para>
      <programlisting>
          Extension.static();
      </programlisting>
      <para>
          The other undefined function is extension_ctor. Like extension_ext1,
          this is an ActionScript callback function. Such functions have the
          signature:
      </para>
      <programlisting>
          as_value extension_ctor(const fn_call&amp; fn);
      </programlisting>
      <para>
          The fn_call type contains information about the ActionScript function
          call, including the number of arguments, the &quot;this&quot; 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.
      </para>
      <para>
          The function extension_static is the simplest function. A possible
          implementation is as follows:
      </para>
      <programlisting>
          as_value
          extension_static(const fn_call&amp; 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);
          }
      </programlisting>
      <para>
          The member function implementation extension_ext1 is barely more
          complex. It could look like this:
      </para>
      <programlisting>
          as_value extension_ext1(const fn_call&amp; 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&lt;ValidThis&gt;(fn);

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

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

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

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

              // This is the return value of the function.
              return as_value(&quot;return value&quot;);
          }
      </programlisting>
      <para>
          It is not a very useful function. In ActionScript, this definition
          will have the following effect:
      </para>
      <programlisting>
          var e = new Extension();
          var i = e.ext1(8);
          trace(e.property) // traces &quot;8&quot;
          trace(i) // traces &quot;return value&quot;
      </programlisting>
      <para>
          The constructor function is very similar, but has a different
          purpose. When the actionscript &quot;new Extension&quot; is called,
          this extension_ctor function will be called with a newly-created
          object as the &quot;this&quot; object. Its job is to attach properties
          to the &quot;this&quot; object. Unlike the class prototype's propertes
          that we attached in the attachInterface function, any properties
          attached here belong directly to the new object.
      </para>
      <programlisting>
          as_value
          extension_ctor(const fn_call&amp; fn)
          {
              // When called as a constructor, there is always a &quot;this&quot; object
              as_object* this_ptr = ensure&lt;ValidThis&gt;(fn);

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

              // A constructor function must not return anything.
              return as_value();
          }
      </programlisting>
      <para>
          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):
      </para>
      <programlisting>
          as_value extension_ctor(const fn_call&amp; fn)
          {
          }
      </programlisting>
      <para>
          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:
      </para>
      <programlisting>
          void
          extension_init(as_object&amp; where, const ObjectURI&amp; uri) 
          {
              string_table&amp; st = getStringTable(where);
              registerBuiltinClass(where, extension_ctor, attachInterface,
                  0, st.find(&quot;Extension&quot;));
          }
      </programlisting>
      <para>
          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:
      </para>
      <programlisting>
          #include &quot;Relay.h&quot;
          #include &lt;complex&gt;

          class Complex : public Relay
          {
          public:
              typedef std::complex&lt;double&gt; type;
              Complex(type c = type()) : _c(c) {}
              type _c;
          };
      </programlisting>
      <para>
          Using this Relay involves two steps: attaching it, and accessing
          it. Relays must be attached in the constructor:
      </para>
      <programlisting>
          as_value extension_ctor(const fn_call&amp; fn)
          {
              as_object* this_ptr = ensure&lt;ValidThis&gt;(fn);
              this_ptr->setRelay(new Complex())
          }
      </programlisting>
      <para>
          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:
      </para>
      <programlisting>
          as_value
          extension_toString(const fn_call&amp; fn)
          {
              // This ensures that the function can only be called as a
              // member function of a genuine Complex object.
              Complex* c = ensure&lt;IsNativeType&lt;Complex&gt; &gt;(fn);

              std::ostringstream s;
              s &lt;&lt; &quot;real:&quot; &lt;&lt; c.real() &lt;&lt; &quot;,imag: &lt;&lt; c.imag();
              // This is the return value of the function.
              return as_value(s.str());
          }
      </programlisting>
    </sect1>

  </sect1>

  <sect1 id="debuext">
    <title>Debugging An Extension</title>
    
    <para>
      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
      <emphasis>^C</emphasis> to drop into the GDB command console.
    </para>
    <programlisting>
      bool stall = true;
      while (stall) {
          sleep 1;
      }
    </programlisting>

    <para>
      Once you have set the breakpoints you want, reset the value of
      the <emphasis>stall</emphasis> variable to break out of the
      loop, and the SWF movie will then continue playing.
    </para>
    <programlisting>
      (gdb) set variable stall = false;
      continue
    </programlisting>

  </sect1>
  
  <sect1 id="inclext">
    <title>Included Extensions</title>

    <para>
      &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.
    </para>
    
    &gtkext;
    &fileext;
    &mysqlext;

  </sect1>

</chapter>
