summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-04-01 05:05:34 +0000
committerTim E. Real <termtech@rogers.com>2011-04-01 05:05:34 +0000
commit0fcb500389e91c0692f2b5fa9c95684b3416e254 (patch)
tree0c6ffdf3a32cc75ec26f4dc5660a247afaceda11
parent1ba4f03ff7fea99fc7d215837f8a4f6d8f27c859 (diff)
Initial support for custom LADSPA DSSI GUIs, such as those generated by FLAM.
-rw-r--r--muse2/ChangeLog4
-rw-r--r--muse2/muse/dssihost.cpp2
-rw-r--r--muse2/muse/dssihost.h2
-rw-r--r--muse2/muse/mixer/rack.cpp3
-rw-r--r--muse2/muse/osc.cpp85
-rw-r--r--muse2/muse/osc.h2
-rw-r--r--muse2/muse/plugin.cpp79
-rw-r--r--muse2/muse/plugin.h10
8 files changed, 128 insertions, 59 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog
index 38047516..2d42c0d0 100644
--- a/muse2/ChangeLog
+++ b/muse2/ChangeLog
@@ -1,3 +1,7 @@
+31.03.2011:
+ * Feature: Support for custom LADSPA DSSI GUIs, such as those generated by FLAM. (p4.0.19 Tim)
+ - Initial support. TODO: Refine how a particular UI file is chosen - uses first one found for now.
+ Also may need to support multiple choices if multiple lib-level and/or plugin-level UIs are found.
27.03.2011:
- Fixed end/off-screen selections not being drawn in midi controller graphs. (Tim)
- Reverted Midi Track Info ui layout more or less to pre- Mar 5, with some improvements. (Tim)
diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp
index 88ad0eed..2f434972 100644
--- a/muse2/muse/dssihost.cpp
+++ b/muse2/muse/dssihost.cpp
@@ -2967,6 +2967,8 @@ int DssiSynthIF::pluginID() { return (synth &&
int DssiSynthIF::id() { return 0; } // Synth is not part of a rack plugin chain. Always 0.
QString DssiSynthIF::pluginLabel() const { return (synth && synth->dssi) ? QString(synth->dssi->LADSPA_Plugin->Label) : QString(); }
QString DssiSynthIF::name() const { return synti->name(); }
+QString DssiSynthIF::lib() const { return synth ? synth->completeBaseName() : QString(); }
+QString DssiSynthIF::dirPath() const { return synth ? synth->absolutePath() : QString(); }
AudioTrack* DssiSynthIF::track() { return (AudioTrack*)synti; }
void DssiSynthIF::enableController(int i, bool v) { controls[i].enCtrl = v; }
bool DssiSynthIF::controllerEnabled(int i) const { return controls[i].enCtrl; }
diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h
index c574a719..eab561a5 100644
--- a/muse2/muse/dssihost.h
+++ b/muse2/muse/dssihost.h
@@ -233,6 +233,8 @@ class DssiSynthIF : public SynthIF, public PluginIBase
int id();
QString pluginLabel() const;
QString name() const;
+ QString lib() const;
+ QString dirPath() const;
AudioTrack* track();
void enableController(int /*i*/, bool v = true);
bool controllerEnabled(int /*i*/) const;
diff --git a/muse2/muse/mixer/rack.cpp b/muse2/muse/mixer/rack.cpp
index 7cc5b077..daebaa30 100644
--- a/muse2/muse/mixer/rack.cpp
+++ b/muse2/muse/mixer/rack.cpp
@@ -224,7 +224,8 @@ void EffectRack::menuRequested(QListWidgetItem* it)
upAction->setEnabled(true);
if (idx == (PipelineDepth-1))
downAction->setEnabled(false);
- if(!pipe->isDssiPlugin(idx))
+ //if(!pipe->isDssiPlugin(idx))
+ if(!pipe->has_dssi_ui(idx)) // p4.0.19 Tim.
showNativeGuiAction->setEnabled(false);
}
diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp
index c5ff182d..8bfdfd68 100644
--- a/muse2/muse/osc.cpp
+++ b/muse2/muse/osc.cpp
@@ -830,7 +830,7 @@ void OscIF::oscSendConfigure(const char *key, const char *val)
//bool OscIF::oscInitGui()
bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QString& name,
- const QString& label, const QString& filePath, const QString& dirPath)
+ const QString& label, const QString& filePath, const QString& guiPath)
{
// Are we already running? We don't want to allow another process do we...
if((_oscGuiQProc != 0) && (_oscGuiQProc->state()))
@@ -842,6 +842,12 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
return false;
}
+ if(guiPath.isEmpty())
+ {
+ fprintf(stderr, "OscIF::oscInitGui guiPath is empty\n");
+ return false;
+ }
+
//
// start gui
//
@@ -849,52 +855,13 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
//char oscUrl[1024];
QString oscUrl;
- /*
- QString typ;
- QString baseName;
- QString name;
- QString label;
- QString filePath;
- QString dirPath;
- #ifdef DSSI_SUPPORT
- if(_oscSynthIF)
- {
- //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().toAscii().data());
- //snprintf(oscUrl, 1024, "%s/%s", url, synti->name().ascii());
- //snprintf(oscUrl, 1024, "%s/%s/%s", url, synth->info.baseName().ascii(), synti->name().ascii());
- typ = QT_TRANSLATE_NOOP("@default", "dssi_synth");
- baseName = _oscSynthIF->dssiSynth()->baseName(false);
- label = _oscSynthIF->dssiSynthI()->name();
- name = _oscSynthIF->dssiSynth()->name();
-
- dirPath = _oscSynthIF->dssiSynth()->dirPath(false);
- filePath = _oscSynthIF->dssiSynth()->filePath();
- }
- else
- #endif
- if(_oscPluginI)
- {
- typ = QT_TRANSLATE_NOOP("@default", "ladspa_efx");
- baseName = _oscPluginI->plugin()->lib(false);
- //name = _oscPluginI->name();
- name = _oscPluginI->plugin()->label();
- label = _oscPluginI->label();
-
- dirPath = _oscPluginI->plugin()->dirPath(false);
- //dirPath.replace("ladspa", "dssi", true);
-
- filePath = _oscPluginI->plugin()->filePath();
- //filePath.replace("ladspa", "dssi", true);
- }
- else
- return false;
- */
-
//snprintf(oscUrl, 1024, "%s/%s/%s", url, baseName.ascii(), name.ascii());
//snprintf(oscUrl, 1024, "%s%s/%s/%s", url, typ.toLatin1().constData(), baseName.toLatin1().constData(), name.toLatin1().constData());
//oscUrl = QString("%1%2/%3/%4").arg(QString(QT_TRANSLATE_NOOP("@default", url))).arg(typ).arg(baseName).arg(name);
oscUrl = QString("%1%2/%3/%4").arg(QString(QT_TRANSLATE_NOOP("@default", url))).arg(typ).arg(baseName).arg(label);
+ // Removed p4.0.19 Tim
+ /*
//QString guiPath(info.path() + "/" + info.baseName());
//QString guiPath(synth->info.dirPath() + "/" + synth->info.baseName());
QString guiPath(dirPath + "/" + baseName);
@@ -944,20 +911,23 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
//synth->name().ascii());
name.toLatin1().constData());
#endif
+ */
- if ((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) &&
- (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
- {
+ //if ((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) &&
+ // (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ //{
+
// Changed by T356.
// fork + execlp were causing the processes to remain after closing gui, requiring manual kill.
// Changed to QProcess, works OK now.
//if((guiPid = fork()) == 0)
- {
+ //{
// No QProcess created yet? Do it now. Only once per SynthIF instance. Exists until parent destroyed.
if(_oscGuiQProc == 0)
_oscGuiQProc = new QProcess(muse);
- QString program(fi.filePath());
+ //QString program(fi.filePath());
+ QString program(guiPath);
QStringList arguments;
arguments << oscUrl
<< filePath
@@ -1012,11 +982,12 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
"channel 1", (void*)0);
*/
- fprintf(stderr, "exec %s %s %s %s failed: %s\n",
+ fprintf(stderr, "exec %s %s %s failed: %s\n",
//fi.filePath().toAscii().data(),
//fi.fileName().toAscii().data(),
- fi.filePath().toLatin1().constData(),
- fi.fileName().toLatin1().constData(),
+ //fi.filePath().toLatin1().constData(),
+ guiPath.toLatin1().constData(),
+ //fi.fileName().toLatin1().constData(),
oscUrl.toLatin1().constData(),
@@ -1035,10 +1006,11 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
#ifdef OSC_DEBUG
fprintf(stderr, "OscIF::oscInitGui after QProcess\n");
#endif
- }
- }
- }
+ //}
+ //}
+ //}
//synth->_hasGui = true;
+ /*
}
else {
printf("OscIF::oscInitGui %s: no dir for gui found: %s\n",
@@ -1048,6 +1020,7 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin
//synth->_hasGui = false;
}
+ */
return true;
}
@@ -1305,7 +1278,8 @@ bool OscDssiIF::oscInitGui()
return OscIF::oscInitGui(QT_TRANSLATE_NOOP("@default", "dssi_synth"), _oscSynthIF->dssiSynth()->baseName(),
_oscSynthIF->dssiSynth()->name(), _oscSynthIF->dssiSynthI()->name(),
- _oscSynthIF->dssiSynth()->filePath(), _oscSynthIF->dssiSynth()->path());
+ //_oscSynthIF->dssiSynth()->filePath(), _oscSynthIF->dssiSynth()->path());
+ _oscSynthIF->dssiSynth()->filePath(), _oscSynthIF->dssi_ui_filename()); // p4.0.19
}
#endif // DSSI_SUPPORT
@@ -1391,7 +1365,8 @@ bool OscEffectIF::oscInitGui()
return OscIF::oscInitGui(QT_TRANSLATE_NOOP("@default", "ladspa_efx"), _oscPluginI->plugin()->lib(false),
_oscPluginI->plugin()->label(), _oscPluginI->label(),
- _oscPluginI->plugin()->filePath(), _oscPluginI->plugin()->dirPath(false));
+ //_oscPluginI->plugin()->filePath(), _oscPluginI->plugin()->dirPath(false));
+ _oscPluginI->plugin()->filePath(), _oscPluginI->dssi_ui_filename()); // p4.0.19
}
diff --git a/muse2/muse/osc.h b/muse2/muse/osc.h
index 7d9afa92..ea94451b 100644
--- a/muse2/muse/osc.h
+++ b/muse2/muse/osc.h
@@ -140,7 +140,7 @@ class OscIF
OscControlFifo* _oscControlFifos;
virtual bool oscInitGui(const QString& /*typ*/, const QString& /*baseName*/, const QString& /*name*/,
- const QString& /*label*/, const QString& /*filePath*/, const QString& /*dirPath*/);
+ const QString& /*label*/, const QString& /*filePath*/, const QString& /*guiPath*/);
public:
OscIF();
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index 428afd24..88f73784 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -11,6 +11,7 @@
#include <dlfcn.h>
#include <cmath>
#include <math.h>
+#include <sys/stat.h>
#include <QButtonGroup>
#include <QCheckBox>
@@ -1304,6 +1305,33 @@ bool Pipeline::isDssiPlugin(int idx) const
return false;
}
+/*
+//---------------------------------------------------------
+// dssi_ui_filename
+//---------------------------------------------------------
+
+QString dssi_ui_filename(int idx) const
+{
+ PluginI* p = (*this)[idx];
+ if(p)
+ return p->dssi_ui_filename();
+
+ return QString();
+}
+*/
+
+//---------------------------------------------------------
+// has_dssi_ui
+//---------------------------------------------------------
+
+bool Pipeline::has_dssi_ui(int idx) const
+{
+ PluginI* p = (*this)[idx];
+ if(p)
+ return !p->dssi_ui_filename().isEmpty();
+
+ return false;
+}
//---------------------------------------------------------
// showGui
//---------------------------------------------------------
@@ -1433,6 +1461,57 @@ void Pipeline::apply(int ports, unsigned long nframes, float** buffer1)
}
//---------------------------------------------------------
+// PluginIBase
+//---------------------------------------------------------
+
+QString PluginIBase::dssi_ui_filename() const
+{
+ //QString guiPath(info.path() + "/" + info.baseName());
+ //QString guiPath(synth->info.dirPath() + "/" + synth->info.baseName());
+ if(dirPath().isEmpty() || lib().isEmpty())
+ return QString();
+
+ QString guiPath(dirPath() + "/" + lib());
+
+ //fprintf(stderr, "PluginIBase::dssi_ui_filename :%s\n", guiPath.toLatin1().constData());
+
+ QDir guiDir(guiPath, "*", QDir::Unsorted, QDir::Files);
+ if(!guiDir.exists())
+ return QString();
+
+ QStringList list = guiDir.entryList();
+
+ for(int i = 0; i < list.count(); ++i)
+ {
+ QFileInfo fi(guiPath + QString("/") + list[i]);
+ QString gui(fi.filePath());
+ if (gui.contains('_') == 0)
+ continue;
+ struct stat buf;
+
+ if(stat(gui.toLatin1().constData(), &buf))
+ {
+
+ //perror("stat failed");
+ //fprintf(stderr, "PluginIBase::dssi_ui_filename stat failed\n");
+ continue;
+ }
+
+ if (!((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) &&
+ (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
+ {
+ //perror("stat failed");
+ //fprintf(stderr, "PluginIBase::dssi_ui_filename File stat mode is wrong\n");
+ continue;
+ }
+
+ return gui;
+ }
+
+ return QString();
+};
+
+//---------------------------------------------------------
// PluginI
//---------------------------------------------------------
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 031eb566..8f31e573 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -288,22 +288,25 @@ class PluginIBase
virtual int id() = 0;
virtual QString pluginLabel() const = 0;
virtual QString name() const = 0;
+ virtual QString lib() const = 0;
+ virtual QString dirPath() const = 0;
virtual AudioTrack* track() = 0;
- virtual void enableController(int /*i*/, bool v = true) = 0;
+ virtual void enableController(int /*i*/, bool /*v*/ = true) = 0;
virtual bool controllerEnabled(int /*i*/) const = 0;
virtual bool controllerEnabled2(int /*i*/) const = 0;
virtual void updateControllers() = 0;
virtual void writeConfiguration(int /*level*/, Xml& /*xml*/) = 0;
- virtual bool readConfiguration(Xml& /*xml*/, bool readPreset=false) = 0;
+ virtual bool readConfiguration(Xml& /*xml*/, bool /*readPreset*/=false) = 0;
virtual int parameters() const = 0;
virtual void setParam(int /*i*/, double /*val*/) = 0;
virtual double param(int /*i*/) const = 0;
virtual const char* paramName(int /*i*/) = 0;
virtual LADSPA_PortRangeHint range(int /*i*/) = 0;
+ QString dssi_ui_filename() const;
};
//---------------------------------------------------------
@@ -430,6 +433,7 @@ class PluginI : public PluginIBase {
QString name() const { return _name; }
CtrlValueType valueType() const;
QString lib() const { return _plugin->lib(); }
+ QString dirPath() const { return _plugin->dirPath(); }
#ifdef OSC_SUPPORT
OscEffectIF& oscIF() { return _oscif; }
@@ -502,6 +506,8 @@ class Pipeline : public std::vector<PluginI*> {
QString name(int idx) const;
void showGui(int, bool);
bool isDssiPlugin(int) const;
+ //QString dssi_ui_filename(int) const;
+ bool has_dssi_ui(int idx) const;
void showNativeGui(int, bool);
void deleteGui(int idx);
void deleteAllGuis();