Using Flash Workers in Haxe

216 views
Skip to first unread message

Daniel Kuschny

unread,
Feb 3, 2014, 12:11:13 PM2/3/14
to haxe...@googlegroups.com
Hi everybody. 

I am currently working on a Flash Midi Synthesizer. Synthesizing the audio directly in the SampleDataEvent.SAMPLE_DATA makes this the audio as hell (and the playback is too fast) http://alphatab.net/alphasynth/
So I thought of using Flash Workers (11.4) to generate the audio side-by-side with the playback. But I can't get the Flash Workers running using Haxe. For some reason the loaderInfo of my sprite is null which raises an error when creating my worker. 
Here's the code of my main player class. I cleaned the code a bit to focus on the main problem:

static function main()
{
    ...
    trace('Initializing synthsizer');
    _player = new SynthPlayer();
    trace('Done');
}

class SynthPlayer extends Sprite
{
    public function new() 
    {
        super();
        if (Worker.current.isPrimordial)
        {
            startPlayer();
        }
        else
        {
            startGenerator();
        }
    }
    
    /* Player */
    private var _generator:Worker;
    private var _playerToGenerator:MessageChannel;
    private var _generatorToPlayer:MessageChannel;
    
    ... 
    
    private function startPlayer()
    {
        trace('starting player');
        
        trace('initializing generator worker');
        trace(loaderInfo); // null
        trace(loaderInfo.bytes);
        _generator = WorkerDomain.current.createWorker(loaderInfo.bytes);
        
        _playerToGenerator = Worker.current.createMessageChannel(_generator);
        _generator.setSharedProperty("playerToGenerator", _playerToGenerator);
        
        _generatorToPlayer = Worker.current.createMessageChannel(Worker.current);
        _generatorToPlayer.addEventListener(Event.CHANNEL_MESSAGE, generatorToPlayerMessage);
        _generator.setSharedProperty("generatorToPlayer", _generatorToPlayer);
        
        trace('initializing audio');
        ...
        
        trace('starting generator worker');
        _generator.start();
    }
    
    ...
    
    /* Generator Part */

    public function startGenerator()
    {
        trace('initializing generator');
        _generatorToPlayer = Worker.current.getSharedProperty("generatorToPlayer");
        _playerToGenerator = Worker.current.getSharedProperty("playerToGenerator");
        _playerToGenerator.removeEventListener(Event.CHANNEL_MESSAGE, playerToGeneratorMessage);
        
        trace('opening synthesizer');
        ...
    }
       
    ...
}

Do I need to create my sprite in some special way to ensure the loaderInfo is available? I couldn't find any sample source for Flash Workers in Haxe. 



Motoshi Kamiya

unread,
Feb 11, 2014, 8:22:45 AM2/11/14
to haxe...@googlegroups.com
Hi,

Flash Worker works in Haxe.
The loaderInfo you need is not the instance of Sprite class, but is the loaderInfo of the root display object. Try to use flash.Lib.current.loaderInfo, which is the loaderInfo of the root display object, instead.

See also following sample code for Flash Worker, it would help you.
It works fine both in Linux(Chrome) and Windows.

import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.system.MessageChannel;
import flash.events.Event;
import flash.utils.ByteArray;

class Hoge {
  public var piyo:String;
  public function new() {
    piyo = "foobar";
  }
}

class Main {
  static public var _this:Main;
  static public function main() {
    _this = new Main();
  }
  // ########################################################################
  private var channel:MessageChannel;
  private function new() {
    if ( Worker.current.isPrimordial ) {
      var wk = WorkerDomain.current.createWorker( flash.Lib.current.loaderInfo.bytes );
      trace( flash.Lib.current.loaderInfo ); // Main.hx:24: [object LoaderInfo]
      channel = wk.createMessageChannel( Worker.current );
      wk.setSharedProperty( "channel", channel );
      channel.addEventListener( Event.CHANNEL_MESSAGE, receiveMessage );
      wk.start();
      trace( "primordial" ); // Main.hx:29:primordial
    } else {
      channel = Worker.current.getSharedProperty( "channel" );
      trace( "worker" ); // not displayed
      haxe.remoting.AMFConnection.registerClassAlias( "Hoge", Hoge );
      var ba:ByteArray = new ByteArray();
      ba.writeObject( new Hoge() );
      channel.send( ba );
    }
  }

  private function receiveMessage( e:Event ) {
    var ba:ByteArray = channel.receive();
    haxe.remoting.AMFConnection.registerClassAlias( "Hoge", Hoge );
    var message:Hoge = ba.readObject();
    trace( message.piyo ); // Main.hx:44:foobar
  }
}

2014年2月4日火曜日 2時11分13秒 UTC+9 Daniel Kuschny:

Daniel Kuschny

unread,
Feb 14, 2014, 6:59:53 AM2/14/14
to haxe...@googlegroups.com
Hi there. 

I finally got the workers running using those resources

But it seems within the domain of the worker the Haxe environment is not initialized. For example: The Math.isNaN method is null. Is there some way to tell Haxe to run all __init__ Methods? 

Tom

unread,
Feb 14, 2014, 9:05:28 AM2/14/14
to haxe...@googlegroups.com
Hi!

If I am not mistaken, Your used class is create a new, standard (not Haxed) swf from the given class, and load it, as a worker.
So this is not Haxed, ergo there are no any Haxe enviroment in there, I think.

Daniel Kuschny

unread,
Feb 14, 2014, 9:13:23 AM2/14/14
to haxe...@googlegroups.com
Yes,there's no Haxe Environment and this is exactly my problem what I try to solve now. As far as I know the __init__() method bodies are copied directly into to bootstrap sequence, they are not compiled to the class. If they would be compiled as well, I could use a macro to call __init__ methods. But maybe there's a way to call the Haxe bootstrapping?

Tom

unread,
Feb 14, 2014, 9:24:49 AM2/14/14
to haxe...@googlegroups.com
I don't know, if this possible in this way, because you need to copy the __init__() methods bytecode into the worker class via format lib, and I have no idea now, how.
Maybe you need to modify the HxWorker class, to find the appropriate Boot class too, and write into the worker.swf.

Daniel Kuschny

unread,
Feb 14, 2014, 9:34:13 AM2/14/14
to haxe...@googlegroups.com
The worker has access to all Haxe classes, it's not only a separate copy of the Worker class. The class given to the HxWorker is the entry point/sprite of the new worker. 
If I'm not wrong the inits and boot class are generated here: https://github.com/HaxeFoundation/haxe/blob/development/genswf.ml#L782
I'm currently researching if this generated code can be called somehow.Maybe there's some global function or classname which I can use. 
Reply all
Reply to author
Forward
0 new messages