# HG changeset patch # User Chris Cannam # Date 1144677152 0 # Node ID 163f3428bbe09d675fd56b8e7af4f5be2a2f4ee4 # Parent 47fd14e29813c7d4592b19a5602bf2183f68ee5c * Create temporary directory, cleaned up on exit, and use it to store (inter alia) audio samples for the sample-player plugin. * Ensure newly added layers always have unique names * Make sure configure pairs for real-time plugins are stored in the configuration Xml along with parameter & program settings diff -r 47fd14e29813 -r 163f3428bbe0 base/ViewManager.cpp --- a/base/ViewManager.cpp Fri Apr 07 17:50:33 2006 +0000 +++ b/base/ViewManager.cpp Mon Apr 10 13:52:32 2006 +0000 @@ -20,6 +20,11 @@ #include +#include +#include + +#include + // #define DEBUG_VIEW_MANAGER 1 ViewManager::ViewManager() : @@ -45,6 +50,11 @@ SLOT(considerZoomChange(void *, unsigned long, bool))); } +ViewManager::~ViewManager() +{ + if (m_tmpdir != "") deleteTemporaryDirectory(m_tmpdir); +} + unsigned long ViewManager::getGlobalCentreFrame() const { @@ -351,6 +361,94 @@ } } +QString +ViewManager::getTemporaryDirectory() +{ + if (m_tmpdir != "") return m_tmpdir; + + // Generate a temporary directory. Qt4.1 doesn't seem to be able + // to do this for us, and mkdtemp is not standard. This method is + // based on the way glibc does mkdtemp. + + static QString chars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + QString suffix; + int padlen = 6, attempts = 100; + unsigned int r = time(0) ^ getpid(); + + for (int i = 0; i < padlen; ++i) { + suffix += "X"; + } + + for (int j = 0; j < attempts; ++j) { + + unsigned int v = r; + + for (int i = 0; i < padlen; ++i) { + suffix[i] = chars[v % 62]; + v /= 62; + } + + QString candidate = QString("sv_%1").arg(suffix); + + if (QDir::temp().mkpath(candidate)) { + m_tmpdir = QDir::temp().filePath(candidate); + break; + } + + r = r + 7777; + } + + if (m_tmpdir == "") { + std::cerr << "ERROR: ViewManager::getTemporaryDirectory: " + << "Unable to create a temporary directory!" << std::endl; + assert(0); + } + + return m_tmpdir; +} + +void +ViewManager::deleteTemporaryDirectory(QString tmpdir) +{ + if (tmpdir == "") return; + + QDir dir(tmpdir); + dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + + for (unsigned int i = 0; i < dir.count(); ++i) { + + QFileInfo fi(dir.filePath(dir[i])); + + if (fi.isDir()) { + deleteTemporaryDirectory(fi.absoluteFilePath()); + } else { + if (!QFile(fi.absoluteFilePath()).remove()) { + std::cerr << "WARNING: ViewManager::deleteTemporaryDirectory: " + << "Failed to unlink file \"" + << fi.absoluteFilePath().toStdString() << "\"" + << std::endl; + } + } + } + + QString dirname = dir.dirName(); + if (dirname != "") { + if (!dir.cdUp()) { + std::cerr << "WARNING: ViewManager::deleteTemporaryDirectory: " + << "Failed to cd to parent directory of " + << tmpdir.toStdString() << std::endl; + return; + } + if (!dir.rmdir(dirname)) { + std::cerr << "WARNING: ViewManager::deleteTemporaryDirectory: " + << "Failed to remove directory " + << dirname.toStdString() << std::endl; + } + } +} + #ifdef INCLUDE_MOCFILES #include "ViewManager.moc.cpp" #endif diff -r 47fd14e29813 -r 163f3428bbe0 base/ViewManager.h --- a/base/ViewManager.h Fri Apr 07 17:50:33 2006 +0000 +++ b/base/ViewManager.h Mon Apr 10 13:52:32 2006 +0000 @@ -43,6 +43,7 @@ public: ViewManager(); + virtual ~ViewManager(); void setAudioPlaySource(AudioPlaySource *source); @@ -104,6 +105,8 @@ void setOverlayMode(OverlayMode mode); OverlayMode getOverlayMode() const { return m_overlayMode; } + QString getTemporaryDirectory(); + signals: /** Emitted when a widget pans. The originator identifies the widget. */ void centreFrameChanged(void *originator, unsigned long frame, bool locked); @@ -181,6 +184,9 @@ }; OverlayMode m_overlayMode; + + void deleteTemporaryDirectory(QString); + QString m_tmpdir; }; #endif diff -r 47fd14e29813 -r 163f3428bbe0 plugin/DSSIPluginInstance.cpp --- a/plugin/DSSIPluginInstance.cpp Fri Apr 07 17:50:33 2006 +0000 +++ b/plugin/DSSIPluginInstance.cpp Mon Apr 10 13:52:32 2006 +0000 @@ -828,6 +828,8 @@ m_programCacheValid = false; + m_configurationData[key] = value; + std::string qm; // Ignore return values from reserved key configuration calls such diff -r 47fd14e29813 -r 163f3428bbe0 plugin/PluginXml.cpp --- a/plugin/PluginXml.cpp Fri Apr 07 17:50:33 2006 +0000 +++ b/plugin/PluginXml.cpp Mon Apr 10 13:52:32 2006 +0000 @@ -24,6 +24,7 @@ #include #include "vamp-sdk/PluginBase.h" +#include "RealTimePluginInstance.h" #include @@ -63,6 +64,29 @@ .arg(m_plugin->getParameter(i->name)); } + RealTimePluginInstance *rtpi = + dynamic_cast(m_plugin); + if (rtpi) { + std::map configurePairs = + rtpi->getConfigurePairs(); + QString config; + for (std::map::iterator i = configurePairs.begin(); + i != configurePairs.end(); ++i) { + QString key = i->first.c_str(); + QString value = i->second.c_str(); + key.replace(";", "[[SEMICOLON]]"); + key.replace("=", "[[EQUALS]]"); + value.replace(";", "[[SEMICOLON]]"); + value.replace("=", "[[EQUALS]]"); + if (config != "") config += ";"; + config += QString("%1=%2").arg(key).arg(value); + } + if (config != "") { + s += QString("configuration=\"%1\" ") + .arg(encodeEntities(config)); + } + } + s += "/>\n"; return s; } @@ -90,6 +114,29 @@ std::cerr << "WARNING: PluginXml::setParameters: Plugin version does not match (attributes have " << version << ", my version is " << m_plugin->getPluginVersion() << ")" << std::endl; } + RealTimePluginInstance *rtpi = + dynamic_cast(m_plugin); + if (rtpi) { + QString config = attrs.value("configuration"); + if (config != "") { + QStringList configList = config.split(";"); + for (QStringList::iterator i = configList.begin(); + i != configList.end(); ++i) { + QStringList kv = i->split("="); + if (kv.count() < 2) { + std::cerr << "WARNING: PluginXml::setParameters: Malformed configure pair string: \"" << i->toStdString() << "\"" << std::endl; + continue; + } + QString key(kv[0]), value(kv[1]); + key.replace("[[SEMICOLON]]", ";"); + key.replace("[[EQUALS]]", ";"); + value.replace("[[SEMICOLON]]", ";"); + value.replace("[[SEMICOLON]]", ";"); + rtpi->configure(key.toStdString(), value.toStdString()); + } + } + } + if (!m_plugin->getPrograms().empty()) { m_plugin->selectProgram(attrs.value("program").toStdString()); } diff -r 47fd14e29813 -r 163f3428bbe0 plugin/RealTimePluginInstance.h --- a/plugin/RealTimePluginInstance.h Fri Apr 07 17:50:33 2006 +0000 +++ b/plugin/RealTimePluginInstance.h Mon Apr 10 13:52:32 2006 +0000 @@ -28,6 +28,7 @@ #include #include #include +#include class RealTimePluginFactory; @@ -132,6 +133,10 @@ virtual std::string getType() const { return "Real-Time Plugin"; } + virtual std::map getConfigurePairs() { + return m_configurationData; + } + protected: RealTimePluginInstance(RealTimePluginFactory *factory, QString identifier) : m_factory(factory), m_identifier(identifier) { } @@ -139,6 +144,8 @@ RealTimePluginFactory *m_factory; QString m_identifier; + std::map m_configurationData; + friend class PluginFactory; }; diff -r 47fd14e29813 -r 163f3428bbe0 plugin/plugins/SamplePlayer.cpp --- a/plugin/plugins/SamplePlayer.cpp Fri Apr 07 17:50:33 2006 +0000 +++ b/plugin/plugins/SamplePlayer.cpp Mon Apr 10 13:52:32 2006 +0000 @@ -96,7 +96,7 @@ { 2, // DSSI API version &ladspaDescriptor, - 0, // Configure + configure, getProgram, selectProgram, getMidiController, @@ -128,6 +128,7 @@ m_sampleCount(0), m_sampleRate(sampleRate), m_sampleNo(0), + m_samplePath("samples"), m_sampleSearchComplete(false), m_pendingProgramChange(-1) { @@ -207,6 +208,28 @@ delete (SamplePlayer *)handle; } +char * +SamplePlayer::configure(LADSPA_Handle handle, const char *key, const char *value) +{ + if (key && !strcmp(key, "samplepath")) { + + SamplePlayer *player = (SamplePlayer *)handle; + + QMutexLocker locker(&player->m_mutex); + + player->m_samplePath = value; + + if (player->m_sampleSearchComplete) { + player->m_sampleSearchComplete = false; + player->searchSamples(); + } + + return 0; + } + + return strdup("Unknown configure key"); +} + const DSSI_Program_Descriptor * SamplePlayer::getProgram(LADSPA_Handle handle, unsigned long program) { @@ -317,22 +340,25 @@ { if (m_sampleSearchComplete) return; - //!!! -// QString path = "/usr/share/hydrogen/data/drumkits/EasternHop-1"; - std::cerr << "Current working directory is \"" << getcwd(0, 0) << "\"" << std::endl; - QString path = "samples"; - std::cerr << "SamplePlayer::searchSamples: Path is \"" - << path.toLocal8Bit().data() << "\"" << std::endl; + << m_samplePath.toLocal8Bit().data() << "\"" << std::endl; - QDir dir(path, "*.wav"); - for (unsigned int i = 0; i < dir.count(); ++i) { - QFileInfo file(dir.filePath(dir[i])); - m_samples.push_back(std::pair - (file.baseName(), file.filePath())); - std::cerr << "Found: " << dir[i].toLocal8Bit().data() << std::endl; + QStringList dirList = m_samplePath.split(QRegExp("[:;]")); + + for (QStringList::iterator i = dirList.begin(); i != dirList.end(); ++i) { + + QDir dir(*i, "*.wav"); + + for (unsigned int i = 0; i < dir.count(); ++i) { + QFileInfo file(dir.filePath(dir[i])); + if (file.isReadable()) { + m_samples.push_back(std::pair + (file.baseName(), file.filePath())); + std::cerr << "Found: " << dir[i].toLocal8Bit().data() << std::endl; + } + } } m_sampleSearchComplete = true; diff -r 47fd14e29813 -r 163f3428bbe0 plugin/plugins/SamplePlayer.h --- a/plugin/plugins/SamplePlayer.h Fri Apr 07 17:50:33 2006 +0000 +++ b/plugin/plugins/SamplePlayer.h Mon Apr 10 13:52:32 2006 +0000 @@ -62,6 +62,7 @@ static void run(LADSPA_Handle, unsigned long); static void deactivate(LADSPA_Handle); static void cleanup(LADSPA_Handle); + static char *configure(LADSPA_Handle, const char *, const char *); static const DSSI_Program_Descriptor *getProgram(LADSPA_Handle, unsigned long); static void selectProgram(LADSPA_Handle, unsigned long, unsigned long); static int getMidiController(LADSPA_Handle, unsigned long); @@ -90,6 +91,7 @@ int m_velocities[Polyphony]; long m_sampleNo; + QString m_samplePath; QString m_program; std::vector > m_samples; // program name, path bool m_sampleSearchComplete;