• SoftwareFaust
  • My experience with Faust, and some more general observations

Yes, I'll try to dig into that. Have enough time at the moment.

@sletz suggests:

We already have a « server a web-based GUI to the user » model. On server side we use libmicrohttpd (https://www.gnu.org/software/libmicrohttpd/) to have the Web server running, wrapping/controlling the running DSP, delivering a HTML + SVG + CSS page to the browser. Then messages are sent/received using HTTP requests (which is a bit heavy but works…) This could be a starting point, possibly using OSC an an alternate protocol later on.

You can see this HTML + SVG + CSS code used in another context here : http://faust.grame.fr/modules/. In this case we just generated static pages, but you can see the kind of UI we get.

To activate HTTP UI control you will have to follow what is done in other architecture files, like : https://github.com/grame-cncm/faust/blob/master-dev/architecture/jack-qt.cpp

So adding in the bela.cpp template file:

#include "faust/gui/httpdUI.h"

 httpdUI httpdinterface(name, fDSP.getNumInputs(), fDSP.getNumOutputs(), argc, argv);
 fDSP.buildUserInterface(&httpdinterface);
 ...
httpdinterface.run(); 

Then you'll have to compile the code in faust source tree: /architecture/httpdlib and link also with libmicrohttpd (https://www.gnu.org/software/libmicrohttpd/)

Then starting the program will start a libmicrohttpd based server at http://127.0.0.1:5510, that should display the UI to control the DSP running on the Bela card.

A bit of work but not impossible...

Do you mean render.cpp (instead of bela.cpp)?
I found a gem: if (p == '.' | p == ',') (really?) ;-)

So, I got the /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so, how do I have to link this to the bela project?
(I guess, I have to change the Makefile, but what will be the code for including the shared lib)?

    I finally got around adding the so file, but now I'm lost (again):
    /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to jsscripts_len'
    /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to
    stylesheet_len'
    /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to stylesheet'
    /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so: undefined reference to
    jsscripts'

    This variables are defined as 'extern', but in what library?
    This is the line in Makefile, I'm using:
    LDFLAGS += $(DEFAULT_XENOMAI_LDFLAGS) -Llib/ -lasound -lsndfile -lseasocks -L/root/faust/architecture/httpdlib/ -lHTTPDFaust /root/faust/architecture/httpdlib/cmake/libHTTPDFaust.so

    It may be that they are referenced here?
    https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp#L122-L144

    It seems that if you #define LOADSCRIPTS then a number of external .js and .css files are loaded, but if you don't, you should have in your code some variables stylesheet_len, stylesheet, jsscripts, jsscripts_len which should point to some appropriate scripts (which you are probably supposed to provide yourself?).

    I'd recommend you #define LOADSCRIPTS at the top of that file and try to rebuild and see what happens.

    DragonSF Do you mean render.cpp (instead of bela.cpp)?

    The render.cpp that is in the bela-faust-jit repo is based on the bela.cpp that you find in the FAUST repo. The former allows dynamic loading and just-in-time compilation of FAUST code, while the latter is meant to be used with some FAUST-generated C++ code. The GUI/libmicrohttpd issue you are facing now should be independent of which of the two you use.

    (remember that to get that render.cpp to work with the latest FAUST you'd need this I think:

    giuliomoro Perhaps just adding virtual void addSoundfile(const char label, const char filename, Soundfile** sf_zone) {} inside class BelaUI : public UI would have fixed this.

    )

    Your adviced worked so far, that I can link and run the application:
    Faust httpd server version 0.73 is running on TCP port 5510
    But when I try to connect, I'm getting: Unable to connect. Strange.
    When I use the 'ss' command, I can't see any app listen to port 5510.

    What address are you trying to connect to?

    Maybe try curl from the board itself? like curl localhost:5510 or try telnet localhost 5510 then from the host telnet 192.168.7.2 5510

      using strace:
      open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 10
      fstat64(10, {st_mode=S_IFREG|0644, st_size=124, ...}) = 0
      read(10, "127.0.0.1\tlocalhost\n127.0.1.1\tbe"..., 4096) = 124
      read(10, "", 4096) = 0
      close(10) = 0
      socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 10
      setsockopt(10, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
      bind(10, {sa_family=AF_INET, sin_port=htons(5510), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
      listen(10, 128) = 0
      fcntl64(10, F_GETFL) = 0x2 (flags O_RDWR)
      fcntl64(10, F_SETFL, O_RDWR|O_NONBLOCK) = 0
      mmap2(NULL, 8388608, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0xb5282000
      mprotect(0xb5282000, 4096, PROT_NONE) = 0
      clone(child_stack=0xb5a80f88, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb5a814b8, tls=0xb5a81910, child_tidptr=0xb5a814b8) = 5768
      fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
      write(1, "Faust httpd server version 0.73 "..., 60Faust httpd server version 0.73 is running on TCP port 5510
      ) = 60
      shutdown(10, SHUT_RDWR) = 0
      close(10) = 0
      Doesn't seem correct to me.

      giuliomoro I tried taht, no avail. No process is listen at port 5510.
      root@bela:~/Bela/projects/nfaust# Faust httpd server version 0.73 is running on TCP port 5510
      curl localhost:5510
      curl: (7) Failed to connect to localhost port 5510: Connection refused
      same with local telnet:
      root@bela:~/Bela/projects/nfaust# telnet localhost 5510
      Trying ::1...
      Trying 127.0.0.1...
      telnet: Unable to connect to remote host: Connection refused

      Yeah it seems the socket gets shutdown.
      Maybe HTTPDControler::stop() is being called somewhere? Is your httpdUI object global? I guess if it goes out of scope, the destructor is called and the server is killed.

      That's an idea. I'll try that.
      Yes, that was the reason. Now I see something, but not as expected. I'll come back tomorrow.
      ATM the page source is:

      <html>
        <head>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquery-1.7.1.min.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquerysvg/jquery.svg.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/jquerysvg/jquery.svgdom.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_proto.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_jquery_svg_backend.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_mobile.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_inits.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_load_external_file.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_objects.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_builder.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_ui_interact.js"></script>
          <script type="text/javascript" src="http://www.mikesolomon.org/faust/svg/faust_server_communication.js"></script>
          <link rel="stylesheet" type="text/css" href="http://www.mikesolomon.org/faust/svg/faust_css.css"></link>
        </head>
        <body>
          <script type="text/javascript">
            _f4u$t.server_update_function = _f4u$t.main('{  "name": "bela render",  "address": "127.0.1.1",  "port": "5510",  "inputs": "0",  "outputs": "2",  "ui": [   {    "type": "vgroup",    "label": "WaveGuide_Sitar",    "items": [     {      "type": "vgroup",      "label": "Physical_Parameters",      "items": [       {        "type": "hslider",        "label": "Resonance",        "address": "/WaveGuide_Sitar/Physical_Parameters/Resonance",        "meta": [          { "2": ""},         { "tooltip": "A value between 0 and 1"}        ],        "init": "0.7",        "min": "0",        "max": "1",        "step": "0.01"       }      ]     },     {      "type": "hgroup",      "label": "Reverb",      "meta": [        { "3": ""}      ],      "items": [       {        "type": "hgroup",        "label": "Freeverb",        "items": [         {          "type": "vgroup",          "label": "0x00",          "meta": [            { "0": ""}          ],          "items": [           {            "type": "vslider",            "label": "Damp",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/Damp",            "meta": [              { "0": ""},             { "style": "knob"},             { "tooltip": "Somehow control the   density of the reverb."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.025"           },           {            "type": "vslider",            "label": "RoomSize",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/RoomSize",            "meta": [              { "1": ""},             { "style": "knob"},             { "tooltip": "The room size   between 0 and 1 with 1 for the largest room."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.025"           },           {            "type": "vslider",            "label": "Stereo_Spread",            "address": "/WaveGuide_Sitar/Reverb/Freeverb/0x00/Stereo_Spread",            "meta": [              { "2": ""},             { "style": "knob"},             { "tooltip": "Spatial   spread between 0 and 1 with 1 for maximum spread."}            ],            "init": "0.5",            "min": "0",            "max": "1",            "step": "0.01"           }          ]         },         {          "type": "vslider",          "label": "Wet",          "address": "/WaveGuide_Sitar/Reverb/Freeverb/Wet",          "meta": [            { "1": ""},           { "tooltip": "The amount of reverb applied to the signal   between 0 and 1 with 1 for the maximum amount of reverb."}          ],          "init": "0.3333",          "min": "0",          "max": "1",          "step": "0.025"         }        ]       }      ]     },     {      "type": "vgroup",      "label": "Spat",      "items": [       {        "type": "hslider",        "label": "pan_angle",        "address": "/WaveGuide_Sitar/Spat/pan_angle",        "init": "0.6",        "min": "0",        "max": "1",        "step": "0.01"       },       {        "type": "hslider",        "label": "spatial_width",        "address": "/WaveGuide_Sitar/Spat/spatial_width",        "init": "0.5",        "min": "0",        "max": "1",        "step": "0.01"       }      ]     },     {      "type": "hslider",      "label": "ON_OFF_(ASR_Envelope)",      "address": "/WaveGuide_Sitar/ON_OFF_(ASR_Envelope)",      "meta": [        { "0": ""},       { "BELA": "ANALOG_0"}      ],      "init": "0",      "min": "0",      "max": "1",      "step": "1"     },     {      "type": "hslider",      "label": "Frequency",      "address": "/WaveGuide_Sitar/Frequency",      "meta": [        { "1": ""},       { "BELA": "ANALOG_0"}      ],      "init": "440",      "min": "460",      "max": "1500",      "step": "1"     },     {      "type": "hslider",      "label": "Pressure",      "address": "/WaveGuide_Sitar/Pressure",      "meta": [        { "2": ""},       { "BELA": "ANALOG_4"},       { "style": "knob"}      ],      "init": "0.96",      "min": "0.2",      "max": "2",      "step": "0.01"     }    ]   }  ] } ', null, _f4u$t.faust_server_handler);
          </script>
        </body>
      </html> 

      Looks like the function f4u$t.server_update_function should do the work, but it doesn't seem to be called anywhere.
      I'm missing the link between JSON code (which seems to OK) and the final HTML code for the UI (which is missing).

      I debugged the webpage and found this:

       _f4u$t.server_update_function = _f4u$t.main(...);
      -> 
      var URLParams = _f4u$t.parseURLParams(document.URL);
      ->
       if (query === url || query === "") return;

      query and url are both "http://192.168.7.2:5510/"
      in that case:

        if (URLParams) {
       ...
       }
        else {
          _f4u$t.make_ui(svg, raw_json);

      raw_json is null and therefore to ui.
      Please advise.

      Please use Markdown to format your posts in order to make them more comprehensible. In particular, use lines with ``` to surround blocks of code (see my edits above to your latest posts).

      it looks like the _f4u$t.main() call is passing a json as first argument, while the _f4u$t.main() definition in http://www.mikesolomon.org/faust/svg/faust_proto.js expects function(svg, raw_json), so it seems that there is a mismatch there between the two files.

      The faust_proto.jsin faust/architecture/httpdlib/html/js/svg/faust_proto.js instead seems to accept the same arguments that are passed in the html file, so you should probably use this instead of the mikesolomon one. In order to use this you probably have to remove the #define LOADSCRIPTS line you added in https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp following my above suggestion and probably you will have to declare stylesheet_len, stylesheet, jsscripts, jsscripts_len in your .cpp file instead. They are declared as

      // in faust/architecture/httpdlib//src/html/stylesheet.h
      extern unsigned char stylesheet[];
      extern unsigned int  stylesheet_len;
      // in faust/architecture/httpdlib//src/html/jsscripts.h
      extern unsigned char jsscripts[];
      extern unsigned int  jsscripts_len;

      Judging by the way they are being parsed in https://github.com/grame-cncm/faust/blob/master-dev/architecture/httpdlib/src/html/htmlpage.cpp, these should be char[] which should contain actual css and js code. I have no idea how you would generate that.

      So here is another trick: change the generated html (or even better the faust/architecture/httpdlib/src/html/htmlpage.cpp file) so that it does not use those remote URLs but the local files with the same name provided by faust in faust/architecture/httpdlib/html/js/svg/. The relative paths to the files will depend on where the root of the http server is. Something like this may work, or try changing the prefix to svg/...

        <script type="text/javascript" src="js/svg/jquery-1.7.1.min.js"></script>
          <script type="text/javascript" src="js/svg/jquerysvg/jquery.svg.js"></script>
          <script type="text/javascript" src="js/svg/jquerysvg/jquery.svgdom.js"></script>
          <script type="text/javascript" src="js/svg/faust_proto.js"></script>
          <script type="text/javascript" src="js/svg/faust_jquery_svg_backend.js"></script>
          <script type="text/javascript" src="js/svg/faust_mobile.js"></script>
          <script type="text/javascript" src="js/svg/faust_ui_inits.js"></script>
          <script type="text/javascript" src="js/svg/faust_load_external_file.js"></script>
          <script type="text/javascript" src="js/svg/faust_ui_objects.js"></script>
          <script type="text/javascript" src="js/svg/faust_ui_builder.js"></script>

      with your html file appropriately placed in a local http server, the above works for me and I get displayed a GUI (no idea if the backend communication works though).

      Thanks a lot. I&ll take care of that (had the same idea about local scripts). And sorry about not correctly formatted code. I'll try to get better.

      So far so good, the local js storage is working now and also the parameters are fine (raw_json is correct). But now I'm only getting a black background. Reason:
      these lines in faust_proto.js:

          if (callback) {
              _f4u$t.HANDLER_CALLBACKS.push(function(address, value) {
                                            if (_f4u$t.first_part_matches(address, hash)) {
                                            return callback(_f4u$t.remove_from_head_of_string(address, hash), value);
                                            }
                                            });
          }

      prevent the building of the svg controls.
      When commented,the page shows the svg controls. But no callback action.

      alt text

      I have no idea what svg is supposed to appear there, but given that the call to _f4u$t.main passes null as the svg argument, I am not sure I would expect anything different really!