Howl - Self Contained Build Environment for OWL

Im building a self contained build environment with Docker for Owl. Ill be posting my thoughts and my progress here and announcing whenever it is ready for testing.

My idea is to be able to eventually run something like
$ howl-build --type cpp MyPatch.cpp
or
$ howl-build --type faust --run MyPatch.dsp
etc.

Feature Ideas:

  • Docker image that can be built via Docker file (could later be deployed to docker hub once stable)
  • Run Howl image to generate howl-build helper script
  • Use howl-build to compile patches and run on OWL from CLI easily (script wraps more complicated make target and arguments)
  • Support for c++, faust, pd and gen patches
  • All build dependencies committed to image and pre-built, no installation necessary
  • Update/Rebuild build dependencies and tools via howl-build script handle (i.e. $ howl-build --update-all): merges source updates, rebuilds everything and commits to image

Be interesting to hear your thought and Im hoping for feedback, help and advice along the way.

Cheers,

3 Likes

Before i start configuring anything with Docker I needed to make sure I can compile with OwlProgram:

Prereqs:

  • Build OwlControl (for remote control access for checking settings and removing annoying noise issue)
  • Build FIrmwareSender

Notes:

  • Some JUCE settings didn’t work out of the box, had to adjust some pahs
  • FirmwareSender only works in Debug build config for me. There is an issue when opening a midi out device with JUCE, which only happens in release mode. Strangely enough OwlControl uses the same method to open a midi out device but it works fine in the binary release and when I build it locally in Xcode. Ideas??

Now on to testing polyglot build/deploys:

  • Created simple gain patches in all languages to minimize issues during compilation
  • cpp: works well, deployment works, running works
  • faust: work well for simple gain test patch, compilation and deployment works but most of the faust patches i tested that were in the OwlPatches repo did not run on Owl. Instead the LED went red after uploading patch.bin. Ideas??
  • pd: used uploader script and enzien audio heavy account/project: works fine, one needs to create an auth token for this to work but my example patch was compiled with heavy and then deployed and ran fine
  • gen: did not work, currently there is an issue where the trunc() function in cmath.h within the gcc-arm SDK is shadowed by trunc() in genlib_ops.h . Maybe Id have to change some compile flags to avoid double declarations here? Any ideas?? How do you do this online?

So, so far I’m not unhappy with these results! My next steps will be devising the best way to create a way to configure a docker image properly with all the necessary packages… this will require using a linux image so it might also entail rearranging some build project files to make this work with linux. Havent thought about this in detail yet. Open to any ideas and advice! Ill keep posting my progress here.

Later,

2 Likes

Awesome!

What version of the gcc crosscompiler are you using? What version FAUST?
It’s strange that the FAUST patches compile but then don’t run. Do you get an error message from the device if you connect OwlControl?
The gen failures are probably down to using a different gcc version from us. I’m currently on GCC 7.2.1 and FAUST 2.5.16 on my dev machine, but GCC 5.4.1 and FAUST 0.12.0 on live.

I’ve not used Docker, obviously now I’ll have to try it out :grin:

Keep us posted!

Hey, cheers for your response! I appreciate any help I can get along the way.

Heres some version info:
arm-gcc: arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1
faust: FAUST, DSP to C++ compiler, Version 0.10.6

It might be worth trying to install the versions you are using on live… Ill try that once I get a chance.
I agree on the FAUST issues being strange… Maybe we could mirror the live (stable) versions in Howl instead of more experimental setup with newest arm-gcc and faust 2… dunno yet.

Actually, I just tried to rebuild a few FAUST .dsp patches and now it seems to work… I noticed that if I don’t clean the PatchSource/ directory i might end up producing mucked up code, since the compile process places owl.h in there and make clean doesnt clean that file in the process. Maybe worth noting that for a future change to the make clean rule. Also, it seems all the .dsp’s i tested work except for SmoothDelay.dsp which happened to be what i tested initially :smiley: . I get a red LED with that patch after uploading to the modular and OwlControl doesnt really give me any info on what might be going wrong… I do notice there is no audio at all, so it seems no dsp process is actually running on the device.

I just installed Docker for Mac OS… the now support Hyperkit on new Intel Hypervisors instead of using Docker toolbox with VirtualBox, so I think I dont have to sweat getting Howl to run for Mac/Linux people. I havent looked into Windows but maybe someone can test that when the time has come.

By the way what dev/debugging setup do you run locally for FW development? Would be interesting to get some more insight into the Firmware along the way. :slight_smile:

Talk soon,
Ben

So here’s a new quick update on howl and what I’ve got so far:

  • Dockerfile to bootstrap a docker image with all the build-essentials needed to build owl program and firmwaresender and install the arm toolchain in the image
  • running a container based on an image built with the Dockerfile will generate the howl helper script that you can use for local compilation with the image.

So basically you can do this:

build a howl container

$ docker build howl-container .

run the container to generate howl helper script somewhere in path

$ docker run howl-container > ~/bin/howl

make it executable

$ chmod +x howl

run it to get some help on config options for patch compilation

$ howl helpconfig
INFO: Checking for built-in command: “helpconfig”
usage: howl --configoption [config setting] [image command line]
usage: howl – [image command line]

By default, sets config parameters and then runs the given command line in a howl container.

Builtin config options:
cpp-patch: set name of cpp patch
pd-patch: set name of pd patch
faust-patch: set name of faust patch
gen-patch: set name of gen patch

For config-option-specific help: howl helpconfig
For command-specific help: howl help

“howl” helper is used to call make in the container. The skeleton architecture works and i can “$ howl bash” into the container and see everything is installed properly.

Next steps:

  1. Build OwProgram ad FirmwareSender in the container and install the binaries (we could also make versioned binary packages to install directly with the container in future)
  2. Test crosscompilation/deploy with howl (hoping deploy will also work, no idea how well juce libraries will run in the container, hoping that will go well)

If all goes well you should run it like this

call make cpp patch GainPatch.hpp, deploy .bin and run on OWL

$ howl --cpp-patch Gain run

I am working on this in my free time and only really have one day a week i can properly focus on it, so sorry for the slow progress but within the next 2-3 weeks i should have something worth testing on github.

If you have any further ideas or thoughts on this let me know, I am excited to see this in action.

Cheers all!

1 Like

This sounds great. Let me know when you have something testable, I’ll be happy to put some effort in to it.

Quick status update:

Currently on holidays but had a bit of time in between activities to continue with Howl.

  • Installed a software-packages directory that can be mounted to build FirmwareSender
  • Dependencies JUCE (modules only) and FRUT installed to software-packages, FRUT makes it possible to easily convert JUCE projects into cmake projects and compile them in the container
  • Migrated container os from debian jessie to debian stretch (needed Cmake 3.4)

Next steps:

  • Test FirmwareSender from container (check if midi sysex upload works)
  • Install owl program dependency
  • Run compilation for patch target
  • Implement / Test c++ patch compilation/deployment

If this works, then support for pd, Faust and gen should just be a matter of time, hopefully.

Catch y’all later!
Cheers,
Ben

1 Like

Sooo… i’ve run into the first setback…

FirmwareSender requires native OS midi support to run. On Mac thats CoreMidi and on Linux its Alsa Midi. What I didnt know until a few days ago is that Mac OS (apparently other BSDish Linux’ too) dont run with architectures that provide /dev/snd in the devices fs. This prevents The JUCE native code to run something like listing midi io devices. :frowning:

Soo without being able to map /dev/snd into the container Docker could be a dead end for Howl on Mac. I still have to test this on a Linux box… running Linux this issue should not be a problem as we can run docker run --device /dev/snd ....

Im evaluating some VM based alternatives for Mac (I would like this to run on Mac of course…), but if any of you has any ideas regarding the Docker issue in the meantime, let me know!!

More soon…

Cheers,

I have migrated howl from being containerized with Docker to running on a vm using Vagrant.

Why?

  • JUCE requires native audio support (OwlProgram’s FirmwareSender tool requires JUCE device modules for midi) which in term does not work for all platforms when runing in a container
  • Virtual Machines can be customized to virtualize audio devices and can be provisioned with the native audio driver layer (e.g. ALSA, CoreAudio) so that JUCE device modules can be used properly

What changed?

  • You have one more dependency than when running docker :frowning: : you need a hypervisor (I’m running virtualbox)
  • Instead of containerization with Docker Vagrant is used to build a VM running the sandboxed OwlProgram build environment: https://www.vagrantup.com/

Will there still be a handy helper script that can be used to compile my awesome patch?

  • TLDR: yes
  • Long Story: Currently you need to install vagrant and then run an install script that brings up your virtual machine. After that the help script howl can be installed in your PATH and be used as intended and described in my posts above (the helper script it will ssh into the vm and run patch compilation from within a shared folder between you box and the vm so you dont have to worry about the complexity of that your self).

Current Status:

  • /dev/snd issues are resolved now: I virtualized the audio hardware for the vm and got the daily alsa daily build kernel modules to work alongside alsa and alsa-utils, so now JUCE midi device support is ready
  • VM can be brought up and provisioned with audio drivers, host build and cross compile environment

Next Steps:

  • Provisioners for building FirmwareSender
  • Provisioners for building OwlProgram Patch Target
  • Install Script
  • New Helper Script
  • Linux Support
  • Windows

Im releasing this as soon as i have it fully running for OS X. After that ill bring a rolling release for Linux.

Cheers,

1 Like

Last Status: FirmwareSender crashes when running --list devices on the VM. I will have a chance to look into it today.
Strace

open("/dev/snd/seq", O_RDWR|O_CLOEXEC)  = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
ioctl(3, SNDRV_SEQ_IOCTL_PVERSION, 0x7ffe1aa93ba8) = 0
ioctl(3, SNDRV_SEQ_IOCTL_CLIENT_ID, 0x7ffe1aa93bac) = 0
ioctl(3, SNDRV_SEQ_IOCTL_RUNNING_MODE, 0x7ffe1aa93bb0) = 0
fcntl(3, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0

Looks like the last system call was setting some flags for /dev/snd/seq. Anybody any ideas?

Cheers,

Im actually thinking this still might be ALSA related stuff. “speaker-test” utility has some issues when running, too. It’s probably worth ensuring alsa audio and midi is working in the box before trying FirmwareSender again…

Hi all.

A little update from linux userland hell :stuck_out_tongue:

TLDR;
This is all more tedious then expected but Im still positive I can get howl up and running granted more delay than im happy about. Currently theres two issues that need attention: usb midi support in the vm and getting firmware sender running without it blowing up. For more info see the long story below :slight_smile:

Long Story:
Issues ATM

  • Xenial / No ALSA Audio (solved): howl uses a ubuntu xenial box to spin a vm from, the official base box on vagrant cloud does not have alsa installed, this is not great for running JUCE. This issue is somewhat solved after mucking around for a while with it I have audio running for my mac laptop in the vm using the pci hda intel card driver and the correct codec support.
  • Xenial / No ALSA USB Midi (open): my kernel module repository is missing some snd-usb* modules, have to figure out how to get those installed. Then i should be able to see my owl be registered as a midi device. This works fine in an ubuntu live installation so is only a matter of time until i get it running.
  • FirmwareSender segfaults: So this is a strange one… when running MidiInput::getDevices() FirmwareSender crashes. Since i dont have a good debugging environment in howl i made a simple console app with JUCE 5.2.1 and compiled it on howl, too. After linking against the correct JUCE Version this works withou segfaulting. For some reaseon FirmwareSender still wont do the job of listing devices without crashing.

Next Steps:

  • Probably gutting out FirmwareSender as much as possible to isolate the issue. Then incrementally building it back again or worst case porting it

@mars have you seen any of these segfaulting issues in linux with firmware sender? let me know if you have any hints!

Heres proof of concept that MidiInput::getDevices() runs ok on the howl vm:
vagrant@ubuntu-xenial:/vagrant/tools/MidiInputDevices/build$ ./MidiInputDevices
JUCE v5.2.1
Midi Input Devices:
0: Midi Through Port-0

Cheers and talk soon guys,

Good to hear you’re making progress!

If MidiInput::getDevices() returns NULL the code will probably SEGFAULT, but there’s no indication it should.

Now the FirmwareSender doesn’t use MidiInput, really, it just gives you the option to list the inputs along with the outputs when invoked with -l. What happens when you invoke it normally, e.g. by make run or even make sysex (no MIDI) from OwlProgram?

It might be an idea to build FirmwareSender with latest JUCE, I think it’s configured with a really old version though…

1 Like

Hey @mars,

Appreciate the hints, it actually did boil down to the JUCE version in the end. As of version 5 theres some new user defines you need to set if running an alsa midi command line app without using an ApplicationBase for your program. The crash stemmed from not setting JUCE_ALSA_MIDI_NAME causing getInstance() to return null. See the linked source below for reference.
If you set the JUCE_ALSA_MIDI_NAME in AppConf.h the issues go away. I was dancing around this issue for a while before i considered the JUCE version you used originally might be a different one. Well, finally got this sorted.I’ll make sure FirmwareSender runs against JUCE 5x. If it’s useful I’ll make a merge request, maybe you can tag it as new version then or make a new branch out of it or something :slight_smile:

Talk soon,

Hey fam,

Had to set Howl aside last week a bit because I had to move some gear and focus on other projects. But I did pick up my OWL from the lab yesterday and am able to cram some development in during the week. Heres whats happend:

  • Ubuntu Xenial is dead: i have abandoned ubuntu/xenial64 as base box. It is maintained without ALSA and getting USB Audio/Midi kernel modules running was causing too much of a fuss.
  • Long live generic/arch: Adopted Arch Linux instead of Ubuntu LTS. generic/arch comes with precompiled and installed ALSA modules that seem to work out of the box.
  • Plan to use packer.io: Im currently planning to extend generic/arch to a custom how-arch vagrant box hosted on vagrant cloud. This should make the Vagrantfile in howl more maintainable and the installation process easier. The plan is to pre-install as much as possible in this box and remove most of the shell provisioners I used in the Vagrantfile previously
  • FirmwareSender no longer crashes: Its ported to JUCE 5.2 now on howl. @mars: i havent tested patch deployment yet but the app no longer crashes because of JUCE or ALSA making a fuss. I assume the migration to 5.2 is easy enough if you guys want to do it. Or i can make a merge request, allthough the diff would be in the .jucer file mainly and it might be easier to just update the JUCE version and add the user code on your end. Or even add a note to the documentation for FirmwareSender if people want to use newer versions of JUCE with it.

Next Steps:

  • Compiling C++ patches: Now that the VM seems to work for FirmwareSender i can see if i can get a basic C++ patch to compile.

Release Plan:

  • Hope to get the experimental release out in March. The release would still be considered instable but ready to be played around with. Main Features planned for the first release:
  • Tested support for Mac OS X host systems, vagrant and virtualbox hypervisor
  • Support for compiling C++ patches
  • Basic Documentation on github and in source

Talk soon,

2 Likes

FirmwareSender : I’ve put it on my todo-list to upgrade the JUCE version. (Unfortunately, it’s a long todo-list…)

Well now is as good a time as any! I’ve done the JUCE upgrade, it’s in the master branch of FirmwareSender. Thanks so much @bfabricius for the heads-up on JUCE_ALSA_MIDI_NAME. I got the same segfault, I would have spent ages on that if you’d not told me!
Let me know if you try it out, I’ve not made a release of it yet so we can still fix issues.

oh actually, there’s a problem.
Turns out the MIDI devices are somehow differently named after the update, probably ALSA related. The OWL device shows up as OWL-MIDI MIDI 1 - note the added MIDI 1 at the end.
This means that the default in the OwlProgram Makefile doesn’t work. Furthermore, since there is now whitespace in the device name they need to be quoted in the invocation.

I’ve pushed a change to OwlProgram so that the name is quoted correctly. You can now either build with e.g.
OWLDEVICE="OWL-MIDI MIDI 1" make ...

Still this is pretty awkward… Why are simple things never simple??

1 Like

Had to laugh at this one, story of my DIY life, really. Pretty funny, i was just going to write about the MIDI device name, i just ran into it :P. Thanks for already adding it to the thread.

No worries, mate. I’m enjoying being able to contribute and hoping that Howl turns out in a way that makes it a useful add-on to your stuff.

Talk soon,

@mars, btw… did you ever get the leaks in FirmwareSender under control?

[vagrant@bazinga OwlProgram]$ OWLDEVICE="OWL-MIDI MIDI 1" make PATCHNAME=Gain run
Building patch Gain
Sending patch Gain to OWL-MIDI MIDI 1 to run
JUCE v5.2.1
*** Leaked objects detected: 1 instance(s) of class MidiOutput
JUCE Assertion failure in juce_LeakedObjectDetector.h:88
*** Leaked objects detected: 1 instance(s) of class Thread
JUCE Assertion failure in juce_LeakedObjectDetector.h:88
*** Leaked objects detected: 2 instance(s) of class WaitableEvent
JUCE Assertion failure in juce_LeakedObjectDetector.h:88
*** Leaked objects detected: 1 instance(s) of class OwnedArray
JUCE Assertion failure in juce_LeakedObjectDetector.h:88

I remember you mentioning some changes… maybe im still not working with the latest source.

Cheers,

Yes they should be fixed since b02f01ef957, see Leaked object messages in Debug build · Issue #1 · pingdynasty/FirmwareSender · GitHub

1 Like