question on expanding Fermata

Sorry for putting this out without a more detailed explanation…

So, in a VCV Rack module I’m working on I try to collect the text of some neighbouring modules. This code seems to be working with VCV Core Notes and Submarine TD-316. But somehow it’s failing in case of Stochastic Telegraph Fermata. Knowing that my DEBUG_VAL variable never set to -0.444 I believe that there is an issue with the plug and/or the model name. But what? I just don’t get it.

@StochasticTelegraph am I missing something?

    std::string readNeighbourText(int64_t& outId){
        Module* left=getLeftExpander().module;
        outId=-1;
        if(!left||!left->model||!left->model->plugin) return "";
        const std::string& plug =left->model->plugin->slug;
        const std::string& model=left->model->slug;
        if(plug=="Core"&&model=="Notes"){
        DEBUG_VAL=-0.111;
            rack::core::NotesModule* n=dynamic_cast<rack::core::NotesModule*>(left);
            if(n){outId=n->id; return n->text;}
        }
        if(plug=="SubmarineFree"&&model=="TD-316"){
        DEBUG_VAL=-0.316;
            outId=left->id;
            json_t* j=left->dataToJson();
            std::string result;
            if(j){json_t* tJ=json_object_get(j,"text");
                  if(tJ) result=json_string_value(tJ);
                  json_decref(j);}
            return result;
        }
		if (plug == "StochasticTelegraph" && model == "Fermata") {
        DEBUG_VAL=-0.444;
			outId = left->id;
			json_t* j = left->dataToJson();
			std::string result;
			if(j){json_t* tJ=json_object_get(j,"text");
                  if(tJ) result=json_string_value(tJ);
				// if (tJ && json_is_string(tJ)) result = json_string_value(tJ);
				json_decref(j);}
			return result;
		}
        return "";
    }

Further reference: plugin.json

I’m almost offended that you’re not grabbing text from pachde One:Info, too. :slight_smile:

The method of grabbing the “text” item from the json will work for all of Notes, TD-316, Fermata and Info. I simplified your code to the following (Guide is the module I happened to check it with), stepped through in a debugger and it works fine, so something else is going on.

    std::string moduleText(Module *mod) {
        assert(mod);
        json_t *j = mod->dataToJson();
        std::string result;
        if (j) {
            json_t *tJ = json_object_get(j, "text");
            if (tJ)
                result = json_string_value(tJ);
            json_decref(j);
        }
        return result;
    }

    std::string Guide::readNeighbourText(int64_t &outId)
    {
        Module *left = getLeftExpander().module;
        outId = -1;
        if (!left || !left->model || !left->model->plugin)
            return "";
        const std::string &plug = left->model->plugin->slug;
        const std::string &model = left->model->slug;
        bool grab = false;
        if (plug == "Core" && model == "Notes") {
            outId = left->id;
            grab = true;
        } else if (plug == "SubmarineFree" && model == "TD-316") {
            outId = left->id;
            grab = true;
        } else if (plug == "StochasticTelegraph" && model == "Fermata") {
            outId = left->id;
            grab = true;
        } else if (plug == "pachde-one" && model == "pachde-info") {
            outId = left->id;
            grab = true;
        }
        return grab ? moduleText(left) : "";
    }
1 Like

Thanks for looking into this!

I like your code. It’s easy to read, way more polished than the one I used. However it is equally efficient. It grabs the text from VCV Core Notes, TD-316 but not from Fermata or Info.

By the way, I’ve just added your plugin and I am confused by the total transparency. Is it meant to look like this? (Info is the second module from the left.)

I can confirm that when I add a new Info module to a patch, it starts as invisible, except for the screws in the corners. If I select it, and fiddle with it, it becomes more visible. Paul?

@FiroLFO I never would have thought to do this, but it sure looks like it could work. I’m curious at what point it fails:

Does getLeftExpander not see Fermata as a module at all?

If it does, what does it think the slug and model are?

1 Like

Yes I had to save a new default for info, because mine loads invisible as well.

Regarding invisible Info module

Thanks, Dave! I guess I should submit to the library now. I was waiting to see if any other issues came in for the many new things in pachde One, but haven’t seen anything else so far.

False alarm. I’m sorry. I realized that I made a mistake.

The error wasn’t in the code I provided. There was another section in the module with an additional condition… My apologies.

But just for the record: even Fermata’s frame is turning to transparent if I zoom in

If you’d like more Transparency in rack modules. Here’s Rack without rails, and transparent panels, using pachde One:Skiff.

2 Likes

I’ve also noticed the edges of Fermata going clear when zoomed way in. Since my code has little-to-no idea what size it is when being rendered, I’ve not really investigated it.

Very curious to see what this will be for. It looks like a language of some sort…definitely a clever way to offload the “having a text editor in my module” problem, which I know from experience is a royal pain. That’s where Fermata came from; I’d done so much work to make a better editor for BASICally that I thought, well, might as well release it on its own.

That’s exactly the point. :slight_smile: I am happy to talk about the concept, influences, motivations and/or to share my CPP file as a working proof-of-concept. I don’t think I’ll ever release it to the VCV Library and I don’t think I’ll ever finish it. However I think it can be useful even as is now.

In general it’s a ‘set and forget’ module in 2HP. It’s as dumb as you can imagine. Reads the text of the editor module and evaluates every line. If there’s an error then it quietly ignores it.

The incomplete list of tricks are

OUTx = PATTERN(CLK, RST, bits [, low [, high]])		# Gate sequencer
OUTx = TPATTERN(CLK, RST, bits [, low [, high]])	# Trigger sequencer
OUTx = PPATTERN(PHASOR, bits [, low [, high]])		# Phasor sequencer
OUTx = HPATTERN(CLK, RST, val1:steps1, val2:steps2, …)	# Hold-on sequencer
OUTx = VPATTERN(CLK, RST, hexstring [, low [, high]])	# CV sequencer. Hex characters: 0-9 A-F

SVARx = RANDPAT(CLK,length,density)       # bits, creates a new pattern
SVARx = RANDVAL(CLK,length,minval,maxval) # hextring, creates a new pattern

For temporary calculations there are a limited number of variables available:

IN1 to IN4 are the inputs
OUT1 to OUT4 are the outputs
VAR1 to VAR9 for numbers
SVAR2 to SVAR9 for strings

Additional limitation of my current approach is that I can easily grab the text from the editor but there is no way to send it there. (Unless I modify or rewrite the editor module.) But that’s fine. I can live with it. I added an export to my context menu to dump the current script to the clipboard.

If interested, send me a message or open a separate topic. I am happy to share.

1 Like

You could try loading the text by reversing the process you used to grab it. For most modules it would work fine to contain only the “text” variable and omit the rest. Then you call the module’s dataFromJson.

A while ago I had thoughts about making a module that was a variant of Fermata, but for other people’s text-based languages.

Think essentially of a Fermata editor with a Tipsy output and input. Every time the text gets edited, it sends the entire text out through the output. If it gets a Tipsy input (likely in response to the text it sent to the output) of a particular form (e.g., “line=3,error=‘unknown function foo’”), then the module would highlight the errant line and display the error in a small text window within the module.

In more sober moments, I figured that there weren’t that many “text-based language” modules waiting to be written, so I never wrote up a proposal here. But I’d be happily intrigued if I was wrong!

Indeed, I’ve been pondering how to do note-length patterns and rhythms in an approachable way, and something like this occurs as a nice way to lift it off the ground.

mahlen

2 Likes