Newbie question - missing template files

Hi, I’m writing a VCV rack module, and I have the module working in a basic way. I have a crash now though where whenever I try to add any module to a patch it crashes due to a missing template.vcvm file. My understanding was these templates were optional?

For instance when loading a VCO, it crashes looking for this file …/Library/Application Support/Rack2/presets/Fundamental/VCO/template.vcvm

This file appears to be mandatory?

oid ModuleWidget::loadTemplate() {
	std::string templatePath = system::join(model->getUserPresetDirectory(), "template.vcvm");
	try {
		load(templatePath);
	}
	catch (Exception& e) {
		// Do nothing
	}
}

Could someone explain if these are manadatory, and if so, where should I get them from? Is this a problem because I’ve built VCV Rack from source, and I need to do something to generate templates?

Yes they are optional.

I took at look at this, and on my system, there was no template.vcvm for Fundamental/VCO. In fact, the only two folders I had under Rack2/presets were for plugins that I know I have saved default templates for: CosineKitty-Sapphire and SurgeXTRack. And I have no problem adding VCV VCO instances to a new patch.

So then I saved the default template for VCV VCO and now of course I do have a file Rack2/presets/Fundamental/VCO/template.vcvm. And I can still create new VCO instances after restarting Rack.

Then I manually deleted just the file template.vcvm from that directory, launched VCV Rack, and I can still add VCO instances to a patch.

My conclusion is that there is something else going wrong on your system. Can you provide more information about your crash? Do you have a stack trace in your log.txt that you can post here?

1 Like

Thanks for your investigations! I also assumed they were optional but in this particular code path it throws an exception if the file isn’t there in ModuleWidget::load() (see code snippet).

My understanding is the exception should be ignored because the calling function ModuleWidget::loadTemplate() ignores the exception.

It’s possible I’ve done something to screw up my environment, I don’t remember getting this before, now I get it when trying to load the in-built modules and my own.

void ModuleWidget::load(std::string filename) {
	FILE* file = std::fopen(filename.c_str(), "r");
	if (!file)
		throw Exception("Could not load patch file %s", filename.c_str());
	DEFER({std::fclose(file);});

	INFO("Loading preset %s", filename.c_str());

	json_error_t error;
	json_t* moduleJ = json_loadf(file, 0, &error);
	if (!moduleJ)
		throw Exception("File is not a valid patch file. JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
	DEFER({json_decref(moduleJ);});

	engine::Module::jsonStripIds(moduleJ);
	fromJson(moduleJ);
}

Here’s a stack trace

__cxa_throw (@__cxa_throw:3)
rack::app::ModuleWidget::load(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>) (/Users/x/Code/Github/Rack/src/app/ModuleWidget.cpp:583)
rack::app::ModuleWidget::loadTemplate() (/Users/x/Code/Github/Rack/src/app/ModuleWidget.cpp:621)
rack::app::browser::chooseModel(rack::plugin::Model*) (/Users/x/Code/Github/Rack/src/app/Browser.cpp:100)
rack::app::browser::ModelBox::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/src/app/Browser.cpp:261)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
rack::ui::ScrollWidget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/src/ui/ScrollWidget.cpp:130)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
rack::app::browser::Browser::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/src/app/Browser.cpp:791)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
rack::widget::OpaqueWidget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/OpaqueWidget.hpp:21)
rack::ui::MenuOverlay::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/src/ui/MenuOverlay.cpp:34)
void rack::widget::Widget::recursePositionEvent<void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent>(void (rack::widget::Widget::*)(rack::widget::Widget::ButtonEvent const&), rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:209)
rack::widget::Widget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/Widget.hpp:246)
rack::widget::OpaqueWidget::onButton(rack::widget::Widget::ButtonEvent const&) (/Users/x/Code/Github/Rack/include/widget/OpaqueWidget.hpp:21)
rack::widget::EventState::handleButton(rack::math::Vec, int, int, int) (/Users/x/Code/Github/Rack/src/widget/event.cpp:134)
-[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] (@-[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:]:871)
-[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] (@-[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:]:94)
-[NSWindow(NSEventRouting) sendEvent:] (@-[NSWindow(NSEventRouting) sendEvent:]:74)
-[NSApplication(NSEventRouting) sendEvent:] (@-[NSApplication(NSEventRouting) sendEvent:]:404)
_glfwPollEventsCocoa (/Users/x/Code/GitHub/Rack/dep/glfw/src/cocoa_window.m:1419)
rack::window::Window::step() (/Users/x/Code/Github/Rack/src/window/Window.cpp:434)
rack::window::Window::run() (/Users/x/Code/Github/Rack/src/window/Window.cpp:412)
main (/Users/x/Code/github/rack/adapters/standalone.cpp:274)
start (@start:593)

OK, so the next thing I’m trying to understand is why the try/catch in ModuleWidget.cpp loadTemplate isn’t handling the exception thrown from ModuleWidget.cpp line 583.

Did you build Rack from source yourself? If so, I’m wonder if there is something about the compiler options or your build environment that isn’t compiling the code correctly to catch exceptions.

Yeah, this is the question I have. The exception should be caught and ignored in loadTemplate().

I actually couldn’t remember how I installed VCV Rack dev tools originally. I have a folder in my GitHub folder, but actually I’m linking against another version, so I assume that was downloaded. This is the attached change log.

Ok, I’ve sorted the problem, and like most times, I was being a fool! cxa_throw is the standard method of triggering all exceptions, the reason it appeared like a crash is that I had break points set on throw exception!!

Thanks for your help @cosinekitty

image

2 Likes

Oh, OK, I didn’t realize you were running Rack itself in a debugger. So this wasn’t actually a crash, but Visual Studio “helping” you… I get it.

Yeah, sorry, I didn’t make that clear.

No worries! If it happened to you, it will happen to other developers working in Rack also, and this thread will help them. The whole “first chance” C++ exception debugging thing has hit me in other projects, just not in Rack because I’ve never tried to run it inside a debugger before.

1 Like