summaryrefslogtreecommitdiff
path: root/muse2/muse
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2012-09-02 18:37:06 +0000
committerFlorian Jung <flo@windfisch.org>2012-09-02 18:37:06 +0000
commit00d38a64c11bfc363fd762a351225f3e4902d44e (patch)
tree420fd5f8bda0c8046c02bdf0b6474f59fc31c39c /muse2/muse
parent58136c7acf8f5f3281fe8e339aeaca251f2d1b7f (diff)
plugins can now be grouped
Diffstat (limited to 'muse2/muse')
-rw-r--r--muse2/muse/conf.cpp5
-rw-r--r--muse2/muse/plugin.cpp409
-rw-r--r--muse2/muse/plugin.h75
3 files changed, 467 insertions, 22 deletions
diff --git a/muse2/muse/conf.cpp b/muse2/muse/conf.cpp
index cca3cb94..37959f0f 100644
--- a/muse2/muse/conf.cpp
+++ b/muse2/muse/conf.cpp
@@ -64,6 +64,7 @@
#include "midiseq.h"
#include "amixer.h"
#include "track.h"
+#include "plugin.h"
namespace MusECore {
@@ -917,6 +918,8 @@ void readConfiguration(Xml& xml, bool doReadMidiPortConfig, bool doReadGlobalCon
MusEGlobal::config.unhideTracks = xml.parseInt();
else if (tag == "smartFocus")
MusEGlobal::config.smartFocus = xml.parseInt();
+ else if (tag == "plugin_groups")
+ MusEGlobal::readPluginGroupConfiguration(xml);
// ---- the following only skips obsolete entries ----
else if ((tag == "arranger") || (tag == "geometryPianoroll") || (tag == "geometryDrumedit"))
@@ -1321,6 +1324,8 @@ void MusE::writeGlobalConfiguration(int level, MusECore::Xml& xml) const
xml.colorTag(level, "bigtimeBackgroundcolor", MusEGlobal::config.bigTimeBackgroundColor);
xml.colorTag(level, "waveEditBackgroundColor", MusEGlobal::config.waveEditBackgroundColor);
+ MusEGlobal::writePluginGroupConfiguration(level, xml);
+
writeSeqConfiguration(level, xml, false);
MusEGui::DrumEdit::writeConfiguration(level, xml);
diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp
index e8b0489c..f1d817c9 100644
--- a/muse2/muse/plugin.cpp
+++ b/muse2/muse/plugin.cpp
@@ -31,6 +31,7 @@
#include <QButtonGroup>
#include <QCheckBox>
+#include <QInputDialog>
#include <QComboBox>
#include <QCursor>
#include <QDir>
@@ -70,6 +71,9 @@
#include "fastlog.h"
#include "checkbox.h"
#include "verticalmeter.h"
+#include "popupmenu.h"
+#include "menutitleitem.h"
+
#include "audio.h"
#include "al/dsp.h"
@@ -84,10 +88,14 @@
namespace MusEGlobal {
MusECore::PluginList plugins;
+MusECore::PluginGroups plugin_groups;
+QList<QString> plugin_group_names;
+
}
namespace MusEGui {
int PluginDialog::selectedPlugType = 0;
+int PluginDialog::selectedGroup = 0;
QStringList PluginDialog::sortItems = QStringList();
QRect PluginDialog::geometrySave = QRect();
QByteArray PluginDialog::listSave = QByteArray();
@@ -623,6 +631,9 @@ void ladspaControlRange(const LADSPA_Descriptor* plugin, unsigned long port, flo
*max = 1.0;
}
+
+
+
//---------------------------------------------------------
// Plugin
//---------------------------------------------------------
@@ -631,6 +642,7 @@ Plugin::Plugin(QFileInfo* f, const LADSPA_Descriptor* d, bool isDssi, bool isDss
{
_isDssi = isDssi;
_isDssiSynth = isDssiSynth;
+
#ifdef DSSI_SUPPORT
dssi_descr = NULL;
#endif
@@ -1021,6 +1033,40 @@ static void loadPluginDir(const QString& s)
}
}
+
+void PluginGroups::shift_left(int first, int last)
+{
+ for (int i=first; i<=last; i++)
+ replace_group(i, i-1);
+}
+
+void PluginGroups::shift_right(int first, int last)
+{
+ for (int i=last; i>=first; i--)
+ replace_group(i,i+1);
+}
+
+void PluginGroups::erase(int index)
+{
+ for (PluginGroups::iterator it=begin(); it!=end(); it++)
+ {
+ it->remove(index);
+ }
+}
+
+void PluginGroups::replace_group(int old, int now)
+{
+ for (PluginGroups::iterator it=begin(); it!=end(); it++)
+ {
+ if (it->contains(old))
+ {
+ it->remove(old);
+ it->insert(now);
+ }
+ }
+}
+
+
//---------------------------------------------------------
// initPlugins
//---------------------------------------------------------
@@ -2822,14 +2868,23 @@ namespace MusEGui {
PluginDialog::PluginDialog(QWidget* parent)
: QDialog(parent)
{
+ group_info=NULL;
setWindowTitle(tr("MusE: select plugin"));
if(!geometrySave.isNull())
setGeometry(geometrySave);
QVBoxLayout* layout = new QVBoxLayout(this);
-
+
+ tabBar = new QTabBar(this);
+ tabBar->setToolTip(tr("Plugin categories.\nRight-click on tabs to manage.\nRight-click on plugins to add/remove from a category."));
+ tabBar->addTab("All");
+ for (QList<QString>::iterator it=MusEGlobal::plugin_group_names.begin(); it!=MusEGlobal::plugin_group_names.end(); it++)
+ tabBar->addTab(*it);
+
+
pList = new QTreeWidget(this);
+
pList->setColumnCount(12);
// "Note: In order to avoid performance issues, it is recommended that sorting
// is enabled after inserting the items into the tree. Alternatively, you could
@@ -2862,7 +2917,9 @@ PluginDialog::PluginDialog(QWidget* parent)
pList->setSelectionMode(QAbstractItemView::SingleSelection);
pList->setAlternatingRowColors(true);
pList->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ pList->setContextMenuPolicy(Qt::CustomContextMenu);
+ layout->addWidget(tabBar);
layout->addWidget(pList);
//---------------------------------------------------
@@ -2920,6 +2977,23 @@ PluginDialog::PluginDialog(QWidget* parent)
case SEL_M: onlyM->setChecked(true); break;
case SEL_ALL: allPlug->setChecked(true); break;
}
+
+ tabBar->setCurrentIndex(selectedGroup);
+ tabBar->setContextMenuPolicy(Qt::ActionsContextMenu);
+ newGroupAction= new QAction(tr("&create new group"),tabBar);
+ delGroupAction= new QAction(tr("&delete currently selected group"),tabBar);
+ renGroupAction= new QAction(tr("re&name currently selected group"),tabBar);
+ tabBar->addAction(newGroupAction);
+ tabBar->addAction(delGroupAction);
+ tabBar->addAction(renGroupAction);
+
+ if (selectedGroup==0)
+ {
+ delGroupAction->setEnabled(false);
+ renGroupAction->setEnabled(false);
+ }
+ //tabBar->setMovable(true); //not yet. need to find a way to forbid moving the zeroth tab
+
plugSelGroup->setToolTip(tr("Select which types of plugins should be visible in the list.<br>"
"Note that using mono plugins on stereo tracks is not a problem, two will be used in parallel.<br>"
@@ -2968,21 +3042,122 @@ PluginDialog::PluginDialog(QWidget* parent)
connect(pList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), SLOT(accept()));
connect(pList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(enableOkB()));
+ connect(pList, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(plistContextMenu(const QPoint&)));
connect(cancelB, SIGNAL(clicked()), SLOT(reject()));
connect(okB, SIGNAL(clicked()), SLOT(accept()));
- connect(plugSel, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(fillPlugs(QAbstractButton*)));
+ connect(plugSel, SIGNAL(buttonClicked(QAbstractButton*)), SLOT(pluginTypeSelectionChanged(QAbstractButton*)));
+ connect(tabBar, SIGNAL(currentChanged(int)), SLOT(tabChanged(int)));
+ //connect(tabBar, SIGNAL(tabMoved(int,int)), SLOT(tabMoved(int,int))); //not yet. need to find a way to forbid moving the zeroth tab
connect(sortBox, SIGNAL(editTextChanged(const QString&)),SLOT(fillPlugs()));
+ connect(newGroupAction, SIGNAL(activated()), SLOT(newGroup()));
+ connect(delGroupAction, SIGNAL(activated()), SLOT(delGroup()));
+ connect(renGroupAction, SIGNAL(activated()), SLOT(renameGroup()));
sortBox->setFocus();
}
+void PluginDialog::plistContextMenu(const QPoint& point)
+{
+ QTreeWidgetItem* item = pList->currentItem();
+ if (item)
+ {
+ group_info = &MusEGlobal::plugin_groups.get(item->text(1), item->text(2));
+ QMenu* menu = new MusEGui::PopupMenu(this, true);
+ QSignalMapper* mapper = new QSignalMapper(this);
+ menu->addAction(new MusEGui::MenuTitleItem(tr("Associated categories"), menu));
+
+ if (tabBar->count()==1)
+ {
+ QAction* tmp=menu->addAction(tr("You need to define some categories first."));
+ tmp->setEnabled(false);
+ }
+ else
+ {
+ for (int i=1; i<tabBar->count(); i++) // ignore the first tab ("All")
+ {
+ QAction* act=menu->addAction(tabBar->tabText(i));
+ act->setCheckable(true);
+ act->setChecked(group_info->contains(i));
+ connect(act,SIGNAL(toggled(bool)), mapper, SLOT(map()));
+ mapper->setMapping(act, i);
+ }
+ connect(mapper, SIGNAL(mapped(int)), this, SLOT(groupMenuEntryToggled(int)));
+ }
+
+ menu->exec(mapToGlobal(point));
+
+ delete mapper;
+ delete menu;
+
+ if (selectedGroup!=0 && !group_info->contains(selectedGroup)) // we removed the entry from the currently visible group
+ fillPlugs();
+
+ group_info=NULL;
+ }
+}
+
+void PluginDialog::groupMenuEntryToggled(int index)
+{
+ if (group_info)
+ {
+ if (group_info->contains(index))
+ group_info->remove(index);
+ else
+ group_info->insert(index);
+ }
+ else
+ {
+ fprintf(stderr,"THIS SHOULD NEVER HAPPEN: groupMenuEntryToggled called but group_info is NULL!\n");
+ }
+}
+
+
+
//---------------------------------------------------------
// enableOkB
//---------------------------------------------------------
void PluginDialog::enableOkB()
- {
- okB->setEnabled(true);
- }
+{
+ okB->setEnabled(true);
+}
+
+
+void PluginDialog::newGroup()
+{
+ MusEGlobal::plugin_groups.shift_right(selectedGroup+1, tabBar->count());
+ tabBar->insertTab(selectedGroup+1, tr("new group"));
+ MusEGlobal::plugin_group_names.insert(selectedGroup, tr("new group"));
+}
+
+void PluginDialog::delGroup()
+{
+ if (selectedGroup!=0)
+ {
+ MusEGlobal::plugin_groups.erase(selectedGroup);
+ MusEGlobal::plugin_groups.shift_left(selectedGroup+1, tabBar->count());
+ tabBar->removeTab(selectedGroup);
+ MusEGlobal::plugin_group_names.removeAt(selectedGroup-1);
+ }
+}
+
+void PluginDialog::renameGroup()
+{
+ if (selectedGroup!=0)
+ {
+ bool ok;
+ QString newname = QInputDialog::getText(this, tr("Enter the new group name"),
+ tr("Enter the new group name"), QLineEdit::Normal,
+ tabBar->tabText(selectedGroup), &ok);
+ if (ok)
+ {
+ tabBar->setTabText(selectedGroup, newname);
+ MusEGlobal::plugin_group_names.replace(selectedGroup-1, newname);
+ }
+ }
+}
+
+
+
//---------------------------------------------------------
// value
@@ -3042,10 +3217,10 @@ void PluginDialog::reject()
}
//---------------------------------------------------------
-// fillPlugs
+// pluginTypeSelectionChanged
//---------------------------------------------------------
-void PluginDialog::fillPlugs(QAbstractButton* ab)
+void PluginDialog::pluginTypeSelectionChanged(QAbstractButton* ab)
{
if (ab == allPlug)
selectedPlugType = SEL_ALL;
@@ -3058,11 +3233,42 @@ void PluginDialog::fillPlugs(QAbstractButton* ab)
fillPlugs();
}
+void PluginDialog::tabChanged(int index)
+{
+ renGroupAction->setEnabled(index!=0);
+ delGroupAction->setEnabled(index!=0);
+
+ selectedGroup=index;
+ fillPlugs();
+}
+
+void PluginDialog::tabMoved(int from, int to)
+{
+//all the below doesn't work :/
+/* static bool recurse=false;
+
+ if (!recurse)
+ {
+ if (from==0 && to!=0) {recurse=true; tabBar->moveTab(to, from);}
+ if (from!=0 && to==0) {recurse=true; tabBar->moveTab(from, to);}
+ }
+ recurse=false;*/
+
+
+ //if ((from==0 && to!=0) || (from!=0 && to==0)) { tabBar->setMovable(false); tabBar->setMovable(true); }
+ printf("**** %i -> %i\n", from, to);
+
+ //FINDMICH TODO
+}
+
void PluginDialog::fillPlugs()
{
QString type_name;
pList->clear();
- for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i) {
+ okB->setEnabled(false);
+ for (MusECore::iPlugin i = MusEGlobal::plugins.begin(); i != MusEGlobal::plugins.end(); ++i)
+ if (selectedGroup==0 || MusEGlobal::plugin_groups.get(*i).contains(selectedGroup))
+ {
unsigned long ai = i->inports();
unsigned long ao = i->outports();
unsigned long ci = i->controlInPorts();
@@ -4267,6 +4473,191 @@ QWidget* PluginLoader::createWidget(const QString & className, QWidget * parent,
return new Slider(parent, name.toLatin1().constData(), Qt::Horizontal);
return QUiLoader::createWidget(className, parent, name);
-};
+}
} // namespace MusEGui
+
+
+namespace MusEGlobal {
+
+static void writePluginGroupNames(int level, MusECore::Xml& xml)
+{
+ xml.tag(level++, "group_names");
+
+ for (QList<QString>::iterator it=plugin_group_names.begin(); it!=plugin_group_names.end(); it++)
+ xml.strTag(level, "name", *it);
+
+ xml.etag(--level, "group_names");
+}
+
+static void writePluginGroupMap(int level, MusECore::Xml& xml)
+{
+ using MusECore::PluginGroups;
+
+ xml.tag(level++, "group_map");
+
+ for (PluginGroups::iterator it=plugin_groups.begin(); it!=plugin_groups.end(); it++)
+ if (!it.value().empty())
+ {
+ xml.tag(level++, "entry");
+
+ xml.strTag(level, "lib", it.key().first);
+ xml.strTag(level, "label", it.key().second);
+
+ for (QSet<int>::iterator it2=it.value().begin(); it2!=it.value().end(); it2++)
+ xml.intTag(level, "group", *it2);
+
+ xml.etag(--level, "entry");
+ }
+
+ xml.etag(--level, "group_map");
+}
+
+void writePluginGroupConfiguration(int level, MusECore::Xml& xml)
+{
+ xml.tag(level++, "plugin_groups");
+
+ writePluginGroupNames(level, xml);
+ writePluginGroupMap(level, xml);
+
+ xml.etag(--level, "plugin_groups");
+}
+
+static void readPluginGroupNames(MusECore::Xml& xml)
+{
+ plugin_group_names.clear();
+
+ for (;;)
+ {
+ MusECore::Xml::Token token = xml.parse();
+ if (token == MusECore::Xml::Error || token == MusECore::Xml::End)
+ break;
+
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case MusECore::Xml::TagStart:
+ if (tag=="name")
+ plugin_group_names.append(xml.parse1());
+ else
+ xml.unknown("readPluginGroupNames");
+ break;
+
+ case MusECore::Xml::TagEnd:
+ if (tag == "group_names")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
+static void readPluginGroupMap(MusECore::Xml& xml)
+{
+ plugin_groups.clear();
+
+ for (;;)
+ {
+ MusECore::Xml::Token token = xml.parse();
+ if (token == MusECore::Xml::Error || token == MusECore::Xml::End)
+ break;
+
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case MusECore::Xml::TagStart:
+ if (tag=="entry")
+ {
+ QString lib;
+ QString label;
+ QSet<int> groups;
+ bool read_lib=false, read_label=false;
+
+ for (;;)
+ {
+ MusECore::Xml::Token token = xml.parse();
+ if (token == MusECore::Xml::Error || token == MusECore::Xml::End)
+ break;
+
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case MusECore::Xml::TagStart:
+ if (tag=="lib")
+ {
+ lib=xml.parse1();
+ read_lib=true;
+ }
+ else if (tag=="label")
+ {
+ label=xml.parse1();
+ read_label=true;
+ }
+ else if (tag=="group")
+ groups.insert(xml.parseInt());
+ else
+ xml.unknown("readPluginGroupMap");
+ break;
+
+ case MusECore::Xml::TagEnd:
+ if (tag == "entry")
+ goto done_reading_entry;
+
+ default:
+ break;
+ }
+ }
+
+done_reading_entry:
+
+ if (read_lib && read_label)
+ plugin_groups.get(lib,label)=groups;
+ else
+ fprintf(stderr,"ERROR: plugin group map entry without lib or label!\n");
+ }
+ else
+ xml.unknown("readPluginGroupMap");
+ break;
+
+ case MusECore::Xml::TagEnd:
+ if (tag == "group_map")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
+void readPluginGroupConfiguration(MusECore::Xml& xml)
+{
+ for (;;)
+ {
+ MusECore::Xml::Token token = xml.parse();
+ if (token == MusECore::Xml::Error || token == MusECore::Xml::End)
+ break;
+
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case MusECore::Xml::TagStart:
+ if (tag=="group_names")
+ readPluginGroupNames(xml);
+ else if (tag=="group_map")
+ readPluginGroupMap(xml);
+ else
+ xml.unknown("readPluginGroupConfiguration");
+ break;
+
+ case MusECore::Xml::TagEnd:
+ if (tag == "plugin_groups")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
+} // namespace MusEGlobal
diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h
index 39da5edf..ee37c34f 100644
--- a/muse2/muse/plugin.h
+++ b/muse2/muse/plugin.h
@@ -27,8 +27,13 @@
#include <list>
#include <vector>
+#include <QSet>
+#include <QMap>
+#include <QPair>
+#include <QMouseEvent>
#include <QDialog>
+#include <QTabBar>
#include <QFileInfo>
#include <QMainWindow>
#include <QUiLoader>
@@ -71,6 +76,7 @@ class Xml;
class MidiController;
+
//---------------------------------------------------------
// Plugin
//---------------------------------------------------------
@@ -119,7 +125,7 @@ class Plugin {
unsigned long id() const { return _uniqueID; }
QString maker() const { return _maker; }
QString copyright() const { return _copyright; }
- QString lib(bool complete = true) { return complete ? fi.completeBaseName() : fi.baseName(); } // ddskrjo const
+ QString lib(bool complete = true) const { return complete ? fi.completeBaseName() : fi.baseName(); } // ddskrjo const
QString dirPath(bool complete = true) const { return complete ? fi.absolutePath() : fi.path(); }
QString filePath() const { return fi.filePath(); }
QString fileName() const { return fi.fileName(); }
@@ -188,6 +194,22 @@ class Plugin {
typedef std::list<Plugin>::iterator iPlugin;
+
+class PluginGroups : public QMap< QPair<QString, QString>, QSet<int> >
+{
+ public:
+ QSet<int>& get(QString a, QString b) { return (*this)[(QPair<QString,QString>(a,b))]; }
+ QSet<int>& get(const Plugin& p) { return (*this)[(QPair<QString,QString>(p.lib(),p.label()))]; }
+
+ void shift_left(int first, int last);
+ void shift_right(int first, int last);
+ void erase(int index);
+
+ private:
+ void replace_group(int old, int now);
+};
+
+
//---------------------------------------------------------
// PluginList
//---------------------------------------------------------
@@ -529,6 +551,10 @@ class PluginGui : public QMainWindow {
void updateValues();
};
+
+
+
+
//---------------------------------------------------------
// PluginDialog
//---------------------------------------------------------
@@ -538,14 +564,6 @@ enum { SEL_SM, SEL_S, SEL_M, SEL_ALL };
class PluginDialog : public QDialog {
Q_OBJECT
- QTreeWidget* pList;
- QRadioButton* allPlug;
- QRadioButton* onlyM;
- QRadioButton* onlyS;
- QRadioButton* onlySM;
- QPushButton *okB;
- void saveSettings();
-
public:
PluginDialog(QWidget* parent=0);
static MusECore::Plugin* getPlugin(QWidget* parent);
@@ -554,25 +572,56 @@ class PluginDialog : public QDialog {
public slots:
void accept();
void reject();
- void fillPlugs(QAbstractButton*);
- void fillPlugs();
private slots:
void enableOkB();
+ void pluginTypeSelectionChanged(QAbstractButton*);
+ void tabChanged(int);
+ void tabMoved(int,int);
+ void fillPlugs();
+
+ void newGroup();
+ void delGroup();
+ void renameGroup();
+ void plistContextMenu(const QPoint&);
+ void groupMenuEntryToggled(int i);
private:
- QComboBox *sortBox;
+ QComboBox* sortBox;
+ QTabBar* tabBar;
+ QTreeWidget* pList;
+ QRadioButton* allPlug;
+ QRadioButton* onlyM;
+ QRadioButton* onlyS;
+ QRadioButton* onlySM;
+ QPushButton *okB;
+
+ QAction* newGroupAction;
+ QAction* delGroupAction;
+ QAction* renGroupAction;
+
+
+ void saveSettings();
+
static int selectedPlugType;
+ static int selectedGroup; // 0 means "show all"
static QStringList sortItems;
static QRect geometrySave;
static QByteArray listSave;
- };
+
+ QSet<int>* group_info; //holds the group-set of the plugin which shall be affected by the plistContextMenu.
+};
}
namespace MusEGlobal {
extern MusECore::PluginList plugins;
+extern MusECore::PluginGroups plugin_groups;
+extern QList<QString> plugin_group_names;
+
+void writePluginGroupConfiguration(int level, MusECore::Xml& xml);
+void readPluginGroupConfiguration(MusECore::Xml& xml);
}
#endif