Skip to content

Commit

Permalink
Fix #305502: Osc plugin controller
Browse files Browse the repository at this point in the history
After a lot of plugin projects I felt blocked by the lack of network communication between a plugin and an exterior app so i imagined a way of doing that kind of things.

Duplicate of musescore#6095, fix an MSVC compiler warning it introduced.
  • Loading branch information
NozBead authored and Jojo-Schmitz committed Mar 5, 2023
1 parent aaab93a commit 15a4b37
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 31 deletions.
7 changes: 6 additions & 1 deletion mscore/musescore.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ class MuseScore : public QMainWindow, public MuseScoreCore {
void oscMuteChannel(double val);
void oscOpen(QString path);
void oscCloseAll();
void oscTriggerPlugin(QString list);
void oscTriggerPlugin(QString path, QVariant args);
void oscColorNote(QVariantList list);
void oscAction();
#endif
Expand All @@ -577,8 +577,13 @@ class MuseScore : public QMainWindow, public MuseScoreCore {
virtual void cmd(QAction* a);
void dirtyChanged(Score*);
void setPos(const Fraction& tick);
QString pluginPathFromIdx(int idx);
void pluginTriggered(int);
void pluginTriggered(QString path);
#ifdef SCRIPT_INTERFACE
void oscControlPlugin(int idx, QStringList methodPath, QVariant arg);
void oscControlPlugin(QString pluginPath, QStringList methodPath, QVariant arg);
#endif
void handleMessage(const QString& message);
void setCurrentScoreView(ScoreView*);
void setCurrentScoreView(int);
Expand Down
44 changes: 27 additions & 17 deletions mscore/osc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ void MuseScore::initOsc()
oo = new PathObject( "/close-all", QVariant::Invalid, osc);
QObject::connect(oo, SIGNAL(data()), SLOT(oscCloseAll()));

oo = new PathObject( "/plugin", QVariant::String, osc);
QObject::connect(oo, SIGNAL(data(QString)), SLOT(oscTriggerPlugin(QString)));
oo = new PathObject( "/plugin(/[^/.]*)+", QVariant::List, osc);
QObject::connect(oo, SIGNAL(data(QString, QVariant)), SLOT(oscTriggerPlugin(QString, QVariant)));

oo = new PathObject( "/color-note", QVariant::List, osc);
QObject::connect(oo, SIGNAL(data(QVariantList)), SLOT(oscColorNote(QVariantList)));
Expand Down Expand Up @@ -196,27 +196,37 @@ void MuseScore::oscTempo(int val)
seq->setRelTempo(double(t));
}

void addOscPrefix(QString* methodName)
{
methodName->replace(0, 1, methodName[0][0].toUpper());
methodName->prepend("osc");
}

//---------------------------------------------------------
// oscTriggerPlugin
//---------------------------------------------------------

void MuseScore::oscTriggerPlugin(QString /*s*/)
void MuseScore::oscTriggerPlugin(QString path, QVariant args)
{
#if 0 // TODO
#ifdef SCRIPT_INTERFACE
QStringList args = s.split(",");
if(args.length() > 0) {
int idx = pluginIdxFromPath(args.at(0));
if(idx != -1) {
for(int i = 1; i < args.length()-1; i++) {
addGlobalObjectToPluginEngine(qPrintable(args.at(i)), args.at(i+1));
i++;
}
pluginTriggered(idx);
}
QStringList pathElts = path.split("/");
QString pluginName;

for (int i = 0 ; i < 3 ; i++) {
if (i == 2)
pluginName = pathElts.first();

pathElts.removeFirst();
}
#endif
#endif

qDebug() << "[OSC] Plugin called : " << pluginName;

int idx = pluginIdxFromPath(pluginName);
if (idx != -1) {
addOscPrefix(&pathElts.last());
oscControlPlugin(idx, pathElts, args);
}
else
qDebug() << "[OSC] Unknow plugin : " << pluginName;
}

//---------------------------------------------------------
Expand Down
77 changes: 65 additions & 12 deletions mscore/plugin/mscorePlugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,36 +362,89 @@ bool MuseScore::loadPlugin(const QString& filename)
}

//---------------------------------------------------------
// pluginTriggered
// pluginPathFromIdx
//---------------------------------------------------------

void MuseScore::pluginTriggered(int idx)
{
QString MuseScore::pluginPathFromIdx(int idx) {
if (plugins.size() > idx)
pluginTriggered(plugins[idx]);
return plugins[idx];
else
return QString();
}

void MuseScore::pluginTriggered(QString pp)
{
QmlPluginEngine* engine = getPluginEngine();
//---------------------------------------------------------
// getPluginFromPath
//---------------------------------------------------------

QmlPlugin* pluginFromPath(QmlPluginEngine* engine, QString pluginPath)
{
QQmlComponent component(engine);
component.loadUrl(QUrl::fromLocalFile(pp));
component.loadUrl(QUrl::fromLocalFile(pluginPath));
QObject* obj = component.create();
if (obj == 0) {
if (!obj ) {
foreach(QQmlError e, component.errors())
qDebug(" line %d: %s", e.line(), qPrintable(e.description()));
return;
return nullptr;
}

QmlPlugin* p = qobject_cast<QmlPlugin*>(obj);
return qobject_cast<QmlPlugin*>(obj);
}

//---------------------------------------------------------
// oscControlPlugin
//---------------------------------------------------------

#ifdef SCRIPT_INTERFACE

void MuseScore::oscControlPlugin(int idx, QStringList methodPath, QVariant arg)
{
oscControlPlugin(pluginPathFromIdx(idx), methodPath, arg);
}

void MuseScore::oscControlPlugin(QString _pluginPath, QStringList methodPath, QVariant arg)
{
if (_pluginPath.isEmpty())
return;

QmlPluginEngine* engine = getPluginEngine();
QmlPlugin* p = pluginFromPath(engine, _pluginPath);
if (!p)
return;

QObject* obj = dynamic_cast<QObject*>(p);

for (int i = 0 ; i < (methodPath.length() - 1) ; i++)
obj = obj->findChild<QObject*>(methodPath[i]);

QMetaObject::invokeMethod(obj, methodPath.last().toLocal8Bit().data(), Q_ARG(QVariant, arg));
}

#endif
//---------------------------------------------------------
// pluginTriggered
//---------------------------------------------------------

void MuseScore::pluginTriggered(int idx)
{
pluginTriggered(pluginPathFromIdx(idx));
}

void MuseScore::pluginTriggered(QString pp)
{
if (pp.isEmpty())
return;

QmlPluginEngine* engine = getPluginEngine();
QmlPlugin* p = pluginFromPath(engine, pp);
if (!p)
return;

if(MuseScoreCore::mscoreCore->currentScore() == nullptr && p->requiresScore() == true) {
QMessageBox::information(0,
QMessageBox::tr("MuseScore"),
QMessageBox::tr("No score open.\n"
"This plugin requires an open score to run.\n"),
QMessageBox::Ok, QMessageBox::NoButton);
delete obj;
return;
}

Expand Down
2 changes: 2 additions & 0 deletions thirdparty/ofqf/qoscserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ void QOscServer::readyRead()
foreach( PathObject* obj, paths ) {
if ( exp.exactMatch( obj->_path ) )
obj->signalData( arguments );
else if ( QRegExp( obj->_path ).exactMatch( path ) )
emit obj->data( path, arguments );
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion thirdparty/ofqf/qosctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ class PathObject : public QObject
void data( double );
void data( QString );
void data( QVariantList );
void data();
void data( QString path, QVariant args );
void data();
// @}
private:
// called by QOscServer:
Expand Down

0 comments on commit 15a4b37

Please sign in to comment.