[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash/doc/C/usermanual/installation amf.xml as_...
From: |
Rob Savoye |
Subject: |
[Gnash-commit] gnash/doc/C/usermanual/installation amf.xml as_... |
Date: |
Sat, 01 Mar 2008 15:04:43 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Rob Savoye <rsavoye> 08/03/01 15:04:43
Added files:
doc/C/usermanual/installation: amf.xml as_value.xml
codestyle.xml internals.xml
logging.xml main.xml memory.xml
new_as_class.xml object.xml
plugin.xml revisions.xml rtmp.xml
Log message:
Moved from user manual.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/amf.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/as_value.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/codestyle.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/internals.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/logging.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/main.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/memory.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/new_as_class.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/object.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/plugin.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/revisions.xml?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/doc/C/usermanual/installation/rtmp.xml?cvsroot=gnash&rev=1.1
Patches:
Index: amf.xml
===================================================================
RCS file: amf.xml
diff -N amf.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ amf.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,132 @@
+<sect1 id="amf">
+ <title>AMF Format</title>
+
+ <para>
+ The AMF format is used in the LocalConnection, SharedObject,
+ NetConnection, and NetStream ActionScript classes. This is a means
+ of binary data interchange between Flash movies, or between a
+ Flash player and a Flash server.
+ </para>
+
+ <para>
+ Like the RTMP messages, an AMF packet header can be of a variable
+ size. The size is either the same as the initial header of the
+ RTMP message, or a 1 byte header, which is commonly used for
+ streaming audio or video data.
+ </para>
+
+ <para>
+ The body of an AMF packet may look something like this
+ example. The spaces have been added for clarity.
+
+ <screen>
+ 02 0007 636f6e6e656374
+ </screen>
+
+ <variablelist>
+ <varlistentry>
+ <term>02</term>
+ <listitem>
+ <para>
+ This is a single byte header. The value of the first 2
+ bits is 0x3, and the AMF index is also 0x3.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0007</term>
+ <listitem>
+ <para>
+ This is the length in bytes of the string.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>63 6f 6e 6e 65 63 74</term>
+ <listitem>
+ <para>
+ This is the string. Note that there is no null terminator
+ since the length is specified.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+
+<!--
+ <para>
+ These data types are used to exchange data between Flash
+ movies. The data part of a message is one of the ActionScript data
+ types.
+
+ <variablelist>
+ <varlistentry>
+ <term>Byte</term>
+ <listitem>
+ <para>
+ A single byte.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Int</term>
+ <listitem>
+ <para>
+ Two bytes (a short).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>MediumInt</term>
+ <listitem>
+ <para>
+ Three bytes.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Long</term>
+ <listitem>
+ <para>
+ Four bytes (an int).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Double</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>UTF8</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>LongUTF8</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+-->
+
+</sect1>
+
Index: as_value.xml
===================================================================
RCS file: as_value.xml
diff -N as_value.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ as_value.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,75 @@
+ <sect1 id="as_value">
+ <title>The <emphasis>as_value</emphasis> Object Type</title>
+ <para>
+ The <emphasis>as_value</emphasis> class is used throughout
+ the interpreter to create generic objects to hold data.
+ </para>
+
+ <sect2 id="data_types">
+ <title>Data Types</title>
+ <para>
+ The following data types are supported:
+ <emphasis>NULLTYPE</emphasis>,
+ <emphasis>BOOLEAN</emphasis>, <emphasis>STRING</emphasis>,
+ <emphasis>NUMBER</emphasis>, <emphasis>OBJECT</emphasis>,
+ <emphasis>AS_FUNCTION</emphasis>, and
+ <emphasis>MOVIECLIP</emphasis> (sprite).
+ The type <emphasis>C_FUNCTION</emphasis> is being deprecated.
+ </para>
+ </sect2>
+
+ <sect2 id="is_methods">
+ <title>Determining the Type</title>
+ <para>
+ Several methods allow you to determine if a value stored in
+ <emphasis>as_value</emphasis> is of a specific type. These
+ follow the form of <emphasis>is_TYPE</emphasis>, for example
+ <emphasis>is_as_function()</emphasis> and
+ <emphasis>is_number()</emphasis>. In general, the type names
+ match the <link linkend="data_types">data types</link> listed
+ above, with the exception of the type <emphasis>MOVIECLIP</emphasis>
+ which has a method <emphasis>is_sprite()</emphasis>.
+ </para>
+ </sect2>
+
+ <sect2 id="to_methods">
+ <title>Fetching the Value</title>
+ <para>
+ Another set of methods will return a representation of
+ the value as a particular type. They follow the
+ <emphasis>to_TYPE</emphasis> naming convention. Examples
+ are <emphasis>to_number()</emphasis> and
+ <emphasis>to_bool()</emphasis>. The type names are as
+ <link linkend="data_types">listed</link> earlier, except for
+ <emphasis>MOVIECLIP</emphasis>, which uses
+ <emphasis>to_sprite()</emphasis>.
+ </para>
+ </sect2>
+
+ <sect2 id="set_methods">
+ <title>Setting the Value and Type</title>
+ <para>
+ Finally, there is the <emphasis>set_TYPE</emphasis> series
+ of methods. They change the type to the type specified in
+ the method name, and set the value to the one given as an
+ argument. It is also possible to accomplish the same thing
+ with the <emphasis>=</emphasis> operator. Again, type names
+ match those <link linkend="data_types">named earlier</link>,
+ except in the case of <emphasis>MOVIECLASS</emphasis>. Its
+ method is called <emphasis>set_sprite()</emphasis>.
+ </para>
+ </sect2>
+
+ <sect2 id="further_as_value_reading">
+ <title>Further Reading</title>
+ <para>
+ Please refer to <emphasis>as_value.h</emphasis> or the
+ Doxygen documentation (see 'Processing The Documentation'
+ in the &appname; manual for instructions on generating
+ documents with Doxygen) for more information
+ about which methods are available for the
+ <emphasis>as_value</emphasis> object.
+ </para>
+ </sect2>
+
+ </sect1>
Index: codestyle.xml
===================================================================
RCS file: codestyle.xml
diff -N codestyle.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ codestyle.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,167 @@
+<sect1 id="appendix">
+ <title>Appendix</title>
+
+ <sect2 id="codestyle">
+ <title>Code Style</title>
+
+ <para>
+ I know any discussion of coding styles leads to strong opinions,
+ so I'll state simply I follow the <ulink type="http"
+ url="http://www.gnu.org/prep/standards/standards.html">GNU
+ Coding Standards</ulink>. Where there is some flexibility as to
+ the location of braces, I prefer mine on the end of a line when
+ using an <emphasis>if</emphasis>, <emphasis>while</emphasis>, or
<emphasis>do</emphasis>
+ statement. I find this more compact style easier to read and
+ parse by eye. I'm also a big fan of always using
+ braces around <emphasis>if</emphasis> statements, even if they're one
+ liners.
+ </para>
+
+ <para>
+ Here's my tweaked style settings for <emphasis>Emacs</emphasis>, the one
+ true editor to rule them all.
+
+ <programlisting>
+ (defconst my-style
+ '((c-tab-always-indent . t)
+ (c-auto-newline . t)
+ (c-hanging-braces-alist . (
+ (brace-list-intro)
+ (namespace-open)
+ (inline-open)
+ (block-open)
+ (brace-list-open)
+ (brace-list-close)
+ (brace-entry-open)
+ (brace-else-brace)
+ (brace-elseif-brace)
+ (class-open after)
+ (class-close)
+ (defun-open after)
+ (defun-close)
+ (extern-lang-open)
+ (inexpr-class-open)
+ (statement-open)
+ (substatement-open)
+ (inexpr-class-close)))
+ (c-hanging-colons-alist . ((member-init-intro before)
+ (inher-intro)
+ (case-label after)
+ (label after)
+ (access-label after)))
+ (c-offsets-alist . (
+ (innamespace . 0)
+ (case-label . 2)
+ ))
+ (c-cleanup-list . (
+ (scope-operator)
+ (empty-defun-braces)
+ (brace-else-brace)
+ (brace-elseif-brace)
+ (defun-close-semi)
+ (list-close-comma)
+ )
+ )
+ ;; no automatic newlines after ';' if following line non-blank or inside
+ ;; one-line inline methods
+ (add-to-list 'c-hanging-semi&comma-criteria
+ 'c-semi&comma-no-newlines-before-nonblanks)
+ (add-to-list 'c-hanging-semi&comma-criteria
+ 'c-semi&comma-no-newlines-for-oneline-inliners)
+; (knr-argdecl-intro . -)
+ (c-echo-syntactic-information-p . t)
+ )
+ "My GNU Programming Style")
+ </programlisting>
+
+ </para>
+
+ <para>
+ Another coding consideration: comments are good! Over
+ commenting isn't good. Here is an over commented example:
+
+ <programlisting>
+ counter++; // increment counter
+ </programlisting>
+
+ Gnash also uses <ulink type="http"
+ url="http://www.doxygen.org">Doxygen</ulink> style
+ comments. These are processed by Doxygen when building a cross
+ reference of all the classes, and is a good way to help push
+ internals documentation from the depths of the code into
+ documentation where it can be seen by others.
+ </para>
+
+ <para>
+ <emphasis>Doxygen</emphasis> style comments for <emphasis>C++</emphasis>
code involves
+ simply using three slashes <emphasis>///</emphasis> instead of the
+ standard two slashes <emphasis>//</emphasis> used for C++
+ comments. Here's a short comment block for the
+ <emphasis>XML::cloneNode()</emphasis> method:
+
+ <programlisting>
+ /// \brief copy a node
+ ///
+ /// Method; constructs and returns a new XML node of the same type,
+ /// name, value, and attributes as the specified XML object. If deep
+ /// is set to true, all child nodes are recursively cloned, resulting
+ /// in an exact copy of the original object's document tree.
+ XMLNode &
+ XML::cloneNode(XMLNode &newnode, bool deep) {
+ ...
+ }
+ </programlisting>
+ </para>
+
+ <para>
+ The <emphasis>\brief</emphasis> keyword means that the
+ text becomes associated
+ when listing all the classes on the generated web pages. The
+ text after the blank link becomes the detailed description which
+ appears on the generated web page for that class and method.
+ </para>
+ </sect2>
+
+ &rtmp;
+
+<!--
+ <sect2 id="opcodes">
+ <title>Shockwave Movie Opcodes</title>
+
+ <sect3 id="v5">
+ <title>Version 5</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+ <sect3 id="v6">
+ <title>Version 6</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+ <sect3 id="v7">
+ <title>Version 7</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+ <sect3 id="v8">
+ <title>Version 8</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+ <sect3 id="v9">
+ <title>Version 9</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+
+ </sect2>
+-->
+
+</sect1>
+
+
Index: internals.xml
===================================================================
RCS file: internals.xml
diff -N internals.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ internals.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,1095 @@
+<sect1 id="internals">
+ <title>Software Internals</title>
+
+ <sect2 id="tour">
+ <title>A Tour of Gnash</title>
+
+ <para>
+ The top level of Gnash has several libraries,
<emphasis>libgnashbase</emphasis>,
+ <emphasis>libgnashgeo</emphasis>, <emphasis>libgnashserver</emphasis>,
+ <emphasis>libgnashasobjs</emphasis> and
+ <emphasis>libgnashbackend</emphasis>. There are two utility programs
+ included for debug parsing and processing of Flash movie files
+ which test the Actionscript interpreter. There is also a standalone
+ flash movie player.
+ </para>
+
+ <sect3 id="The Libraries">
+ <title>The Libraries</title>
+
+ <sect4 id="libbase">
+ <title>libgnashbase</title>
+
+ <para>
+ Libgnashbase contains support classes used by the rest of the
+ code. Among these classes is a small and efficient STL library
+ clone that uses smart pointers. A current goal is to replace
+ this small STL clone with standard STL containers to reduce
+ the amount of code which has to be maintained, and to add
+ functionality not currently in the smaller
+ implementation.
+ </para>
+
+ <para>
+ Gnash makes heavy use of smart pointers, so memory allocations
+ are freed up automatically by the interpreter.
+ </para>
+
+ </sect4>
+
+ <sect4 id="libgnashgeo">
+ <title>libgnashgeo</title>
+
+ <para>
+ Libgnashgeo contains code for device independent graphics routines.
+ </para>
+
+ </sect4>
+
+ <sect4 id="libgnashgui">
+ <title>libgnashgui</title>
+
+ <para>
+ Libgnashgui contains code for a portable GUI class that
+ supports using GTK2, a framebuffer, SDL, or KDE.
+ </para>
+
+ </sect4>
+
+ <sect4 id="libgnashserver">
+ <title>libgnashserver</title>
+ <para>
+ Libgnashserver is the guts of the interpreter itself. This is where
+ the main code for the interpreter lives.
+ </para>
+ </sect4>
+
+ <sect4 id="libgnashasobjs">
+ <title>libgnashasobjs</title>
+ <para>
+ Libgnashasobjs contains all the ActionScript classes used by
+ the interpreter.
+ </para>
+ </sect4>
+
+ <sect4 id="libgnashamf">
+ <title>libgnashamf</title>
+ <para>
+ AMF is the data format used internally by Flash. This is
+ Gnash's support library to handle AMF data. This is
+ currently unused, but when the LocalConnection class is more
+ fully implemented, this will be used to transfer data
+ between flash movies.
+ </para>
+ </sect4>
+
+ <sect4 id="libgnashbackend">
+ <title>libgnashbackend</title>
+
+ <para>
+ Libgnashbackend is a small library containing OpenGL and SDL
+ code that glues this display to the Gnash display.
+ </para>
+
+ </sect4>
+ <sect4 id="libgnashpluin">
+ <title>libgnashplugin</title>
+
+ <para>
+ Libgnashplugin is the Mozilla/Firefox plugin.
+ </para>
+
+ </sect4>
+ <sect4 id="libklashpart">
+ <title>libklashpart</title>
+
+ <para>
+ Libklashpart is the Konqueror plugin.
+ </para>
+
+ </sect4>
+ </sect3>
+
+
+ <sect3 id="apps">
+ <title>The Applications</title>
+
+ <para>
+ There are currently a few standalone programs in Gnash,
+ which serve to either assist with Gnash development or play flash
+ movies.
+ </para>
+
+ <sect4 id="Gnash">
+ <title>The Standalone Player</title>
+
+ <para>
+ This is the standalone OpenGL back-end used to play
+ movies. There are several command-line options and keyboard
+ control keys used by Gnash which <link linkend="usage"> are
+ documented here.</link>
+ </para>
+
+ </sect4>
+
+ <sect4 id="parser">
+ <title>Gparser</title>
+
+ <para>
+ Gparser uses the Gnash parser to disassemble the flash
+ movie, and dumps the object types, the depth, and other
+ information to make sure Gnash is parsing the file
+ correctly.
+ </para>
+
+ </sect4>
+ <sect4 id="processor">
+ <title>Gprocesser</title>
+
+ <para>
+ Gprocesser is used to print out the actions (using the -va
+ option) or the parsing (using the -vp option) of a flash
+ movie. It is also used to produce the <emphasis>.gsc</emphasis>
+ files that Gnash uses to cache data, thereby speeding up the
+ loading of files.
+ </para>
+
+ </sect4>
+ </sect3>
+
+ <sect3 id="plugin">
+ <title>The Plugin</title>
+
+ <para>
+ The plugin is designed to work within Mozilla or Firefox,
+ although there is Konqueror support as well. The plugin uses
+ the Mozilla NSPR plugin API to be cross platform, and is
+ portable, as well as being well integrated into Mozilla based
+ browsers.
+ </para>
+
+ <para>
+ One future thought for the plugin is to use the new Firefox
+ 1.0.5 or greater version of Firefox. This version has added a
+ GTK drawable window which supports hardware acceleration, and
+ is designed to support things like rendering directly into the
+ window without needing OpenGL.
+ </para>
+
+ <sect4 id="pluginstatus">
+ <title>Current Status</title>
+ <para>
+ As of March 30, 2006, the plugin works! This works in a
+ fashion similar to MozPlugger in that the standalone player
+ is used instead of using a thread. This gets around the
+ issue of having to maintain a separate player to support the
+ plugin. It also gets around the other issues that Gnash
+ itself is not thread safe at this time.
+ </para>
+ <para>
+ There are a few limitations in the current implementation,
+ but it works well enough to be used for web surfing. The
+ main limitations are the SDL version has no event handling,
+ and sound doesn't work yet.
+ </para>
+ </sect4>
+
+ <sect4 id="gui">
+ <title>GUI Support</title>
+
+ <para>
+ Any plugin that wants to display in a browser window needs
+ to be tied into the windowing system of the platform being
+ used. On GNU/Linux systems, Firefox is a GTK2+ application.
+ There is also KDE support through the use of the Klash
+ plugin.
+ </para>
+
+ <para>
+ Gnash can use either SDL or GTK now to create the window,
+ and to handle events for the standalone player. Work is
+ underway to add a portable interface for more windowing
+ toolkits to allow better embedded device support when
+ running in framebuffer only devices.
+ </para>
+
+ <para>
+ The SDL version is more limited, but runs on all
+ platforms, including win32. It has no support for event
+ handling, which means mouse clicks, keyboard presses, and
+ window resizing doesn't work. I personally find the default
+ event handler slow and unresponsive. Gnash has support to
+ use fast events, (currently not enabled) which is an SDL
+ hack using a background thread to pump events into the SDL
+ event queue at a much higher rate.
+ </para>
+
+ <para>
+ There are a variety of development libraries that build a GUI
+ widget system on top of SDL and OpenGL. The use of these to
+ add menus and dialog boxes to the SDL version is being
+ considered.
+ </para>
+
+ <para>
+ The GTK support is currently the most functional, and the
+ best integrated into Firefox. The performance of this
+ version is better than the SDL version because of the more
+ efficient event handling within GTK. For the best end user
+ experience, use the GTK enabled version.
+ </para>
+
+ <para>
+ GTK also allows Gnash to have menus and dialog
+ boxes. Currently this is only being utilized in a limited
+ fashion for now. There is a right mouse button menu that
+ allows the user to control the movie being player the same
+ way the existing keyboard commands do.
+ </para>
+
+ </sect4>
+
+ <sect4 id="mozplugger">
+ <title>Mozplugger</title>
+
+ <para>
+ <ulink type="http"
+ url="http://mozplugger.mozdev.org/">Mozplugger</ulink> is a
+ <emphasis>Mozilla/Firefox</emphasis> plugin that uses external
+ programs to play video, audio, and other multimedia content
+ in the browser. With some support added to the external
+ application, it's possible to force the external program to
+ use the internal window in the browser where this plugin is
+ supposed to display. This enables one to then run the
+ standalone player and display its output in the browser.
+ </para>
+
+ <para>
+ While this is not an optimal solution, it does enable one to
+ use Gnash as the flash player when browsing. The main issue
+ appears to be that the Flash movie being played doesn't get
+ any mouse or keyboard input. That may be a mozplugger
+ configuration issue, however.
+ </para>
+
+ <para>
+ Use of MozPlugger is obsolete now that the Gnash plugin
+ works. Still, this may be useful still on some platforms.
+ </para>
+
+ <para>
+ Add this to your <emphasis>$(HOME)/.mozilla/mozpluggerrc</emphasis>
+ file to enable this:
+
+ <programlisting>
+ application/x-shockwave-flash:swf:Shockwave Gnash
+ nokill embed noisy ignore_errors hidden fill swallow(Gnash) loop:
gnash -v "$file" -x $window
+ : gnash -v "$file" -x $window
+ </programlisting>
+ </para>
+
+ <para>
+ Once this is added, you must delete the
+ <emphasis>$(HOME)/.mozilla/firefox/pluginreg.dat</emphasis> file to
+ force Firefox to register the plugins again. This is an
+ ASCII text file, so if the patch has been added correctly,
+ you'll see an entry for <emphasis>swf</emphasis> files after it is
+ recreated. You will need to restart Firefox to recreate this
+ file.
+ </para>
+
+ <para>
+ This file is not recreated immediately when restarting
+ Firefox, but waits till the first time a plugin is used. You
+ can force creation of this file by typing
+ <emphasis>about:plugins</emphasis> into the URL entry of the browser
+ window. The output will also contain information about the
+ mozplugger. You should see an entry for Gnash now.
+ </para>
+
+ </sect4>
+
+ <sect4 id="Klash">
+ <title>Klash</title>
+ <para>
+ Klash is MozPlugger type support for KDE's Konqueror web
+ browser. Klash makes Gnash a <emphasis>kpart</emphasis>, so it's
+ integrated into KDE better than when using MozPlugger. Klash
+ uses the standalone player, utilizing Gnash's "-x" window
+ plugin command line option.
+ </para>
+
+ <para>
+ By default, Klash is not built. To enable building Klash,
+ use the <emphasis>--enable-klash</emphasis> option when
+ configuring. Other than installing, there is nothing else
+ that needs to be done to install Klash.
+ </para>
+ </sect4>
+
+ &plugin;
+
+ </sect3>
+
+ &logging;
+
+ </sect2>
+
+ <sect2 id="engine">
+ <title>The Interpreter Engine</title>
+ <para>
+ FIXME:
+ </para>
+
+ <sect3 id="loop">
+ <title>The Main Loop</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+
+ <sect3 id="io">
+ <title>I/O Processing</title>
+ <para>
+ FIXME:
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="soundhandlers">
+ <title>Sound handling in Gnash</title>
+
+ <para>
+ When a SWF-file contains audio Gnash uses its sound handlers to play it.
+ At the moment there are two sound handlers, but it is likely that more
+ will be made.
+ </para>
+
+ <para>
+ There are two different settings related to sound support:
+ <emphasis><link linkend="pluginsound">pluginsound</link></emphasis> and
+ <emphasis><link linkend="standalonesound">sound</link></emphasis>.
+ This was done in order to allow the plugin to be independently
+ configured, for instance to block sound from advertisements.
+ </para>
+
+ <sect3 id="soundtypes">
+ <title>Sound types</title>
+ <para>
+ Sounds can be divided into two groups: event-sounds and soundstreams.
+ Event-sounds are contained in a single SWF frame, but the playtime can
+ span multiple frames. Soundstreams can be (and normally are) divided
+ between the SWF frames the soundstreams spans. This means that if a
+ gotoframe-action jumps to a frame which contains data for a soundstream,
+ playback of the stream can be picked up from there.
+ </para>
+ </sect3>
+
+ <sect3 id="soundparsing">
+ <title>Sound parsing</title>
+ <para>
+ When Gnash parses a SWF-file, it creates a sound handler if possible
+ and hands over the sounds to it. Since the event-sounds are contained
+ in one frame, the entire event-sound is retrieved at once, while a
+ soundstream maybe not be completely retrieved before the entire
+ SWF-file has been parsed. But since the entire soundstream doesn't need
+ to be present when playback starts, it is not necessary to wait.
+ </para>
+ </sect3>
+
+ <sect3 id="soundplayback">
+ <title>Sound playback</title>
+ <para>
+ When a sound is about to be played Gnash calls the sound handler, which
+ then starts to play the sound and return. All the playing is done by
+ threads (in both SDL and Gstreamer), so once
+ started the audio and graphics are not sync'ed with each other, which
+ means that we have to trust both the graphic backend and the audio
+ backend to play at correct speed.
+ </para>
+ </sect3>
+
+ <sect3 id="sdlsound">
+ <title>The SDL sound backend</title>
+ <para>
+ The current SDL sound backend has replaced the original sound
+ handler, based on SDL_mixer, which by design had some limitations,
+ making it difficult to implement needed features such as support
+ for soundstreams.
+ The SDL sound backend supports both event-sounds and soundstreams,
+ using Gnash's internal ADPCM, and optionally MP3 support, using
+ either FFMPEG or LIBMAD.
+ When it receives sound data it is stored without being decoded, unless
+ it is ADPCM, which is decoded in the parser. When playing, backend
+ relies on a function callback for retrieving output sound, which is
+ decoded and re-sampled if needed, and all sound output is mixed
together.
+ The current SDL sound backend was made since Gnash needed a working
+ sound backend as soon as possible, and since the gstreamer backend at
+ the time suffered from bugs and/or lack of features in gstreamer. The
+ result was the most complete and best sound handler so far.
+ The advantages of the SDL sound handler is speed, and ease of use,
+ while its only real disadvantage is that it has to be compiled with
+ MP3 support, which some Linux distributions will probably not like...
+ </para>
+ </sect3>
+
+ <sect3 id="gstreamer">
+ <title>The Gstreamer backend</title>
+ <para>
+ The Gstreamer backend, though not complete, supports both soundstreams
+ and event-sounds. When receiving sound data it stores it compressed,
+ unless if it's ADPCM event-sounds, which it decodes by the parser.
+ When the playback starts, the backend sets up a
+ Gstreamer bin containing a decoder (and other things needed) and places
+ it in a Gstreamer pipeline, which plays the audio. All the sound data is
+ not passed at once, but in small chunks, and via callbacks the
+ pipeline gets fed. The advantages of the Gstreamer backend is that it
+ supports both kinds of sound, it avoids all the legal MP3-stuff, and it
+ should be relatively easy to add VORBIS support. The drawbacks are that
+ it has longer "reply delay" when starting the playback of a sound, and
+ it suffers under some bugs in Gstreamer that are yet to be fixed.
+ </para>
+ </sect3>
+
+ <sect3 id="audio-future">
+ <title>Future audio backends</title>
+ <para>
+ It would probably be desirable to make more backends in the future,
+ either because other and better backend systems are brought to our
+ attention, or perhaps because an internal sound handling is better
+ suited for embedded platform with limited software installed.
+ </para>
+ </sect3>
+
+ <sect3 id="gstreamer-details">
+ <title>Detailed description of the Gstreamer backend</title>
+ <para>
+ Gstreamer uses pipelines, bins and elements. Pipelines are the
+ main bin, where all other bins or elements are places. Visually the
+ audio pipeline in Gnash looks like this:
+ </para>
+
+ <programlisting>
+ ___
+ |Bin|_
+ |___| \
+ ___ \ _____ ____________
+ |Bin|___|Adder|_____|Audio output|
+ |___| |_____| |____________|
+ ___ /
+ |Bin|_/
+ |___|
+
+ </programlisting>
+
+ <para>
+ There is one bin for each sound which is being played. If a sound is
+ played more the once at the same time, multiple bins will be made. The
+ bins contains:
+ </para>
+
+ <programlisting>
+
+
|source|---|capsfilter|---|decoder|---|aconverter|---|aresampler|---|volume|
+
+ </programlisting>
+
+ <para>
+ In the source element we place parts of the undecoded sound data, and
+ when playing the pipeline will pull the data from the element. Via
+ callbacks it is refilled if needed. In the capsfilter the data is
+ labeled with the format of the data. The decoder (surprise!) decodes
+ the data. The audioconverter converts the now raw sound data into a
+ format accepted by the adder, all input to the adder must in the same
+ format. The audio re-sampler re-samples the raw sound data into a sample
+ accepted by the adder, all input to the adder must in the same
+ sample rate. The volume element makes it possible to control the volume
+ of each sound.
+ </para>
+
+ <para>
+ When a sound is done being played it emits a End-Of-Stream-signal
+ (EOS), which is caught by an event-handler-callback, which then makes
+ sure that the bin in question is removed from the pipeline. When a
+ sound is told by Gnash to stop playback before it has ended playback,
+ we do something (not yet finally implemented), which makes the bin emit
+ an EOS, and the event-handler-callback will remove the sound from the
+ pipeline. Unfortunately Gstreamer currently has a bug which causes the
+ entire pipeline to stop playing when unlinking an element from the
+ pipeline; so far no fix is known.
+ </para>
+
+ <para>
+ Gstreamer also contains a bug concerning linking multiple elements to
+ the adder in rapid succession, which causes to adder to "die" and stop
+ the playback.
+ </para>
+ </sect3>
+
+
+ </sect2>
+
+ <sect2 id="testing">
+ <title>Testing </title>
+
+ <para>
+ <link linkend="runtests">Instructions on running tests</link>
+ can be found in the section on building Gnash.
+ </para>
+
+ <sect3 id="testtools">
+ <title>Testing Tools</title>
+
+ <para>
+ Currently Gnash uses three other tools to help with
+ testing. Two of these are free compilers for the Flash
+ format. This lets us write simple test cases for Gnash to test
+ specific features, and to see how the features operate.
+ </para>
+
+ <para>
+ The primary compiler used at this time is <ulink type="http"
+ url="http://ming.sf.net">Ming</ulink>. Since release 0.3,
+ <emphasis>Ming</emphasis> includes a command-line compiler,
+ <emphasis>makeswf</emphasis>. This allows test case development
+ to be done entirely with free tools.
+ </para>
+
+ <para>
+ The other tools are optional.
+ <ulink type="http"
+ url="http://www.gnu.org/software/dejagnu">DejaGnu</ulink>
+ is used to run multiple test cases in an automated
+ manner. <emphasis>DejaGnu</emphasis> is used by many other <ulink
+ type="http" url="http://www.gnu.org">GNU</ulink> projects like
+ <ulink type="http" url="http://gcc.gnu.org">GCC</ulink> and
+ <ulink type="http" url="http://www.samba.org">Samba</ulink>.
+ </para>
+
+ </sect3>
+
+ <sect3 id="testcases">
+ <title>Test Cases</title>
+
+ <para>
+ ActionScript test cases are located under testsuite/actionscript.all/;
+ these are organized in one file for the ActionScript class.
+ Other Ming-generated tests are under testsuite/ming-misc.all/;
+ these are typically used to test specific tag types.
+ Full movies are located in testsuite/movies.all/ and
+ sample movies are found in testsuite/samples/.
+ Other directories in testsuite/ are (or shall be) used for other
+ kind of tests.
+ </para>
+
+ </sect3>
+
+ <sect3 id="writeastests">
+ <title>Writing ActionScript Tests</title>
+
+ <para>
+ Writing ActionScript tests is very simple. The
+ <emphasis>makeswf</emphasis> compiler makes use of the C preprocessor,
+ thus allowing the inclusion of definitions for macros and external
+ files. We use these feature to provide common utilities
+ for test units.
+ </para>
+
+ <para>
+ Each test unit sets an <emphasis>rcsid</emphasis> variable, includes the
+ <emphasis>check.as</emphasis> file and performs some checks using
+ the provided macros. Here is an example:
+
+ <programlisting>
+
+ // This variable will be used by check.as
+ // to show testcase info as part of the test runs.
+ rcsid="Name and version of this testcase, usually the RCS id";
+
+ #include "check.as"
+
+ // Test object creation
+ check(new Object() instanceOf Object);
+
+ // Test parseInt
+ check(isNaN(parseInt('none')));
+
+ // Test assignment
+ var a = 1;
+ check_equals(a, 1);
+
+ // .. your tests here ...
+ </programlisting>
+ </para>
+
+ <para>
+ The check(expr) macro will <emphasis>trace</emphasis> PASSED or FAILED
+ together with the expression being evaluated and the line number
+ of the check. This is the format expected by DejaGnu.
+ </para>
+
+ <para>
+ The <emphasis>check_equals(obtained, expected)</emphasis> macro uses
equality operator
+ <emphasis>==</emphasis> to check for equality. When possible, use of the
+ <emphasis>check_equals()</emphasis> macro is preferred over
<emphasis>check()</emphasis>
+ because it shows what the actual result was in case of a failure.
+ </para>
+
+ <para>
+ Additionally, the check.as file provides a transparent way to send
+ results to a TextField rather then using trace. This is very useful
+ when you use a flash player without tracing support.
+ </para>
+
+ <para>
+ Test units are built by running <emphasis>make
TestName-v#.swf</emphasis>.
+ This will use TestName.as as source and the value of # as target
version.
+ Allowed target version are from 5 to 8 (inclusive).
+ </para>
+
+ <para>
+ Note that if you get a syntax error from the compiler, the line
+ number will refer to the pre-processed file. This file is called
+ <emphasis>TestName.as.pp</emphasis> or
<emphasis>TestName-v#.swf.frame#.pp</emphasis>
+ (depending on Ming version) and it's not thrown away by
+ <emphasis>makeswf</emphasis> to make debugging easier.
+ </para>
+
+ <para>
+ Sometimes an expression is only supported by a specific SWF
+ version, or it's evaluated differently by different SWF versions.
+ For this purpose the framework provides an OUTPUT_VERSION macro
+ that you can use to switch code based on output version. For example:
+
+ <programlisting>
+
+ #if OUTPUT_VERSION >= 7
+ check(_root.getSWFVersion == OUTPUT_VERSION);
+ #endif
+
+ </programlisting>
+ </para>
+ </sect3>
+
+ <sect3 id="writemingtests">
+ <title>Writing Ming-based self-contained SWF tests</title>
+
+ <para>
+ Ming-based test cases are located in testsuite/misc-ming.all
+ and contain a test generator and a test runner.
+ The test generator (usually a C program) is used to produce the SWF
+ file, while the test runner (a C++ program) will run it using a
+ MovieTester class.
+ Note that only the test generator needs Ming, not the test
+ runner, so if Ming isn't installed on the user's host,
+ the test cases can still be run as long as SWF has been distributed.
+ </para>
+
+ <para>
+ Producing tests using Ming has the advantage that you can easily see
+ and modify the full source code for the SWF movie, and you can use
+ some <link linkend="ming_testgenerator_facilities">facilities</link>
+ provided by the Gnash testing framework to easily run tests.
+ </para>
+
+ <para>
+ For generic Ming API documentation, see <ulink type="http"
+ url="http://www.libming.org/">http://www.libming.org</ulink>.
+ </para>
+
+ <sect4 id="ming_testgenerator_facilities">
+ <title>Using Ming-based test generators facilities</title>
+
+ <para>
+ Ming-based test generator facilities, which might be moved into
+ a loadable SWF in the future, can be currently used by your test
+ generator by including the ming_utils.h file and calling the
+ appropriate functions.
+ </para>
+
+ <para>
+ The most useful facility provided for Ming-based SWF test generators
+ is a Dejagnu-like TestState ActionScript class.
+ In order to use this facility you must call 'add_dejagnu_functions()'
+ right after Movie creation.
+ The function takes an SWFMovie object and some parameters specifying
+ depth and location of the "visual" trace textfield; it instantiates
+ a global 'TestState' ActionScript object to keep track of test's state.
+ </para>
+
+ <para>
+ You will <emphasis>not</emphasis> need to directly invoke the
+ TestState object created by the 'add_dejagnu_functions()' routine,
+ rather you will be using C macros hiding its complexity:
+
+ <programlisting>
+
+ check(SWFMovie mo, const char* expr)
+
+ Evaluate an ActionScript expression.
+
+ xcheck(SWFMovie mo, const char* expr)
+
+ Evaluate an ActionScript expression.
+ A failure is expected
+ (for cases where the call exposes a known bug).
+
+ check_equals(SWFMovie mo, const char* obtained, const char* expected)
+
+ Evaluate an ActionScript expression against an expected output.
+
+ xcheck_equals(SWFMovie mo, const char* obtained, const char* expected)
+
+ Evaluate an ActionScript expression against an expected output.
+ A failure is expected (for cases where the call exposes a known
bug).
+
+ print_tests_summary(SWFMovie mo)
+
+ This will print a summary of tests run, and should be
+ called as the last step in your SWF generator.
+
+ </programlisting>
+
+ </para>
+
+ <para>
+ Test cases generated using Ming and the provided
+ <link linkend="ming_testgenerator_facilities">facilities</link>
+ will be self-contained, which means they can be used as tests
+ by simply running them with whatever Player you might have.
+ Any 'check' or 'check_equals' result will be both traced and
+ printed in a textfield. You can use 'gprocessor -v' to have
+ Gnash use them as tests.
+ </para>
+
+ <para>
+ See section <link linkend="writing_test_runners">Writing Test
Runners</link>
+ for information about writing SWF test runners.
+ </para>
+
+
+ </sect4>
+
+ </sect3>
+
+ <sect3 id="writing_dejagnu_so_tests">
+ <title>Writing self-contained SWF tests with other compilers</title>
+
+ <para>
+ If you want/need to use a different compiler for your test cases
(there's
+ plenty of open source tools for generating SWF out there), you can still
+ make use of a loadable SWF utility provided as part of the Gnash
testsuite
+ to let your test consistent with the rest of the suite.
+ </para>
+
+ <para>
+ The loadable module is called <code>Dejagnu.swf</code> and is built
during
+ <code>make check</code> under testsuite/misc-ming.all. In order to use
it
+ you will need to load it into your SWF. We currently load it with an
IMPORT
+ tag for our ActionScript based test cases, but you can probably also use
+ loadMovie or whatever works in the target SWF you're generating. Just
make
+ sure that the module is initialized before using it. You can check this
by
+ inspecting the <code>dejagnu_module_initialized</code> variable, which
will
+ be set to 'true' when all initialization actions contained in the
+ <code>Dejagnu.swf</code> file are executed.
+ </para>
+
+ <para>
+ Once the module is loaded you will be able to invoke the following
functions,
+ all registered against the <code>_root</code> sprite (effects of
<code>_lockroot</code>
+ untested):
+ <programlisting>
+
+ check(expression, [message]);
+
+ Evaluate the expression.
+ Trace result (PASSED: expression / FAILED: expression).
+ If fails, *visually* trace the failure.
+ If second argument is given, it will be used instead of
+ 'expression' for printing results.
+
+ check_equals(obtained, expected)
+
+ Evaluate an expression against an expected output.
+ Trace result (PASSED: obtained == expected / FAILED: expected
X, obtained Y)
+ If fails, *visually* trace the failure.
+
+ xcheck(expression, [message]);
+
+ Evaluate the expression.
+ Trace result (XPASSED: expression / XFAILED: expression).
+ If fails, *visually* trace the failure.
+ If second argument is given, it will be used instead of
+ 'expression' for printing results.
+
+ xcheck_equals(obtained, expected)
+
+ Evaluate an expression against an expected output.
+ Trace result (XPASSED: obtained == expected / XFAILED: expected
X, obtained Y)
+ If fails, *visually* trace the failure.
+
+ note(string)
+
+ Print string, both as debugging and *visual* trace.
+
+ totals()
+
+ Print a summary of tests run, both as debugging and *visual*
traces.
+
+ </programlisting>
+ </para>
+
+ <para>
+ Visual traces are lines of text pushed to a textarea defined by the
<code>Dejagnu.swf</code> module.
+ The textarea is initially placed at <code>0, 50</code> and is
<code>600x800</code> in size.
+ You can resize/move the clip after loading it.
+ Also, you can completely make the clip invisible if that bothers you.
The important thing is the
+ *debuggin* trace (call to the trace function). The latter will be used
by the testing framework.
+ </para>
+
+ <para>
+ See section <link linkend="writing_test_runners">Writing Test
Runners</link>
+ for information about writing a test runners for your self-contained
tests.
+ </para>
+
+ </sect3>
+
+ <sect3 id="writing_test_runners">
+ <title>Writing Test Runners</title>
+
+ <para>
+ Test runners are executables that run one or more tests,
+ writing results in Dejagnu form to standard output.
+ </para>
+
+ <para>
+ The Dejagnu form uses a standard set of labels when printing test
+ results. These are:
+ <informaltable frame="all">
+ <?dbhtml table-width="75%" ?>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry valign="top">
+ <para>Label</para>
+ </entry>
+ <entry valign="top">
+ <para>Meaning</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry valign="top" align="left">
+ <para>PASSED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The test succeeded.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>FAILED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The test failed.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>XPASSED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The test succeeded, but was expected to fail.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>XFAILED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The test failed, and was expected to fail.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>UNRESOLVED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The results of the test could not be automatically
+ parsed.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>UNTESTED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>This test case is not complete.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>UNSUPPORTED</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>The test case relies on a conditional feature which
+ is not present in your environment.</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+
+ <para>
+ The following labels may also appear:
+ <informaltable frame="all">
+ <?dbhtml table-width="75%" ?>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry valign="top">
+ <para>Label</para>
+ </entry>
+ <entry valign="top">
+ <para>Meaning</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry valign="top" align="left">
+ <para>ERROR</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>There was a serious error in running the test. </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>WARNING</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>There may have been a problem with running the
+ test.</para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>NOTE</para>
+ </entry>
+ <entry valign="top" align="left">
+ <para>There was some additional information given about
+ the test.</para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+
+ <sect4 id="generic_test_runner">
+ <title>Using the generic test runner for self-contained SWF
tests</title>
+
+ <para>
+ The simplest test runner is one that simply invokes Gnash
+ in verbose mode against a self-contained SWF test movie.
+ Self-contained SWF test movies are the ones that print
+ the PASSED/FAILED etc. lines using ActionScript (traces).
+ By invoking Gnash in verbose mode this movie will behave
+ as a compliant "Test Runner".
+ </para>
+
+ <para>
+ A generator for simple test runners can be found in
+ <code>testsuite/generic-testrunner.sh</code>.
+ The script can be invoked by passing it <code>$(top_builddir)</code>
+ as the first argument and the name of the SWF file (without the path)
+ as the second argument. This will create a specific runner for your
+ test in the current build directory.
+ A simple Makefile.am rule for doing this follows:
+ <programlisting>
+MyTest-Runner: $(srcdir)/../generic-testrunner.sh MyTest.swf
+ sh $(srcdir)/../generic-testrunner.sh $(top_builddir) MyTest.swf > $@
+ chmod +x $@
+ </programlisting>
+ </para>
+
+ <para>
+ By default, the generated test runner will play the movie up to the
+ last frame. If you want the movie to be played more then once (maybe
+ because you're exactly testing loop features) you can use the -r switch
+ to the generic-testrunner.sh call. The following will create a runner
+ playing the movie twice:
+ <programlisting>
+MyTest-Runner: $(srcdir)/../generic-testrunner.sh MyTest.swf
+ sh $(srcdir)/../generic-testrunner.sh -r2 $(top_builddir) MyTest.swf >
$@
+ chmod +x $@
+ </programlisting>
+ </para>
+
+ <para>
+ In case your test movie stops before the last frame, or you want to
control the
+ exact number of times to call the frame advancement routine, you can
use the
+ -f switch to control that.
+ <programlisting>
+MyTest-Runner: $(srcdir)/../generic-testrunner.sh MyTest.swf
+ sh $(srcdir)/../generic-testrunner.sh -f10 $(top_builddir) MyTest.swf
> $@
+ chmod +x $@
+ </programlisting>
+ When both -f and -r are given, the first exit condition reached will
take effect.
+ </para>
+
+ </sect4>
+
+ <sect4 id="writing_movie_testers">
+ <title>Writing Movie testers</title>
+
+ <para>
+ There are some parts of Gnash that can NOT be tested
+ by only using ActionScript tests. Examples include: frame
+ advancements, actual actions execution, gui events and so on.
+ </para>
+
+ <para>
+ In this case you might want to use the MovieTester class to
+ implement a C++ test runner. Be aware that you can *mix* tests in
+ the MovieTester-based class with *self-contained*
+ tests in the SWF file as long as you activate verbosity for
+ the debug logfile. This is done, for example, for the
+ DefineEditTextVariableNameTest.swf file. The corresponding
+ test runner (DefineEditTextVariableNameTest-Runner) is a C++
+ runner based on MovieTester class. If you run the runner you
+ see two kinds of test results: the ones coming from the ActionScript
+ engine, and the ones coming from the test runner. You can
+ distinguish between the two because the former contains an
additional
+ timestamp and the latter does not. Also, you'll see two final
+ summaries for the two test sets. The 'make check' rule, which uses
+ the testsuite/simple.exp output parser as its work-horse, will
+ count test results from both test sets.
+ </para>
+
+
+ <para>
+ Movie testers are executables which load an SWF, generate events
+ (both user or system) on it, and check its state using
+ a standard interface.
+ </para>
+
+ <para>
+ To help this process a MovieTester class is defined in the
+ testsuite/MovieTester.{h,cpp} files; see Doxygen documentation
+ for more information.
+ </para>
+
+ <para>
+ Note that you do NOT need access to the SWF source code in order
+ to implement a Movie tester for it. Some knowledge about the
+ expected behavior suffices.
+ </para>
+ </sect4>
+ </sect3>
+ </sect2>
+</sect1>
+
Index: logging.xml
===================================================================
RCS file: logging.xml
diff -N logging.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ logging.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,207 @@
+<sect2 id="logging">
+ <title>The Debug Logging System</title>
+
+ <para>
+ Gnash supports a debug logging system which supports both C and C++
+ natively. This means you can use both <emphasis>printf()</emphasis> style
+ debug messages and C++ <emphasis>iostreams</emphasis> style, where you can
+ print C++ objects directly as you would when using
+ <emphasis>cout</emphasis>.
+ </para>
+
+ <para>
+ In the beginning, Gnash only supported the C API for debug
+ logging, so it is the most heavily used in Gnash. This API was used in
+ the <emphasis>log_msg()</emphasis> and <emphasis>log_error()</emphasis>
functions,
+ and used a callback to set them up.
+ </para>
+
+ <para>
+ It became apparent one day the callback was never needed, and I
+ got tired of having to use <emphasis>c_str()</emphasis> on string data
+ just to print them out.
+ </para>
+
+ <para>
+ If a filename is not specified at object construction time, a
+ default name of <emphasis>gnash-dbg.log</emphasis> is used. If Gnash is
+ started from the command line, the debug log will be created in
+ the current directory. When executing Gnash from a launcher under
+ <emphasis>GNOME</emphasis> or <emphasis>KDE</emphasis> the debug file goes
in your
+ home directory, since that's considered the current directory.
+ </para>
+
+ <para>
+ There is common functionality between using the C or C++
+ API. Optional output is based on flags that can be set or
+ unset. Multiple levels of verbosity are supported, so you can get
+ more output by supplying multiple <emphasis>-v</emphasis> options on the
+ command line. You can also disable the creation of the debug log.
+ </para>
+
+ <sect3 id="capi">
+ <title>Logging System C API</title>
+
+ <para>
+ These functions are clones of the originals as they were used
+ for Gnash. These function the same as always except output can
+ be logged to disk now as well. These currently print no
+ timestamp with the output, which is the older functionality. As
+ these functions are implemented on top of the C++ API now, they
+ can be used without corrupting the output buffers.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>void log_msg(const char* fmt, ...)</term>
+ <listitem>
+ <para>
+ Display a message if verbose output is enabled. By default
+ the messages are always written to the disk file, but
+ optionally displayed in the terminal.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>log_error(const char* fmt, ...)</term>
+ <listitem>
+ <para>
+ Display an error message if verbose output is enabled. By
+ default the error messages are always written to the disk
+ file, but optionally displayed in the terminal.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>log_warning(const char* fmt, ...)</term>
+ <listitem>
+ <para>
+ Display a warning message if verbose output is enabled. By
+ default the error messages are always written to the disk
+ file, but optionally displayed in the terminal.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect3>
+
+ <sect3 id="cppapi">
+ <title>Logging System C++ API</title>
+
+ <para>
+ This is the new C++ streams based API that can be used to print
+ C++ objects natively. All output lines are timestamped.
+ </para>
+
+ <para>
+ There are two macros used for program tracing. these can be used
+ in both C or C++ code with one little difference. Since C
+ doesn't have destructors, you must call
+ <emphasis>GNASH_REPORT_RETURN</emphasis> at the end of a function to
+ display the function returning message.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>GNASH_REPORT_FUNCTION;</term>
+ <listitem>
+ <para>
+ When this is included in a C++ method, a message is
+ printed when entering and exiting this method by hooking
+ into the constructor and destructor. These are always
+ written to the disk file, but optionally written to the
+ screen only at the highest levels of verbosity.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>GNASH_REPORT_RETURN;</term>
+ <listitem>
+ <para>
+ This is used by C functions to print the returning from
+ function debug message. For C++, this macro is executed
+ automatically by the destructor.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ This is the main API for the logging system. By default
+ everything is setup to write to the default
+ <emphasis>gnash-dbg.log</emphasis> file whenever a verbose option is
+ supplied. Optionally it is possible to open a log file with a
+ specified name, allowing multiple output files.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>openLog(const char *filespec)</term>
+ <listitem>
+ <para>
+ Open the debug file with the name specified by
+ <emphasis>filespec</emphasis>. This file goes in the current
+ directory, or your home directory if using a menu based
+ launcher.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>closeLog(void)</term>
+ <listitem>
+ <para>
+ Close a debug log. The disk file remains.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>removeLog(void)</term>
+ <listitem>
+ <para>
+ Delete the debug log file from disk.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>setVerbosity(void)</term>
+ <listitem>
+ <para>
+ Increment the verbosity level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>setVerbosity(int)</term>
+ <listitem>
+ <para>
+ Set the verbosity level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>setStamp(bool flag)</term>
+ <listitem>
+ <para>
+ If <emphasis>flag</emphasis> is <emphasis>true</emphasis>, then
print a
+ timestamp prefixed to every output line. If
+ <emphasis>flag</emphasis> is <emphasis>false</emphasis>, then don't
print
+ a timestamp.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>setWriteDisk(bool flag)</term>
+ <listitem>
+ <para>
+ If <emphasis>flag</emphasis> is <emphasis>true</emphasis>, then
create the
+ disk file. If <emphasis>flag</emphasis> is
<emphasis>false</emphasis>,
+ then don't create the disk file.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect3>
+
+</sect2>
Index: main.xml
===================================================================
RCS file: main.xml
diff -N main.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ main.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,29 @@
+ <sect1 id="introduction">
+ <title>Introduction</title>
+
+ <para>
+ In this document, the term 'ActionScript class' refers to the
+ C++ class which is instantiated by Gnash when some ActionScript
+ code instantiates a corresponding class. The C++ class
+ stores instance data and implements the methods which are
+ called on the object in the ActionScript code.
+ </para>
+
+ <sect2 id="overview">
+ <title>Object Creation Overview</title>
+ <para>
+ When Gnash starts, the <emphasis>class_init()</emphasis> method
+ for each ActionScript class (listed in Global.cpp) is called.
+ This method constructs a prototype, which is implemented as an
+ <emphasis>as_object</emphasis>. In addition, the method
+ registers the constructor to be used for future object creation,
+ and attaches methods and properties to the prototype.
+ </para>
+
+ <para>
+ When a new object is needed, instance data is added to
+ the methods and properties inherited from the prototype.
+ </para>
+ </sect2>
+ </sect1>
+
Index: memory.xml
===================================================================
RCS file: memory.xml
diff -N memory.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ memory.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,51 @@
+ <sect1 id="spec-memory">
+ <title>Memory Management</title>
+
+ <para>
+ One of the new features of &app; &appversion; is the garbage
+ collector. The garbage collector manages complex &AS; variables,
+ which are the only ones that are shared by references. In &app;,
+ these are <command>as_object</command> class instances created by &AS;
+ (i.e. not those created by playhead control:
+ <command>placeobject</command>/<command>removeobject</command>).
+ </para>
+
+ <para>
+ Collected objects are those allocated due to &AS; explicit or implicit
+ calls. Explicit all are any user-defined statements that allocate new
+ objects, such as arrays, Objects, or script-created movieclips.
+ Implicit calls are the built-in functions that can be deleted by
+ arbitrary user calls.
+ </para>
+
+ <para>
+ Any object that is a candidate for garbage collecting is stored in a
+ list owned by the collector. This list is filled by an executing
+ action context whenever a collectible object is allocated on the
+ heap.
+ </para>
+
+ <para>
+ The garbage collector starts at the very end of an execution context,
+ rather than using a threshold to trigger it. At this point, the
+ virtual machine is in a "stable" state; any still-reachable object has
+ its roots in one of the currently live character instances (stage
+ characters).
+ </para>
+
+ <para>
+ The collector is a conservative collector. Any object on the
+ collectibles list is marked as <guilabel>UNREACHABLE</guilabel>, an
+ iterative scan starting from the roots marks any still-reachable
+ object, and a final purge releases all
+ still-<guilabel>UNREACHABLE</guilabel> resources.
+ </para>
+
+ <para>
+ This garbage collector has reduced the memory footprint of &app;.
+ However, the most current, available test data indicated the following
+ runtime memory footprint:
+ </para>
+
+ </sect1>
+
Index: new_as_class.xml
===================================================================
RCS file: new_as_class.xml
diff -N new_as_class.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ new_as_class.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,204 @@
+ <sect1 id="newclass">
+ <title>Adding New ActionScript Class</title>
+
+ <para>
+ Adding a new ActionScript class is relatively simple, but the
+ process is complicated by the fact that the interface has evolved
+ over time and the current code base represents several different
+ formats. This document describes the current interface. The
+ Boolean class should be considered the authoritative example of
+ a modern ActionScript class.
+ </para>
+
+ <para>
+ ActionScript classes contain a header file and a C++
+ implementation. The name is usually the name of the
+ class as it is called in the ActionScript specifications;
+ for instance <emphasis>Boolean.cpp</emphasis> for the Boolean class.
+ </para>
+
+ <sect2 id="prototype">
+ <title>Prototype</title>
+
+ <para>
+ In ActionScript, a prototype is a base object which contains
+ all the methods that an instantiated object will contain.
+ In short, it contains every part of the class except for
+ the portions dealing with the storage of instance data.
+ </para>
+ <para>
+ In Gnash, the prototype of an ActionScript object is
+ implemented as an <emphasis>as_object</emphasis>.
+ At startup, the methods and properties of the ActionScript class
+ are attached to the <emphasis>as_object</emphasis>. The
+ following example demonstrates how methods can be attached:
+ <programlisting>
+ static void
+ attachBooleanInterface(as_object& o)
+ {
+ o.init_member("toString", new
builtin_function(boolean_tostring));
+ o.init_member("valueOf", new
builtin_function(boolean_valueof));
+ }
+ </programlisting>
+ </para>
+ <para>
+ Static properties can also be added to the ActionScript prototype
+ (<link linkend="properties">dynamic properties</link>
+ are addressed later). They are attached in a similar way:
+ <programlisting>
+ o.init_member("myProperty", as_value("HelloWorld"));
+ </programlisting>
+ </para>
+ <para>
+ Properties which have been added in this manner can be
+ directly accessed in ActionScript code without a function
+ call, as this piece of ActionScript code compiled by Ming's
+ <emphasis>makeswf</emphasis> compiler demonstrates:
+ <programlisting>
+ // Get the value of the myProperty property
+ if (node.myProperty == "HelloWorld") {
+ trace("MATCHED");
+ }
+ </programlisting>
+ </para>
+ </sect2>
+
+ <sect2 id="declaration">
+ <title>Declaration</title>
+
+ <para>
+ A new class should derive from <emphasis>as_object</emphasis>,
+ which is the base class of every ActionScript object in Gnash.
+ </para>
+ </sect2>
+
+ <sect2 id="instantiation">
+ <title>Instantiation</title>
+
+ <para>
+ The class should contain an init method.
+ </para>
+ <para>
+ The init method should be called in the constructor in
+ <emphasis>Global.cpp</emphasis>, where all other ActionScript
+ classes are similarly referenced.
+ </para>
+ </sect2>
+
+ <sect2 id="methods">
+ <title>Methods</title>
+
+ <para>
+ Every method you implement and
+ <link linkend="prototype">attach</link> will receive an
+ &fn_call; data structure as an argument when it is called.
+ </para>
+
+ <sect3 id="arguments">
+ <title>Accessing Arguments</title>
+ <para>
+ The arguments stored in &fn_call;
+ should be accessed using <emphasis>arg()</emphasis>. For
+ instance, the first element can be popped with
+ <emphasis>fn.arg(0)</emphasis>.
+ </para>
+ <para>
+ The element popped off the stack is an
+ <link linkend="as_value"><emphasis>as_value</emphasis>
+ object</link>.
+ </para>
+ </sect3>
+
+ <sect3 id="return">
+ <title>Returning a Value to ActionScript</title>
+ <para>
+ The return value should be an
+ <link linkend="as_value"><emphasis>as_value</emphasis>
+ object</link>. For example:
+ <programlisting>
+ return as_value('Goodbye, cruel world.');
+ </programlisting>
+ </para>
+ </sect3>
+
+ <sect3 id="additional_fn_call">
+ <title>Additional &fn_call; Members</title>
+ <para>
+ There are two other useful members of the &fn_call;
+ structure, namely <emphasis>this_ptr</emphasis> and
+ <emphasis>nargs</emphasis>. The former points to the
+ class which is invoking this method, while the latter
+ is a count of the number of
+ <link linkend="arguments">arguments in the stack</link>.
+ </para>
+ <para>
+ You may also see instances of the <emphasis>env</emphasis>
+ pointer being used. This is being deprecated. Instances
+ which could be replaced with
+ <link linkend="arguments"><emphasis>arg()</emphasis></link>
+ are already deprecated; other uses will be deprecated
+ in the near future.
+ </para>
+ <para>
+ Beyond the <emphasis><link
+ linkend="arguments">arg()</link></emphasis> method, there
+ is one method of note. <emphasis>dump_args()</emphasis>
+ can be used in debugging to output the entire argument
+ stack.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="properties">
+ <title>Dynamic Properties</title>
+ <para>
+ This section describes accessors to dynamic properties.
+ Read-only properties are described
+ in the <link linkend="prototype">prototype</link> section.
+ </para>
+ <para>
+ Accessors should be written as a single get/set method.
+ Previously this was done by overriding
+ <emphasis>get_member()</emphasis> and
+ <emphasis>set_member()</emphasis>, but this practice
+ is deprecated.
+ </para>
+ <para>
+ The accessor is written so that it sets the property
+ if it is called with an argument, and puts the property in
+ the <link linkend="methods">&fn_call;</link>
+ <link linkend="return">result pointer</link>. For instance:
+ <programlisting>
+ void
+ MyClass::myProperty_getset(const fn_call& fn)
+ {
+
+ boost::intrusive_ptr<MyClass> ptr =
ensureType<MyClass>(fn.this_ptr);
+
+ // setter
+ if ( fn.nargs > 0 )
+ {
+ bool h = fn.arg(0).to_bool();
+ ptr->MyMethod(h);
+ return;
+ }
+
+ // getter
+ bool h = ptr->MyMethod();
+ fn.result->set_bool(h);
+ }
+ </programlisting>
+ </para>
+ <para>
+ It has not yet been decided whether properties should be set
+ in the <link linkend="prototype">exported interface</link>
+ or attached to instances of the class. A property is attached
+ in the following manner:
+ <programlisting>
+ boost::intrusive_ptr<builtin_function> gettersetter;
+ gettersetter = new
builtin_function(&MyClass::myProperty_getset, NULL);
+ o.init_property("myProperty", *gettersetter, *gettersetter);
+ </programlisting>
+ </para>
+ </sect2>
+ </sect1>
Index: object.xml
===================================================================
RCS file: object.xml
diff -N object.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ object.xml 1 Mar 2008 15:04:42 -0000 1.1
@@ -0,0 +1,318 @@
+<sect4 id="asobject">
+ <title>Object ActionScript Class</title>
+
+ <para>
+ This class implements an Object object.
+ </para>
+
+ <sect5 id="objectmethods">
+ <title>The Methods of the Class</title>
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term>addProperty()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>registerClass()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>toString()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>unwatch()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>valueOf()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>watch()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Sharedclear()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Sharedflush()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>SharedgetLocal()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>SharedgetSize()</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </sect5>
+ <sect5 id="objectprops">
+ <title>The Properties of the Object Class</title>
+
+ <para>
+ <variablelist>
+
+ <varlistentry>
+ <term>constructor</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>__proto__</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>__resolve</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Shareddata</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>SharedonStatus</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </sect5>
+
+ <sect5 id="objectconf">
+ <title>Object Class Conformance</title>
+
+ <para>
+ <informaltable frame="all">
+ <?dbhtml table-width="75%" ?>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry valign="top">
+ <para>Class Name</para>
+ </entry>
+ <entry valign="top">
+ <para>Conformance</para>
+ </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry valign="top" align="left">
+ <para>addProperty()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>registerClass()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>toString()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>unwatch()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>valueOf()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>watch()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>Sharedclear()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>Sharedflush()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>SharedgetLocal()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>SharedgetSize()</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This method has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>constructor</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This property has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>__proto__</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This property has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>__resolve</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This property has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>Shareddata</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This property has an unknown status.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry valign="top" align="left">
+ <para>SharedonStatus</para>
+ </entry>
+ <entry valign="top" align="center">
+ <para>
+ This property has an unknown status.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect5>
+</sect4>
Index: plugin.xml
===================================================================
RCS file: plugin.xml
diff -N plugin.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ plugin.xml 1 Mar 2008 15:04:43 -0000 1.1
@@ -0,0 +1,353 @@
+<sect4 id="mozplugin">
+ <title>Mozilla/Firefox Plugin</title>
+
+ <para>
+ The Mozilla SDK has two API layers for plugins. The older layer is
+ documented in the <ulink type="http"
+ url="http://www.gnu.org/software/gnash/manual/plugin.pdf">
+ Geeko Plugin API Reference</ulink>, and the newer layer doesn't
+ appear to be documented. The new API is simpler, and is portable
+ across multiple versions of Mozilla or Firefox. The new API is
+ just a layer on top of the older one, so this manual still
+ applies.
+ </para>
+
+ <para>
+ Most of the programming of a plugin is filling in real emphasis for
+ the standard API functions and methods. Firefox uses these to
+ create the plugin, and to send it data.
+ </para>
+
+ <para>
+ When initializing or destroying a plugin, no matter how many
+ instances are being used, the C API is used. These functions are
+ typically called once for each plugin that is loaded.
+ </para>
+
+ <sect5 id="plugincapi">
+ <title>Plugin C API</title>
+
+ <para>
+ The lower layer is a C based API which is used by Firefox to
+ initialize and destroy a plugin. This is so a plugin can be
+ portable across multiple systems, since C++ emphasis is not portable
+ between most C++ compilers. This is where most of the behind the
+ scenes work is done in a plugin. For Gnash, the sources this
+ lower layer are in <emphasis>plugin/mozilla-sdk</emphasis>. They were
+ added to the Gnash source tree so it wouldn't be necessary to
+ have the Mozilla development packages installed to compile the
+ Gnash plugin.
+ </para>
+
+ <para>
+ This is also the older API used for plugins, so is usually the
+ one used if you dig around for plugin examples on the web. These
+ are the main functions which have to be implemented in a plugin
+ for it to be recognized by the browser, and to be initialized
+ and destroyed.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>NS_PluginInitialize</term>
+ <listitem>
+ <para>
+ This C function gets called once when the plugin is
+ loaded, regardless of how many instantiations there are
+ actually playing movies. So this is where all the one
+ time only initialization stuff goes that is shared by all
+ the threads.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_NewPluginInstance</term>
+ <listitem>
+ <para>
+ This instantiates a new object for the browser. Returning
+ a pointer to the C++ plugin object is what ties the C++
+ and C emphasis parts of the API together.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_DestroyPluginInstance</term>
+ <listitem>
+ <para>
+ This destroys our instantiated object when the browser is
+ done.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_PluginShutdown</term>
+ <listitem>
+ <para>
+ This is called when a plugin is shut down, so this is
+ where all the one time only shutdown stuff goes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NPP_GetMIMEDescription</term>
+ <listitem>
+ <para>
+ This is called to get the MIME types the plugin supports.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_PluginGetValue</term>
+ <listitem>
+ <para>
+ This is used by Firefox to query information from the
+ plugin, like the supported MIME type, the version number,
+ and a description.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect5>
+
+ <sect5 id="plugincppapi">
+ <title>Plugin C++ API</title>
+
+ <para>
+ The higher level layer is the one we are most concerned
+ with. This is an instantiation of the
+ <emphasis>nsPluginInstanceBase</emphasis> class, as defined by the
+ Mozilla SDK, for our plugin. With this API, a plugin is mostly
+ defining the standard entry points for Firefox, and the emphasis
+ that implements the glue between the Firefox and our plugin.
+ </para>
+
+ <para>
+ These are called for each instantiation of plugin. If there are
+ three Flash movies on a web page, then three instances are
+ created. Unfortunately for plugin programmers, these functions
+ may randomly be called more than once, so it's good to use
+ initialization flags for things that should only be done one per
+ thread. For instance, <emphasis>nsPluginInstance::init()</emphasis> and
+ <emphasis>nsPluginInstance::SetWindow()</emphasis> are called more than
+ once, so the plugin must protect against actions that could be
+ destructive.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>nsPluginInstance::nsPluginInstance</term>
+ <listitem>
+ <para>
+ Create a new plugin object.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::init</term>
+ <listitem>
+ <para>
+ This methods initializes the plugin object, and is
+ called for every movie which gets played. This is where
+ the thread-specific information goes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::SetWindow</term>
+ <listitem>
+ <para>
+ This sets up the window the plugin is supposed to render
+ into. This calls passes in various information used by
+ the plugin to setup the window. This may get called
+ multiple times by each instantiated object, so it can't
+ do much but window specific setup here. This is where the
+ main emphasis is that sets up the window for the plugin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::NewStream</term>
+ <listitem>
+ <para>
+ Opens a new incoming data stream, which is the flash
+ movie we want to play. A URL can be pretty ugly, like in
+ this example:
+
http://www.sickwave.com/swf/navbar/navbar_sw.swf?atfilms=http%3a//www.atm.com/af/home/&shickwave=http%3a//www.sickwave.com&gblst=http%3a//gbst.sickwave.com/gb/gbHome.jsp&known=0
../flash/gui.swf?ip_addr=foobar.com&ip_port=3660&show_cursor=true&path_prefix=../flash/&trapallkeys=true"
+ So this is where we parse the URL to get all the options
+ passed in when invoking the plugin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::Write</term>
+ <listitem>
+ <para>
+ Read the data stream from Mozilla/Firefox. For now we
+ read the bytes and write them to a disk file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::WriteReady</term>
+ <listitem>
+ <para>
+ Return how many bytes we can read into the buffer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::DestroyStream</term>
+ <listitem>
+ <para>
+ Destroy the data stream we've been reading. For Gnash,
+ when the stream is destroyed means we've grabbed the
+ entire movie. So we signal the thread to start reading and
+ playing the movie.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::shut</term>
+ <listitem>
+ <para>
+ This is where the movie playing specific shutdown emphasis goes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::~nsPluginInstance</term>
+ <listitem>
+ <para>
+ This destroys our plugin object.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_PluginInitialize::initGL</term>
+ <listitem>
+ <para>
+ This is a Gnash internal function that sets up OpenGL.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>NS_PluginInitialize::destroyContext</term>
+ <listitem>
+ <para>
+ This is a Gnash internal function that destroys a GLX
+ context.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::getVersion</term>
+ <listitem>
+ <para>
+ This returns the version of Mozilla this plugin supports.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::GetValue</term>
+ <listitem>
+ <para>
+ This returns information to the browser about the plugin's
+ name and description.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>nsPluginInstance::URLNotify</term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect5>
+
+ <sect5 id="glthread">
+ <title>OpenGL and Threads</title>
+ <para>
+ Neither OpenGL nor X11 has any built-in support for threads. Most
+ actions aren't even atomic, so care has to be made to not corrupt
+ any internal data. While it is difficult to render OpenGL from
+ multiple threads, it can be done with the proper locking. The
+ downside is the locking adds a performance hit, since all the
+ threads will have to have the access synchronized by using
+ mutexes.
+ </para>
+
+ <para>
+ The X11 context is maintained one per instantiation of the
+ plugin. It is necessary to lock access to the X11 context when
+ using threads by using <emphasis>XLockDisplay()</emphasis> and
+ <emphasis>XUnlockDisplay()</emphasis>. A connection to the X11
+ server is opened for every instantiation of the plugin using
+ <emphasis>XOpenDisplay()</emphasis>.
+ </para>
+
+ <para>
+ The <emphasis>GLX Context</emphasis> is maintained one per
+ instantiation of the plugin for a web page. If there are more
+ than one Flash movie, there is more than one GLX Context. A GLX
+ context can be created by using <emphasis>glXCreateContext()</emphasis>,
+ and then later destroyed by using
<emphasis>glXDestroyContext()</emphasis>.
+ When swapping threads, the context is changed using
+ <emphasis>glXMakeCurrent()</emphasis>.
+ </para>
+
+ <para>
+ All the emphasis that directly accesses a GLX context or the X11
+ display must be wrapped with a mutex.
+ </para>
+
+ </sect5>
+
+ <sect5 id="eventhandle">
+ <title>Plugin Event Handling</title>
+ <para>
+ Firefox on most UNIX systems is a GTK+ application, so it is
+ possible to have the plugin hook into the X11 event handling via
+ GLX or GTK. Since Firefox uses GTK, so does Gnash. This also
+ allows the addition of a right-click mouse menu for controlling
+ the player. The GTK build of Gnash offers the best browsing
+ experience as it's more functional than the SDL version.
+ </para>
+
+ <para>
+ It is also possible to disable the <emphasis>GTK</emphasis> support so
+ only the older <emphasis>SDL</emphasis> support is used. In this case
+ Gnash can't support event handling within the browser. This
+ means that when using the SDL of the plugin, mouse clicks and
+ keys pressed get ignored. Windows also can't be resized, and
+ sometimes they overrun their boundaries as well. To disable the
+ GTK support and force SDL to be used anyway, configure with
+ <emphasis>--disable-glext</emphasis>
+ </para>
+
+ <para>
+
+ </para>
+
+ </sect5>
+</sect4>
Index: revisions.xml
===================================================================
RCS file: revisions.xml
diff -N revisions.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ revisions.xml 1 Mar 2008 15:04:43 -0000 1.1
@@ -0,0 +1,19 @@
+<revhistory>
+
+ <revision>
+ <revnumber>Gnash User Manual version 0.4</revnumber>
+ <date>Feb 2008</date>
+ <revdescription>
+ <para role="author">Rob Savoye
+ <email>address@hidden</email>
+ The end user parts of the manual have been pulled out of
+ the original version of the manual, and rewritten. This
+ is now a reference manual only.
+ </para>
+
+ <para role="publisher">Open Media Now! Foundation</para>
+ </revdescription>
+ </revision>
+
+</revhistory>
+
\ No newline at end of file
Index: rtmp.xml
===================================================================
RCS file: rtmp.xml
diff -N rtmp.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ rtmp.xml 1 Mar 2008 15:04:43 -0000 1.1
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="utf-8"?>
+<chapter id="rtmp">
+ <title>RTMP Protocol</title>
+
+ <para>
+ This document is based mostly on my own reverse engineering of the
+ RTMP protocol and AMF format. <emphasis>tcpdump</emphasis> and
+ <emphasis>ethereal</emphasis> are your friend. Some additional info that
got
+ me started was from the <ulink type="http"
+ url="http://www.osflash.org/red5">Red5</ulink>
+ project. <emphasis>Red5</emphasis> is the only other open source Flash
+ server. So some details are still vague, but as the implementation
+ appears to work, we'll figure out what they are later.
+ </para>
+
+ <para>
+ The Real Time Messaging Protocol was created by MacroMedia (now
+ Adobe) for delivering Flash objects and video over a network
+ connection. Currently the only servers which support this format
+ are the MacroMedia Media sever, and the Open Source Red5 project.
+ </para>
+
+ <para>
+ This is a simple protocol, optimized for poor bandwidth
+ connections. It can support up to 64 concurrent streams over the
+ same network connection. Part of each AMF packet header contains
+ the index number of the stream. A single RTMP message can contain
+ multiple AMF packets.
+ </para>
+
+ <para>
+ An RTMP connection uses Tcp/ip port 1935. It is also possible to
+ tunnel RTMP over an HTTP connection using port 80. Each AMF packet
+ is 128 bytes long except for streaming audio, which has 64 byte
+ packets.
+ </para>
+
+ <para>
+ The basics of the RTMP protocol are as follows. All communications
+ are initiated by the client.
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/rtmp.png"/>
+ </imageobject>
+ </mediaobject>
+ </para>
+
+ <para>
+ The client starts the RTMP connection by sending a single byte
+ with a value of 0x3. This byte is followed by a data block of 1536
+ bytes. The format if this data block is unknown, but it appears to
+ not be actually used by the protocol except as a handshake.
+ </para>
+
+ <para>
+ The server receives this packet, stores the 1536 byte data block,
+ and then send a single byte with the value of 0x3, followed by two
+ 1536 data blocks. The second data block is the full contents of
+ the original data block as sent by the client.
+ </para>
+
+ <para>
+ The client receives the 1536 byte data block, and if they match,
+ the connection is established. After the handshake process is
+ done, there are three other messages that the client sends to the
+ sever to start the data flowing.
+ </para>
+
+ <para>
+ The first AMF packet sent to the server contains the
+ <emphasis>connect</emphasis> packet. This doesn't appear to do
+ much but notify the server the client is happy with the
+ handshake, and ready to start reading packets.
+ </para>
+
+ <para>
+ The second packet is the <emphasis>NetConnection</emphasis> object from
+ the client. This ActionScript class is used by the Flash movie to
+ create the network connection to the server.
+ </para>
+
+ <para>
+ The third packet is the <emphasis>NetStream</emphasis> object from the
+ client. This is the ActionScript class used to specify the file to
+ be streamed by the server.
+ </para>
+
+ <para>
+ The RTMP packet for our example looks like this:
+
+ <programlisting>
+ 030000190000c91400000000020007connect00?f0000000000000030003app0200#
+ software/gnash/tests/1153948634.flv0008flashVer02000cLNX 6,0,82,0 0006
+ swfUrl02001dfile:///file|%2Ftmp%2Fout.swfc30005tcUrl\002\0004
+ rtmp://localhost/software/gnash/tests/1153948634.flv\000\000\t
+ \002\000\005userx
+ </programlisting>
+
+ We'll take this apart in a bit, but you can see how all three AMF
+ packets are in the same message. The message is received in
+ several 128 byte blocks, with the last one being less than
+ that. The total size of the RTMP message is in the header, so the
+ reader can tell if the entire message was read or not.
+ </para>
+
+ <para>
+ The RTMP header is first, followed by the connect message as an
+ ASCII string as the message body. The following AMF packet is the
+ <emphasis>NetConnection</emphasis> one, which specifies that this is coming
+ from a Flash application. This also contains the file path the server
+ can use to find the file to stream. This is then followed by the
+ version number, which I assume is the version of the Flash player,
+ so the server knows what it is talking to.
+ </para>
+
+ <para>
+ The third packet is the one from <emphasis>NetStream</emphasis>, which
+ specifies the URL used for the movie, followed by the user name
+ for a semblance of security.
+ </para>
+
+ <para>
+ For the next level of detail, we'll explain the format of AMF. AMF
+ is used by the RTMP protocol to transfer data. Each Flash object
+ is encapsulated in an AMF packet, including streaming audio or
+ video.
+ </para>
+
+ <para>
+ The first byte of the RTMP header determines two things about the
+ rest of the message. The first 2 bits of this byte signify the
+ total size of the RTMP header. The RTMP header is of a variable
+ size, so this is important.
+
+ <variablelist>
+ <varlistentry>
+ <term>00</term>
+ <listitem>
+ <para>
+ This specifies the header contains 12 bytes, including
+ this one.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>01</term>
+ <listitem>
+ <para>
+ This specifies the header contains 8 bytes, including this
+ one.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>02</term>
+ <listitem>
+ <para>
+ This specifies the header contains 4 bytes, including this
+ one.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>03</term>
+ <listitem>
+ <para>
+ This specifies the header contains 1 byte, so this is the
+ complete header.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ The other 6 bits in this byte represent the AMF index. As a single
+ RTMP connection can support multiple data streams, this signifies
+ which stream this packet is for. Once an AMF object is fully
+ received by the client, the AMF index may be reused.
+ </para>
+
+ <para>
+ For messages with headers of at least 4 bytes, the next 3 bytes are
+ used by audio and video data packets, but at this time the meaning
+ of this field is unknown.
+ </para>
+
+ <para>
+ For messages with a 8 byte or larger header, the next 3 bytes
+ determine the size of the RTMP message being transmitted. Messages
+ with a 1 byte or 4 byte header use a standard size, 128 bytes for
+ video, and 64 bytes for audio.
+ </para>
+
+ <para>
+ For messages with an 8 byte or larger header, the next byte is the
+ type of the AMF object.
+
+ <variablelist>
+ <varlistentry>
+ <term>0x3</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP packet is the
+ number of bytes read. This is used to start the RTMP
+ connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x4</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is a
+ <emphasis>ping</emphasis> packet.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x5</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is
+ server response of some type.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x6</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP packet is
+ client request of some type.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x8</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP packet is an
+ audio message.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x9</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is a
+ video packet.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x12</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is
+ notify.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x13</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is
+ shared object.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>0x14</term>
+ <listitem>
+ <para>
+ This specifies the content type of the RTMP message is
+ remote procedure call. This invokes the method of a Flash
+ class remotely.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+
+ <para>
+ There are two sets of data types to consider. One set is used by
+ the to specify the content type of the AMF object, the other is an
+ ActionScript data type tag used to denote which type of object is
+ being transferred.
+ </para>
+
+ <para>
+ The values of the initial type byte are:
+ <variablelist>
+
+ <varlistentry>
+ <term>0x0</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a numeric
+ value. All numeric values in Flash are 64 bit,
+ <emphasis>big-endian</emphasis>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x1</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a boolean
+ value.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x2</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is an
+ <emphasis>ASCII</emphasis> string.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x3</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a Flash
+ object. The Flash object data type field further along in
+ the message specifies which type of ActionScript object it
+ is.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x4</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a Flash
+ movie, ie. another Flash movie.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x5</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a NULL
+ value. NULL is often used as the return code from calling
+ Flash functions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x6</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a
+ undefined. This is also used as the return code from
+ calling Flash functions.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x7</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a reference.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x8</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a ECMA
+ array.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x9</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is the end of an
+ object definition. As an object is transmitted with
+ multiple AMF packets, this lets the server know when the
+ end of the object is reached.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>0xa</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a Strict
+ array.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0xb</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a date.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0xc</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a multi-byte
+ string. Multi-byte strings are used for international
+ language support to represent non <emphasis>ASCII</emphasis>
+ fonts.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0xd</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a an
+ unsupported feature.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0xe</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a record
+ set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0xf</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a AML
+ object. XML objects are then parsed by the
+ <emphasis>XML</emphasis> ActionScript class.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>0x10</term>
+ <listitem>
+ <para>
+ This specifies the data in the AMF packet is a typed object.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+
+ <para>
+ For messages with a 12 byte header, the last 4 bytes are the
+ routing of the message. If the destination is the server, this
+ value is the NetStream object source. If the destination is the
+ client, this is the NetStream object for this RTMP message. A
+ value of 0x00000000 appears to be reserved for the NetConnection
+ object.
+ </para>
+
+ <para>
+ Multiple AMF streams can be contained in a single RTMP messages,
+ so it's important to check the index of each AMF packet.
+ </para>
+
+ <para>
+ An example RTMP header might look like this. (spaces added between
+ fields for clarity) All the numbers are in hex.
+
+ <screen>
+ 03 000019 0000c9 14 000000000
+ </screen>
+
+ <variablelist>
+ <varlistentry>
+ <term>03</term>
+ <listitem>
+ <para>
+ The first two bits of this byte are the size of the
+ header, which in this example is 00, for a 12 byte
+ header. The next 6 bits is the AMF stream index number,
+ which in this example is 0x3.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>000019</term>
+ <listitem>
+ <para>
+ These 3 bytes currently have an unknown purpose.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>000c9</term>
+ <listitem>
+ <para>
+ Since this example has a 12 byte header, this is the size
+ of the RTMP message, in this case 201 bytes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>14</term>
+ <listitem>
+ <para>
+ This is the content type of the RTMP message, which in
+ this case is to invoke a remote function call. (which we
+ later see is the connect function).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>00000000</term>
+ <listitem>
+ <para>
+ The source is the NetConnection object used to start this
+ connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+
+ &amf;
+
+</chapter>
+
- [Gnash-commit] gnash/doc/C/usermanual/installation amf.xml as_...,
Rob Savoye <=