Writing a Looper plugin - Storing Audio File?

I want to write a Looper pedal with various looping patterns but for the moment the first hurdle would be recording a single audio track, and playing it back. I’d imagine that depends on the platform I’m developing for, in this case ModDevices. So wondering where I can store audio I assume /tmp would work but probably be wiped on rebooting? If I wanted persistence where should a file be written and how much space is there to play with?

Be great if there was some example code for this type of basic functionality.

Thanks for any pointers

1 Like

You dont handle any file paths yourself, but instead let the host do that for you.
LV2 State has some documentation.

mod-host supports pretty much all of it.

1 Like

@falkTX thanks a million for that on that, but can I ask a follow up question on developing LV2 plugins for the Mod Devices platforms. Specifically I’d like to ask about logging info out of the plugin as you’re developing. I went from the Mod Device to my Ubuntu Laptop just to go through a few of the examples in the lv2 book. That’s good I’m getting the hang of it, but the laptop platform has logging feature enabled and I was even throwing in a few printf() statements and getting those output to the terminal when I ran with ‘jalv’

Is there a way to look at logging out of the Mod Devices platform? I come from an embedded world and even if there was a way to ‘light a LED’ that’d be something that I could use to signal that something had happened in the code. At present I feel like I’m flying blind. If the plugin I wrote worked perfectly first time out of the box then I wouldn’t need any logging output, but I don’t fancy my chances.

Actually be a great plugin example to have a switch and a LED in a plugin that did very little else.

sure. logging can be done with an lv2 extension too :wink:
https://lv2plug.in/ns/ext/log

if you use the eg-sampler (aka “Exampler”) and open your browser console, you will notice the prints from the plugin end up in there.

1 Like

Oh and I just remembered we did a plugin for this as a test

this will print a message every second

1 Like

Thanks a million that should be very helpful but moving back to develop a plugin for Mod Devices platform I now remember why I moved away to develop for the Linux Laptop as a target. Basically I took the example amp plugin and edited it to change the names of the plugin and make simple changes to get the hang of it. That went well I had a plugin that built without any error and installed to the Mod Dwarf without any issue, but as soon as I drag the plugin onto the canvas I get an error on the top right of the canvas “Error adding effect” That’s it nothing more descriptive then that. Nothing in the Console. I’ve no idea what the issue is but be nice if the system could indicate what the issue is.

Error adding effect, is all I’ve got. So I could dump this and start writing from scratch but that serves no purpose I’ll eventually make a mistake in the code and not have an issue with building or installing to the Mod Dwarf but I’ll eventually hit ‘Error adding effect’ and we’re back to square one.

So the idea of having an extensible pedal platform for which I can write plugins is great, but in practice it doesn’t appear to be an easy target to develop for.

huh that is just how an embed platform works.
you know you have full access to the device right? so you can ssh into it and run the binary directly.

very often the binary wont load because it is compiled for intel 64bit, while the unit uses ARM.

since the host can run on the command-line, this can be used to test plugin loading:

echo "add http://lv2plug.in/plugins/eg-sampler 0" | mod-host -i

replace the URI with the one from your plugin

1 Like

Also, if you have a question, just ask it and dont be afraid of it. We are here to assist you and anyone help interested on the platform.
Complaining will often lead nowhere though.

It is quite the different target yes, but on the inside the OS works just like any other.
There is a kernel, it has binaries and files, there are services running on the background, has an audio host etc…

2 Likes

OK I’m complaining but an error message as descriptive as ‘error adding effect’ is not a very helpful or constructive message.

I’ll try ssh into it and see if that’s any more descriptive

Yes, but considering the plugins are typically installed through the plugin store, it is usually enough for us to know something is wrong and look deeper into it. Giving technical details to the user would not really help here IMO.
For developers, we are smart enough to figure it out and diagnose the real problem.
I would not ever recommend to push a plugin binary every single time and commenting out things as a way to figure out what is wrong… work smarter not harder kinda deal.

That said, it should be way more obvious from our side to developers on how to diagnose such problems.
We have in our timeline to work on plugin developer documentation during the v1.11 release candidate phase.

Sorry this is still all a bit confusing, it has been kinda the same people developing the platform also developing/porting the plugins to it. For developers that were used to LV2 and embed linux systems (like Robin aka x42) the process was quite quick and painless (but still arduous, he spent quite some time making all those midi filter modguis!)
But not everyone is used to a setup like this.

I can compare it to web development that can target mobile platforms. If one is used to develop for regular browsers, all if pretty fine - you get direct access to developer tools, logs, and can even change the HTML stuff in-place.
But when mobile platforms get in the mix (ignoring emulators here), things are much more complicated. You can no longer rely on inplace editing, logs and other things.
There is a whole setup/workflow dedicated to remote debugging over websockets that first time you try it will make you quite confused (at least it did so to me).

My point is, everything new takes time to get used to.
Also, apologies for this not being the best experience at the moment. As I said, it is something we will work on, hopefully sooner rather than later.

4 Likes

Oops I think my problem is ‘buildroot’ I think I’ve corrected the problem but when I ask build root to rebuild my plugin, because the version hasn’t changed it just ignores the request and says ‘yeah that build fine!’ I then install the plugin and the previous one gets installed.

Bit like fixing a bug in your editor and forgetting to write the file before you kick off the build process.

Have to remove a few directories and force buildroot to just build it

buildroot caches the download, for local files you want to set it up just right, so it never caches anything at all. but while developing is better to just ignore buildroot packages altogether and just use the environment file on the repo.
like so:

cd /path/to/mod-plugin-builder
source local.env modwarf

cd /path/to/your/plugin/source
make # or cmake, waf, whatever applies
1 Like

Hit a strange error using the buildroot process:

/home/john/mod-workdir/moddwarf/toolchain/lib/gcc/aarch64-mod-linux-gnu/7.5.0/…/…/…/…/aarch64-mod-linux-gnu/bin/ld: cannot find crti.o: No such file or directory

crti.o is a system file part of the build system and a search for it shows it being in:

/home/john/mod-workdir/moddwarf/toolchain/aarch64-mod-linux-gnu/sysroot/usr/lib/crti.o

Since I based my plugin heavily of eg-amp it used make in that directory does work, well it produces a my-plugin.so file.

I assume all I have to do then is copy that directory into the mod dwarf and it’ll pick up the added plugin automatically?

I can see not using buildroot having it’s advantages, thanks for that.

typically you just setup LDFLAGS so it finds that file during the linking stage, but depends on the tools you use. waf usually takes care of this.
rolling your own makefile means you have to do all these steps yourself, I mean calling into the compiler with the right flags, linking etc

contrary to macos and windows, linux does not fail to link if there are missing symbols on the shared library. we need to give -no-undefined to the linker or more typically -Wl,-no-undefined to the compiler that will call the linker.

I decided that I was on shakey ground and I’d go back the start again and work through this:

$ sudo rm -rf ~/mod-workdir
$ rm -rf mod-plugin-builder

$ git clone git://github.com/moddevices/mod-plugin-builder
$ cd mod-plugin-builder
./bootstrap.sh

checking for aarch64-buildroot-linux-gnu-gcc… /home/john/mod-workdir/moddwarf/host/usr/bin/aarch64-linux-gnu-gcc
checking whether the C compiler works… no
configure: error: in `/home/john/mod-workdir/moddwarf/build/attr-2.4.47’:
configure: error: C compiler cannot create executables

The error is telling me to get more details in config.log.

$ find ~/mod-workdir -name config.log -print | wc -l
71

71 config.log files to look through. This might take some time :wink:

this will be in the attr dir, no need to look much.
just go to /home/john/mod-workdir/moddwarf/build/attr-2.4.47/config.log

did you forget to write “moddwarf” as argument to bootstrap.sh ?

what linux system do you have? this must be something in particular with the host linux OS here.

I am going to try myself in a clean workdir too to see if I can reproduce it.
Perhaps this is a regression from a few commits back, I have been doing some experiments lately.

Yeah I messed up, one config got deleted by accident and it broke new builds.
But existing ones were fine, so I didnt notice till now.
use this to get it fixed

rm -rf ~/mod-workdir/*/build/toolchain-external-undefined

git pull and re-run bootstrap, it should work now.

1 Like

Thanks so much for that. I gave it a break last night but came back to it earlier this evening and got the build environment installed again got plugin building, installed and log messages working. Result!

Have to go searching for how to do the next step. Thanks again.

4 Likes

Finally got back to my looper plugin. It’s all gone pretty well but stuck trying to get a momentary footswitch to clear all the recorded loops. What I have does appear to work as in I have a ‘Clear all’ port and can configure it on the web UI to be connected to footswitch ‘B’ of the ModDwarf. Once configured when I press the footswitch I can see in the configuration screen the animation of the ‘clear all’ switch being pressed. So configured as expected but then when I try the footswitch my code isn’t hitting the printf I’m expecting it to.

I’ve taken the code I’m using from other example LV2 plugins but that doesn’t mean I’ve done it right, or that I’m using a good example to copy from. So if I can go through what I’ve done I’ve added a port to the ttl file:

    *] , [*
  •       a lv2:ControlPort, lv2:InputPort;*
    
  •   lv2:index 4;*
    
  •   lv2:symbol "clear_all";*
    
  •   lv2:name "Clear all";*
    
  •   lv2:shortName "Clear";*
    
  •   lv2:default 0;*
    
  •   lv2:minimum 0;*
    
  •   lv2:maximum 1;*
    
  •   lv2:portProperty lv2:integer, lv2:trigger;*
    
  • ]*
  • .*

In the data for my instance I’ve created a data variable for the port, which is a ‘float *’ I’ve copied that from else where even though in the ‘.ttl’ file it’s an ‘lv2:integer’. Like I say copied that from else where so possibly have a bad example.

In the connect_port I simple connect as for any other port:

*case CLEAR_ALL:*
  •   self->clear_all_port = (float *) data;*
    
  •   break;*
    

That’s all good. I’ve used print statements and on initialisation the port is 0.0 once configured and I press the button ‘B’ it changes to 1.000, so it does work, but only once. So you have initialisation and one press there after it’s never changing, no matter how much button B pressing you do.

I’m really looking for a momentary switch functionality, ‘lv2:trigger’ appears to be good as I get to configure a footswitch, but I’m obviously doing something wrong.

Has anybody set up a momentary switch in the ModDwarf in a plugin? Struggling to find relevant example.

are you by any chance modifying the value of your own control input port? I ask because you are not allowed to do this.
the host is the one that will reset the trigger to its default value after every run.
your clear_all_port there should be a const float * type