Development Guide

Rafael Norman Saucedo Delgado edited this page Mar 1, 2015 · 2 revisions

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/toplevel.cpp and make sure you look up each of the class declarations.
  • Pick some simple unimplemented functions in scripting/toplevel/toplevel.cpp referring back to the Action Script (AS) reference: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/
  • 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
{
private:
    Shape(){}
    static void sinit(Class_base* c);
    static void buildTraits(ASObject* o);
    ASFUNCTION(_constructor);
    ASFUNCTION(someMethod);
    ASPROPERTY_GETTER(number_t, someGettableProperty);
    ASPROPERTY_GETTER_SETTER(_NR<ASObject>, someGetSetProperty);
    ...
};

Builtin classes provided by ActionScript must be implemented in the source file corresponding to the namespace of the class: scripting/flash/display/flashdisplay.cpp for flash.display.Shape class for example. Classes in the toplevel namespace are implemented in scripting/toplevel/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->setSuper(Class<DisplayObjectContainer>::getRef());
    c->setDeclaredMethodByQName("someMethod","",Class<IFunction>::getFunction(someMethod),NORMAL_METHOD,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. 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 setDeclaredMethodByQName the fifth 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::getRef()); ... }

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

/* declare Foo.bar(n:Number, i:Integer = 1, o:Object = null) */
ASFUNCTIONBODY(Foo,bar)
{
    Foo* th=obj->as<Foo>()
    number_t n;
    int32_t i;
    _NR<ASObject> o;
    ARGS_UNPACK (n) (i,1) (o,_MNR(new Null));
    if(n > i)
        return abstract_b(true);
    else
    {
        o->incRef();
        return o.getPtr();
    }
}

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. Use the ARGS_UNPACK macro where possible to take care of argument handling. It also handles implicit type conversion and throws the right errors if necessary. It unpacks the arguments into the given types. The second parameter gives the default values. It uses the following mapping between AS types and C++ types: number_t <-> Number int <-> int32_t uint <-> uint32_t bool <-> Boolean tiny_string <-> String _NR <-> SomeClass (e.g. ASObject, Array, DisplayObject, etc.)

The function needs to return a pointer to an ASObject*. If you use objects passed in as parameters, they have to be incRef()'ed first, because all parameters are decRef() after the function returns. If you want to return a primitive type, use conversion functions: ASObject* abstract_b(bool) ASObject* abstract_i(int32_t) ASObject* abstract_ui(uint32_t) ASObject* abstract_d(number_t)

You can also create new objects as the would be created by the AS3 expression (o = new SomeClass()) through ASObject* o = Class::getInstanceS().

References

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.