Hello.

Attached is a patch that brings us closer to release. It allows users to
specify which script file(s) to load in the XML like so:

    <controller id="SCS.3d MIDI 1" port="Port">
        <scriptfiles>
            <file functionprefix="StantonSCS3d">
                <filename>Stanton-SCS3d-scripts.js</filename>
            </file>
        </scriptfiles>

        <controls>
            <control>
                ...

It also calls the correct <devicename>.init() function in each file at
the proper time so LEDs can be set correctly.

I'll update the Wiki with these changes.


It also adds the option to specify a specific XML file at load time with
the --loadXMLfile path/to/file.xml  as a command line option. (For
developers only!!)

Sincerely,
Sean M. Pappalardo
"D.J. Pegasus"

<<--------------------------------------------------------------------------------->>
This E-Mail message has been scanned for viruses
and cleared by >>SmartMail<< from Smarter Technology, Inc.
<<--------------------------------------------------------------------------------->>
Index: src/midiobject.h
===================================================================
--- src/midiobject.h	(revision 2458)
+++ src/midiobject.h	(working copy)
@@ -85,6 +85,10 @@
     void disableMidiLearn();
     
 #ifdef __SCRIPT__
+    QList<QString> scriptFileNames;
+    QList<QString> scriptFunctionPrefixes;
+    
+    void loadScripts();
     MidiScriptEngine *getMidiScriptEngine();
 #endif
 
Index: src/midiobject.cpp
===================================================================
--- src/midiobject.cpp	(revision 2458)
+++ src/midiobject.cpp	(working copy)
@@ -22,6 +22,7 @@
 #include <signal.h>
 #include "dlgprefmididevice.h"
 #include "dlgprefmidibindings.h"
+
 #ifdef __SCRIPT__
 #include "script/midiscriptengine.h"
 #endif
@@ -39,36 +40,6 @@
     requestStop = false;
     midiLearn = false;
     debug = false;
-    
-#ifdef __SCRIPT__
-    m_pScriptEngine = new MidiScriptEngine();
-    m_pScriptEngine->engineGlobalObject.setProperty("midi", m_pScriptEngine->getEngine()->newQObject(this));
-
-    ConfigObject<ConfigValue> *m_pConfig = new ConfigObject<ConfigValue>(QDir::homePath().append("/").append(SETTINGS_FILE));
-    m_pScriptEngine->loadScript(m_pConfig->getConfigPath().append("midi/midi-mappings-scripts.js"));
-// FIXME: this hack below has to be replaced with something better... even *.js is preferrable to a hard coded string switch statement.
-//     switch (m_device) {
-//         case "SCS.3d MIDI *":
-//             m_pScriptEngine->loadScript(m_pConfig->getConfigPath().append("midi/Stanton-SCS3d-scripts.js"));
-//             break;
-//         case "Hercules MK2 *":
-//             m_pScriptEngine->loadScript(m_pConfig->getConfigPath().append("midi/Hercules-MK2-scripts.js"));
-//             break;
-//     }
-    qDebug() << "MidiObject: Evaluating all script code";
-    
-    m_pScriptEngine->evaluateScript();
-    if (!m_pScriptEngine->checkException() && m_pScriptEngine->isGood()) qDebug() << "MidiObject: Script code evaluated successfully";
-
-/*    // Call script's init function if it exists - First need deviceChannel and deviceName in this object
-    QScriptValue scriptFunction = m_pScriptEngine->execute("init");
-    if (!scriptFunction.isFunction()) qDebug() << "MidiObject: No init function in script";
-    else {
-        scriptFunction.call(QScriptValue());
-        m_pScriptEngine->checkException();
-    }
-*/
-#endif
 }
 
 /* -------- ------------------------------------------------------
@@ -80,6 +51,68 @@
 {
 }
 
+#ifdef __SCRIPT__
+/* -------- ------------------------------------------------------
+   Purpose: Loads and processes MIDI scripts
+   Input:   -
+   Output:  -
+   -------- ------------------------------------------------------ */
+void MidiObject::loadScripts()
+{
+    m_pScriptEngine = new MidiScriptEngine();
+    m_pScriptEngine->engineGlobalObject.setProperty("midi", m_pScriptEngine->getEngine()->newQObject(this));
+
+    ConfigObject<ConfigValue> *m_pConfig = new ConfigObject<ConfigValue>(QDir::homePath().append("/").append(SETTINGS_FILE));
+    
+    // Individually load & evaluate script files in the QList (built by dlgPrefMidiBindings) to check for errors
+    // so line numbers will be accurate per file (for syntax errors at least) to make troubleshooting much easier
+    bool scriptError = false;
+    
+    for (int i=0; i<scriptFileNames.size(); i++) {
+        m_pScriptEngine->clearCode();   // So line numbers will be correct
+        
+        QString filename = scriptFileNames.at(i);
+        qDebug() << "MidiObject: Loading & testing MIDI script" << filename;
+        m_pScriptEngine->loadScript(m_pConfig->getConfigPath().append("midi/").append(filename));
+        
+        m_pScriptEngine->evaluateScript();
+        if (!m_pScriptEngine->checkException() && m_pScriptEngine->isGood()) qDebug() << "MidiObject: Success";
+        else {
+            // This is only included for completeness since checkException should pop a qCritical() itself if there's a problem
+            qCritical() << "MidiObject: Failure evaluating MIDI script" << filename;
+            scriptError = true;
+        }
+    }
+    
+    qDebug() << "MidiObject: Loading & evaluating all MIDI script code";
+    m_pScriptEngine->clearCode();   // Start from scratch
+    
+    if (!scriptError) {
+        while (!scriptFileNames.isEmpty()) {
+            m_pScriptEngine->loadScript(m_pConfig->getConfigPath().append("midi/").append(scriptFileNames.takeFirst()));
+        }
+        
+        m_pScriptEngine->evaluateScript();
+        if (!m_pScriptEngine->checkException() && m_pScriptEngine->isGood()) qDebug() << "MidiObject: Script code evaluated successfully";
+    
+        // Call each script's init function if it exists
+        while (!scriptFunctionPrefixes.isEmpty()) {
+            QString initName = scriptFunctionPrefixes.takeFirst();
+            if (initName!="") {
+                initName.append(".init");
+                qDebug() << "MidiObject: Executing" << initName;
+                QScriptValue scriptFunction = m_pScriptEngine->execute(initName);
+                if (!scriptFunction.isFunction()) qWarning() << "MidiObject: No" << initName << "function in script";
+                else {
+                    scriptFunction.call(QScriptValue());
+                    m_pScriptEngine->checkException();
+                }
+            }
+        }
+    }
+}
+#endif
+
 void MidiObject::setMidiConfig(ConfigObject<ConfigValueMidi> * pMidiConfig)
 {
     m_pMidiConfig = pMidiConfig;
@@ -189,11 +222,11 @@
     }
 /*
     qDebug() << QString("MidiObject::receive from device: %1, type: %2, catagory: %3, ch: %4, ctrl: %5, val: %6").arg(device)
-       .arg(QString::number(type))
-       .arg(QString::number(category, 16).toUpper())
-       .arg(QString::number(channel, 16).toUpper())
-       .arg(QString::number(control, 16).toUpper())
-       .arg(QString::number(value, 16).toUpper());
+    .arg(QString::number(type))
+    .arg(QString::number(category, 16).toUpper())
+    .arg(QString::number(channel, 16).toUpper())
+    .arg(QString::number(control, 16).toUpper())
+    .arg(QString::number(value, 16).toUpper());
 */
     if (midiLearn) {
         emit(midiEvent(new ConfigValueMidi(type,control,channel), device));
@@ -291,7 +324,6 @@
         // qDebug() << "New Control Value: " << newValue << " ";
         p->queueFromMidi(category, newValue);
     }
-
 }
 
 void MidiObject::stop()
Index: src/dlgprefmidibindings.cpp
===================================================================
--- src/dlgprefmidibindings.cpp	(revision 2458)
+++ src/dlgprefmidibindings.cpp	(working copy)
@@ -65,8 +65,14 @@
     connect(btnRemoveOutputBinding, SIGNAL(clicked()), this, SLOT(slotRemoveOutputBinding()));
     connect(btnAddOutputBinding, SIGNAL(clicked()), this, SLOT(slotAddOutputBinding()));
 
-    // Try to read in the current XML bindings file, or create one if nothing is available
-    loadPreset(BINDINGS_PATH);
+    // Try to read in the current XML bindings file, one from the command line, or create one if nothing is available
+    QStringList commandLineArgs = QApplication::arguments();
+    int loadXML = commandLineArgs.indexOf("--loadXMLfile");
+    if (loadXML!=-1) {
+        qDebug() << "Loading custom MIDI mapping file:" << commandLineArgs.at(loadXML+1);
+        loadPreset(commandLineArgs.at(loadXML+1));
+    }
+    else loadPreset(BINDINGS_PATH);
     applyPreset();
     m_pMidi->disableMidiLearn();
 }
@@ -97,14 +103,36 @@
         // Get deviceid
         QString device = controller.attribute("id","");
         qDebug() << device << " settings found" << endl;
-        QDomElement control = controller.firstChildElement("controls").firstChildElement("control");
+        
+#ifdef __SCRIPT__
+        // Get a list of MIDI script files to load (loaded by MidiObject)
+        QDomElement scriptFile = controller.firstChildElement("scriptfiles").firstChildElement("file");
+        
+        // Default currently required file
+        m_pMidi->scriptFileNames.append("midi-mappings-scripts.js");
+        m_pMidi->scriptFunctionPrefixes.append("");
+        
+        // Look for additional ones
+        while (!scriptFile.isNull()) {
+        
+            QString functionPrefix = scriptFile.attribute("functionprefix","");
+            QString filename = WWidget::selectNodeQString(scriptFile, "filename");
+            m_pMidi->scriptFileNames.append(filename);
+            m_pMidi->scriptFunctionPrefixes.append(functionPrefix);
+        
+            scriptFile = scriptFile.nextSiblingElement("file");
+        }
 
-#ifdef __SCRIPT__
+        m_pMidi->loadScripts(); // This will halt execution if there's a problem with a script (qCritical)
+
         MidiScriptEngine * ScriptEngine = m_pMidi->getMidiScriptEngine();
         bool scriptGood = ScriptEngine->isGood();
         QStringList scriptFunctions;
         if (scriptGood) scriptFunctions = ScriptEngine->getFunctionList();
 #endif
+
+        QDomElement control = controller.firstChildElement("controls").firstChildElement("control");
+        
         while (!control.isNull()) {
             // For each control
             QString group = WWidget::selectNodeQString(control, "group");
Index: src/script/midiscriptengine.cpp
===================================================================
--- src/script/midiscriptengine.cpp	(revision 2458)
+++ src/script/midiscriptengine.cpp	(working copy)
@@ -28,9 +31,6 @@
 
     engineGlobalObject = m_engine.globalObject();
     engineGlobalObject.setProperty("engine", m_engine.newQObject(this));
-//     ControlObject* m_cobj;
-//     m_cobj = ControlObject::getControl(ConfigKey("[Channel1]","back"));
-//     engineGlobalObject.setProperty("revers", m_engine.newQObject(m_cobj));
 }
 
 MidiScriptEngine::~MidiScriptEngine() {
@@ -73,6 +73,8 @@
    -------- ------------------------------------------------------ */
 void MidiScriptEngine::clearCode() {
     m_scriptCode.clear();
+    m_scriptGood=false;
+    m_result="";
     return;
 }
 
@@ -179,7 +181,7 @@
 
         QString line = codeLines.takeAt(position);    // Pull & remove the current match from the list.
 
-        if (line.indexOf('#') != 0) {    // ignore # hashed out comments
+        if (line.indexOf('#') != 0 && line.indexOf("//") != 0) {    // ignore comments
             QStringList field = line.split(" ");
             qDebug() << "MidiScriptEngine: Found function:" << field[0] << "at line" << position;
             functionList.append(field[0]);
------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
_______________________________________________
Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to