kopia lustrzana https://github.com/jameshball/osci-render
Merge pull request #69 from jameshball/lua-fixes
Lua bug fixes and increased stabilitypull/170/head
commit
616f1128d2
|
@ -187,11 +187,17 @@ void OscirenderAudioProcessorEditor::updateCodeEditor() {
|
|||
codeEditors[i]->setVisible(false);
|
||||
}
|
||||
codeEditors[index]->setVisible(true);
|
||||
// used so that codeDocumentTextInserted and codeDocumentTextDeleted know whether the parserLock
|
||||
// is held by the message thread or not. We hold the lock in this function, but not when the
|
||||
// code document is updated by the user editing text. Since both functions are called by the
|
||||
// message thread, this is safe.
|
||||
updatingDocumentsWithParserLock = true;
|
||||
if (index == 0) {
|
||||
codeEditors[index]->loadContent(audioProcessor.perspectiveEffect->getCode());
|
||||
} else {
|
||||
codeEditors[index]->loadContent(juce::MemoryInputStream(*audioProcessor.getFileBlock(originalIndex), false).readEntireStreamAsString());
|
||||
}
|
||||
updatingDocumentsWithParserLock = false;
|
||||
}
|
||||
triggerAsyncUpdate();
|
||||
}
|
||||
|
@ -227,12 +233,22 @@ void OscirenderAudioProcessorEditor::editPerspectiveFunction(bool enable) {
|
|||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
void OscirenderAudioProcessorEditor::codeDocumentTextInserted(const juce::String& newText, int insertIndex) {
|
||||
updateCodeDocument();
|
||||
if (updatingDocumentsWithParserLock) {
|
||||
updateCodeDocument();
|
||||
} else {
|
||||
juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
|
||||
updateCodeDocument();
|
||||
}
|
||||
}
|
||||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
void OscirenderAudioProcessorEditor::codeDocumentTextDeleted(int startIndex, int endIndex) {
|
||||
updateCodeDocument();
|
||||
if (updatingDocumentsWithParserLock) {
|
||||
updateCodeDocument();
|
||||
} else {
|
||||
juce::SpinLock::ScopedLockType parserLock(audioProcessor.parsersLock);
|
||||
updateCodeDocument();
|
||||
}
|
||||
}
|
||||
|
||||
// parsersLock AND effectsLock must be locked before calling this function
|
||||
|
|
|
@ -55,6 +55,8 @@ private:
|
|||
MainMenuBarModel menuBarModel{*this};
|
||||
juce::MenuBarComponent menuBar;
|
||||
|
||||
std::atomic<bool> updatingDocumentsWithParserLock = false;
|
||||
|
||||
void codeDocumentTextInserted(const juce::String& newText, int insertIndex) override;
|
||||
void codeDocumentTextDeleted(int startIndex, int endIndex) override;
|
||||
void updateCodeDocument();
|
||||
|
|
|
@ -381,10 +381,10 @@ void OscirenderAudioProcessor::changeCurrentFile(int index) {
|
|||
if (index < 0 || index >= fileBlocks.size()) {
|
||||
return;
|
||||
}
|
||||
changeSound(sounds[index]);
|
||||
currentFile = index;
|
||||
updateLuaValues();
|
||||
updateObjValues();
|
||||
changeSound(sounds[index]);
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::changeSound(ShapeSound::Ptr sound) {
|
||||
|
|
|
@ -2,19 +2,29 @@
|
|||
#include "luaimport.h"
|
||||
|
||||
|
||||
LuaParser::LuaParser(juce::String script) {
|
||||
// initialization
|
||||
L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
|
||||
this->script = script;
|
||||
parse();
|
||||
LuaParser::LuaParser(juce::String script, juce::String fallbackScript) : fallbackScript(fallbackScript) {
|
||||
reset(script);
|
||||
}
|
||||
|
||||
LuaParser::~LuaParser() {
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
void LuaParser::reset(juce::String script) {
|
||||
functionRef = -1;
|
||||
|
||||
if (L != nullptr) {
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
L = luaL_newstate();
|
||||
lua_atpanic(L, panic);
|
||||
luaL_openlibs(L);
|
||||
|
||||
this->script = script;
|
||||
parse();
|
||||
}
|
||||
|
||||
void LuaParser::parse() {
|
||||
const int ret = luaL_loadstring(L, script.toUTF8());
|
||||
if (ret != 0) {
|
||||
|
@ -22,6 +32,9 @@ void LuaParser::parse() {
|
|||
DBG(error);
|
||||
lua_pop(L, 1);
|
||||
functionRef = -1;
|
||||
if (script != fallbackScript) {
|
||||
reset(fallbackScript);
|
||||
}
|
||||
} else {
|
||||
functionRef = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
@ -30,10 +43,6 @@ void LuaParser::parse() {
|
|||
// only the audio thread runs this fuction
|
||||
std::vector<float> LuaParser::run() {
|
||||
std::vector<float> values;
|
||||
|
||||
if (functionRef == -1) {
|
||||
return values;
|
||||
}
|
||||
|
||||
lua_pushnumber(L, step);
|
||||
lua_setglobal(L, "step");
|
||||
|
@ -54,24 +63,35 @@ std::vector<float> LuaParser::run() {
|
|||
|
||||
lua_geti(L, LUA_REGISTRYINDEX, functionRef);
|
||||
|
||||
const int ret = lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
if (ret != 0) {
|
||||
const char* error = lua_tostring(L, -1);
|
||||
DBG(error);
|
||||
functionRef = -1;
|
||||
} else if (lua_istable(L, -1)) {
|
||||
auto length = lua_rawlen(L, -1);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
const int ret = lua_pcall(L, 0, LUA_MULTRET, 0);
|
||||
if (ret != 0) {
|
||||
const char* error = lua_tostring(L, -1);
|
||||
DBG(error);
|
||||
functionRef = -1;
|
||||
if (script != fallbackScript) {
|
||||
reset(fallbackScript);
|
||||
}
|
||||
} else if (lua_istable(L, -1)) {
|
||||
auto length = lua_rawlen(L, -1);
|
||||
|
||||
for (int i = 1; i <= length; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_gettable(L, -2);
|
||||
float value = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
values.push_back(value);
|
||||
for (int i = 1; i <= length; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_gettable(L, -2);
|
||||
float value = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
values.push_back(value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
functionRef = -1;
|
||||
if (script != fallbackScript) {
|
||||
reset(fallbackScript);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
// clear stack
|
||||
lua_settop(L, 0);
|
||||
|
||||
step++;
|
||||
|
||||
|
@ -86,3 +106,19 @@ void LuaParser::setVariable(juce::String variableName, double value) {
|
|||
variables.push_back(value);
|
||||
updateVariables = true;
|
||||
}
|
||||
|
||||
bool LuaParser::isFunctionValid() {
|
||||
return functionRef != -1;
|
||||
}
|
||||
|
||||
juce::String LuaParser::getScript() {
|
||||
return script;
|
||||
}
|
||||
|
||||
|
||||
int LuaParser::panic(lua_State *L) {
|
||||
const char *msg = lua_tostring(L, -1);
|
||||
if (msg == NULL) msg = "error object is not a string";
|
||||
DBG("PANIC: unprotected error in call to Lua API (%s)\n" << msg);
|
||||
return 0; /* return to Lua to abort */
|
||||
}
|
|
@ -5,19 +5,25 @@
|
|||
struct lua_State;
|
||||
class LuaParser {
|
||||
public:
|
||||
LuaParser(juce::String script);
|
||||
LuaParser(juce::String script, juce::String LuaParser = "return { 0.0, 0.0 }");
|
||||
~LuaParser();
|
||||
|
||||
std::vector<float> run();
|
||||
void setVariable(juce::String variableName, double value);
|
||||
bool isFunctionValid();
|
||||
juce::String getScript();
|
||||
|
||||
private:
|
||||
void reset(juce::String script);
|
||||
void parse();
|
||||
|
||||
static int panic(lua_State* L);
|
||||
|
||||
int functionRef = -1;
|
||||
long step = 1;
|
||||
lua_State* L;
|
||||
lua_State* L = nullptr;
|
||||
juce::String script;
|
||||
juce::String fallbackScript;
|
||||
std::atomic<bool> updateVariables = false;
|
||||
juce::SpinLock variableLock;
|
||||
std::vector<juce::String> variableNames;
|
||||
|
|
|
@ -8,6 +8,10 @@ FileParser::FileParser() {}
|
|||
void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream> stream, juce::Font font) {
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
if (extension == ".lua" && lua != nullptr && lua->isFunctionValid()) {
|
||||
fallbackLuaScript = lua->getScript();
|
||||
}
|
||||
|
||||
object = nullptr;
|
||||
camera = nullptr;
|
||||
svg = nullptr;
|
||||
|
@ -23,7 +27,7 @@ void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream
|
|||
} else if (extension == ".txt") {
|
||||
text = std::make_shared<TextParser>(stream->readEntireStreamAsString(), font);
|
||||
} else if (extension == ".lua") {
|
||||
lua = std::make_shared<LuaParser>(stream->readEntireStreamAsString());
|
||||
lua = std::make_shared<LuaParser>(stream->readEntireStreamAsString(), fallbackLuaScript);
|
||||
}
|
||||
|
||||
sampleSource = lua != nullptr;
|
||||
|
|
|
@ -37,4 +37,6 @@ private:
|
|||
std::shared_ptr<SvgParser> svg;
|
||||
std::shared_ptr<TextParser> text;
|
||||
std::shared_ptr<LuaParser> lua;
|
||||
|
||||
juce::String fallbackLuaScript = "return { 0.0, 0.0 }";
|
||||
};
|
||||
|
|
Ładowanie…
Reference in New Issue