1. Summary
  2. Files
  3. Support
  4. Report Spam
  5. Create account
  6. Log in

Getting Lightspark

git clone git://github.com/alexp-sssup/lightspark.git

Getting started with development

Unfortunately there isn't much documentation available besides the comments and doxygen docs. The following describes a way that I have gotten into hacking on lightspark. This list does not need to be followed strictly, its purpose is to help out people that are interested in joining development but don't know where and how to start.

  • Read over a couple of functions in scripting/toplevel.cpp and make sure you look up each of the class declarations.
  • Pick some simple unimplemented functions in scripting/toplevel.cpp referring back to the AS reference
  • Keep reading and coding, you will eventually start getting used to the internal structures and flow of lightspark.
  • Do not be shy to ask any questions about the code.
  • Have fun! Once you get familiar with how toplevel is implemented, you can choose to keep implementing unimplemented functions, or follow what you're interested in.

Source Code Structure

  • backends - Contains code for interaction with the system: graphics, sound, networking and so on
    • decoder.{h,cpp} handles compressed video and audio decoding using FFMpeg
    • extscriptobject.{h,cpp} contains classes used to communicate between ActionScript? and the external host (e.g.: web browser using NPAPI) via the ExternalInterface? AS3 class. These classes are specialized by classes dependent on the external host (see plugin/npscriptobject.{h,cpp})
    • geometry.{h,cpp} handles conversion from shape data stored inside SWF to internal data format
    • graphics.{h,cpp} handled rendering of content to GL textures
    • input.{h,cpp]} input handling
    • netutils.{h,cpp} Code to handle downloading of data from the net using libCURL (when running in plugin mode lightspark uses the browser infrastructure to download data. See plugin/plugin.{h,cpp}
    • rendering.{h,cpp} blits all the content textures together to generate the final image
    • security.{h,cpp} contains code for handling and consulting cross domain policy files and deciding whether access to a given resource should be allowed, depending on the information found in those policy files.
    • urlutils.{h,cpp} contains code for parsing and creating URLs.
  • conf - CMake helpers to find some libraries in a (hopefully) cross platform way
  • debian - Debian packaging configuration
  • docs - Doxygen documentation will be built here
  • docs/man - Small man page for lightspark
  • media - Contains icons
  • parsing - Code to parse SWF, FLV and AMF3 data
  • platforms - Platform specific code
  • plugin - contains Netscape Plugin API (de facto standard for everything beside Microsoft IE) related files
    • npscriptobject.{h,cpp} contains classes specializing those in backends/extscriptobject.{h,cpp}. These classes provide the link between ActionScript? and Javascript via NPAPI.
    • plugin.{h,cpp} contains code working with NPAPI for both downloading of data (specializing classes found in backends/netutils.{h,cpp}) and for starting and stopping a new plugin instance.
    • npn_gate.cpp and npp_gate.cpp contain the glue for using NPAPI functions.
  • scripting - contains support for the ActionScript 3 runtime
  • scripts - contains some useful scripts. (E.g.: youtube args dumper so you can play youtube's videos in the standalone player)
  • tests - contains tests for particular actionscript features (see "Running tests" below)

Implementing ActionScript features

Anatomy of an AS3 class

class Shape: public DisplayObject
{
public:
        Shape(){}
        static void sinit(Class_base* c);
        static void buildTraits(ASObject* o);
        ASFUNCTION(_constructor);
        ...
};

Builtin classes provided by ActionScript must be implemented in the source file corresponding to the namespace of the class: scripting/flashdisplay.cpp for flash.display.Shape class for example. Classes in the toplevel namespace are implemented in scripting/toplevel.cpp.

class Shape: public DisplayObject

The inheritance tree of the C++ classes should mimic the one of the AS classes. So as flash.display.Shape derives from flash.display.DisplayObject then class Shape derives from DisplayObject.

Shape(){}

Each C++ class must have a valid constructor with no argument. Other constructors may be added if needed

static void sinit(Class_base* c)
{
        c->setConstructor(Class<IFunction>::getFunction(_constructor));
        c->super=Class<DisplayObjectContainer>::getClass();
        c->max_level=c->super->max_level+1;
        c->setGetterByQName("graphics","",Class<IFunction>::getFunction(_getGraphics),true);
}

This functions must be present in every class. It must create class properties for the ActionScript class. The method also must correctly set the super class and the level (depth in the inheritance tree). Each method (including getters and setters) must be added to the class, even non-static ones. Non static methods that are added to the class are considered borrowed. This is an optimization, as every instance of a class have the same methods is a waste of time to create all the function objects at instance construction time. When using set{Method,Getter,Setter}ByQName the fourth parameter tells if the method is borrowed or not.

static void buildTraits(ASObject* o);

This function has a similar purpose to sinit but is intended to create instance properties.

ASFUNCTION(_constructor);

The ASFUNCTION macro creates a function with the right signature to be called by AS code.

REGISTER_CLASS_NAME(Shape);

This macro must be called somewhere in the beginning of the relevant cpp file. It's used to automatically register classes.

in scripting/abc.cpp
void ABCVm::registerClasses()
{
        ...
        builtin->setVariableByQName("Shape","",Class<Shape>::getClass());
        ...
}

Last but not least the new shiny class must be added to the global namespace in the ABCVm::registerClasses method.

Anatomy of a AS3 function

ASFUNCTIONBODY(Foo,bar)
{
        Foo* th=Class<Foo>::cast(obj);
        ASObject* ret=NULL;
        if(argslen>=1)
        {
                ret=args[0];
                ret->incRef();
        }
        else
                ret=new Undefined;

        return ret;
}

This function implements the Foo::bar method. Hidden in the ASFUNCTIOBODY macro there is a signature with three parameters:

  • obj It's the equivalent of the this pointer for C++ methods. It's a pointer to the object instance this method works on.
  • args An array of pointers to ASObject. Those are the arguments of the function
  • argslen The length of the array.

Lightspark employs reference counting to determine when to destroy objects. Arguments are decRefed (their reference count is decreased by one) automatically at the end of each function. This means that the method is expected to incRef them if they are supposed to survive (for example if one of the arguments is stored inside the object or it's returned like in the code above)


Status

The following classes are completed.

  • Math in toplevel

Logging Levels

  • 0 is less
  • 1 is errors
  • 2 is not implemented
  • 3 is calls, and print a detailed log of opcodes and function called
  • 4 is trace (usually too much)

The default for the standalone player is 2.
The default for the plugin is 1.
To change the logging level of the plugin, you need to edit initLogging call in plugin/plugin.cpp


References


Running tests

Tests are compiled using the Flex 4 SDK and run with the standalone player. You can get the Flex 4 SDK here.

Flex 4 SDK is assumed to be installed in $FLEX_ROOT Make sure that <omit-trace-statements>false</omit-trace-statements> is set to false in $FLEX_ROOT/frameworks/flex-config.xml

To compile tests inside the tests/ directory use the following command: $FLEX_ROOT/bin/mxmlc -static-link-runtime-shared-libraries test.mxml -output test.swf