Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Lv2 Urid feature #5517

Merged
merged 10 commits into from
Aug 9, 2020
81 changes: 81 additions & 0 deletions include/Lv2Features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Lv2Features.h - Lv2Features class
*
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef LV2FEATURES_H
#define LV2FEATURES_H

#include "lmmsconfig.h"

#ifdef LMMS_HAVE_LV2

#include <lv2.h>
#include <map>
#include <vector>
#include "Lv2Manager.h"

/**
Feature container

References all available features for a plugin and maps them to their URIs.

The public member functions should be called in descending order:

1. initCommon: map plugin-common features
2. operator[]: map plugin-specific features
3. createFeatureVectors: create the feature vectors required for
lilv_plugin_instantiate
4. access the latter
*/
class Lv2Features
{
public:
//! Return if a feature is supported by LMMS
static bool isFeatureSupported(const char *featName);

Lv2Features();

//! Register only plugin-common features
void initCommon();
//! Return reference to feature data with given URI featName
void*& operator[](const char* featName);
//! Fill m_features and m_featurePointers with all features
void createFeatureVectors();
//! Return LV2_Feature pointer vector, suited for lilv_plugin_instantiate
const LV2_Feature* const* featurePointers() const
{
return m_featurePointers.data();
}

private:
//! feature storage
std::vector<LV2_Feature> m_features;
//! pointers to m_features, required for lilv_plugin_instantiate
std::vector<const LV2_Feature*> m_featurePointers;
//! features + data, ordered by URI
std::map<const char*, void*, Lv2Manager::CmpStr> m_featureByUri;
};

#endif // LMMS_HAVE_LV2

#endif // LV2FEATURES_H
23 changes: 23 additions & 0 deletions include/Lv2Manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@
#ifdef LMMS_HAVE_LV2

#include <map>
#include <set>
#include <lilv/lilv.h>

#include "Lv2Basics.h"
#include "Lv2UridMap.h"
#include "Plugin.h"


Expand Down Expand Up @@ -114,10 +116,31 @@ class Lv2Manager
Iterator begin() { return m_lv2InfoMap.begin(); }
Iterator end() { return m_lv2InfoMap.end(); }

//! strcmp based key comparator for std::set and std::map
struct CmpStr
{
bool operator()(char const *a, char const *b) const;
};

UridMap& uridMap() { return m_uridMap; }
//! Return all
const std::set<const char*, CmpStr>& supportedFeatureURIs() const
{
return m_supportedFeatureURIs;
}
bool isFeatureSupported(const char* featName) const;

private:
// general data
bool m_debug; //!< if set, debug output will be printed
LilvWorld* m_world;
Lv2InfoMap m_lv2InfoMap;
std::set<const char*, CmpStr> m_supportedFeatureURIs;

// feature data that are common for all Lv2Proc
UridMap m_uridMap;

// functions
bool isSubclassOf(const LilvPluginClass *clvss, const char *uriStr);
};

Expand Down
4 changes: 4 additions & 0 deletions include/Lv2Proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <QObject>

#include "Lv2Basics.h"
#include "Lv2Features.h"
#include "LinkedModelGroups.h"
#include "Plugin.h"
#include "PluginIssue.h"
Expand Down Expand Up @@ -156,13 +157,16 @@ class Lv2Proc : public LinkedModelGroup

const LilvPlugin* m_plugin;
LilvInstance* m_instance;
Lv2Features m_features;

std::vector<std::unique_ptr<Lv2Ports::PortBase>> m_ports;
StereoPortRef m_inPorts, m_outPorts;

//! models for the controls, sorted by port symbols
std::map<std::string, AutomatableModel *> m_connectedModels;

void initPluginSpecificFeatures();

//! load a file in the plugin, but don't do anything in LMMS
void loadFileInternal(const QString &file);
//! allocate m_ports, fill all with metadata, and assign meaning of ports
Expand Down
69 changes: 69 additions & 0 deletions include/Lv2UridMap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Lv2UridMap.cpp - Lv2UridMap class
*
* Copyright (c) 2019 Johannes Lorenz <j.git$$$lorenz-ho.me, $$$=@>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#ifndef LV2URIDMAP_H
#define LV2URIDMAP_H

#include "lmmsconfig.h"

#ifdef LMMS_HAVE_LV2

#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
#include <mutex> // TODO: use semaphore, even though this is not realtime critical
#include <unordered_map>
#include <vector>

/**
* Complete implementation of the Lv2 Urid Map extension
*/
class UridMap
{
std::unordered_map<std::string, LV2_URID> m_map;
std::vector<const char*> m_unMap;

//! mutex for both m_map and m_unMap
//! the URID map is global, which is why a mutex is required here
std::mutex m_MapMutex;

LV2_URID_Map m_mapFeature;
LV2_URID_Unmap m_unmapFeature;

LV2_URID m_lastUrid = 0;

public:
//! constructor; will set up the features
UridMap();

//! map feature function
LV2_URID map(const char* uri);
//! unmap feature function
const char* unmap(LV2_URID urid);

// access the features
LV2_URID_Map* mapFeature() { return &m_mapFeature; }
LV2_URID_Unmap* unmapFeature() { return &m_unmapFeature; }
};

#endif // LMMS_HAVE_LV2
#endif // LV2URIDMAP_H
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ set(LMMS_SRCS

core/lv2/Lv2Basics.cpp
core/lv2/Lv2ControlBase.cpp
core/lv2/Lv2Features.cpp
core/lv2/Lv2Ports.cpp
core/lv2/Lv2Proc.cpp
core/lv2/Lv2Manager.cpp
core/lv2/Lv2SubPluginFeatures.cpp
core/lv2/Lv2UridMap.cpp

core/midi/MidiAlsaRaw.cpp
core/midi/MidiAlsaSeq.cpp
Expand Down
97 changes: 97 additions & 0 deletions src/core/lv2/Lv2Features.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Lv2Features.cpp - Lv2Features implementation
*
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/

#include "Lv2Features.h"

#ifdef LMMS_HAVE_LV2

#include <QtGlobal>

#include "Engine.h"
#include "Lv2Manager.h"


bool Lv2Features::isFeatureSupported(const char* featName)
{
return Engine::getLv2Manager()->isFeatureSupported(featName);
}




Lv2Features::Lv2Features()
{
const Lv2Manager* man = Engine::getLv2Manager();
// create (yet empty) map feature URI -> feature
for(const char* uri : man->supportedFeatureURIs())
{
m_featureByUri.emplace(uri, nullptr);
}
}




void Lv2Features::initCommon()
{
Lv2Manager* man = Engine::getLv2Manager();
// init m_featureByUri with the plugin-common features
operator[](LV2_URID__map) = man->uridMap().mapFeature();
operator[](LV2_URID__unmap) = man->uridMap().unmapFeature();
}




void Lv2Features::createFeatureVectors()
{
// create vector of features
for(std::pair<const char* const, void*>& pr : m_featureByUri)
{
Q_ASSERT(pr.second != nullptr);
m_features.push_back(LV2_Feature { pr.first, pr.second });
}

// create pointer vector (for lilv_plugin_instantiate)
m_featurePointers.reserve(m_features.size() + 1);
for(std::size_t i = 0; i < m_features.size(); ++i)
{
m_featurePointers.push_back(&m_features[i]);
}
m_featurePointers.push_back(nullptr);
}




void *&Lv2Features::operator[](const char *featName)
{
auto itr = m_featureByUri.find(featName);
Q_ASSERT(itr != m_featureByUri.end());
return itr->second;
}


#endif // LMMS_HAVE_LV2

20 changes: 20 additions & 0 deletions src/core/lv2/Lv2Manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#ifdef LMMS_HAVE_LV2

#include <cstdlib>
#include <cstring>
#include <lilv/lilv.h>
#include <lv2.h>
#include <QDebug>
Expand All @@ -50,6 +51,9 @@ Lv2Manager::Lv2Manager()

m_world = lilv_world_new();
lilv_world_load_all(m_world);

m_supportedFeatureURIs.insert(LV2_URID__map);
m_supportedFeatureURIs.insert(LV2_URID__unmap);
}


Expand Down Expand Up @@ -133,6 +137,22 @@ void Lv2Manager::initPlugins()



bool Lv2Manager::CmpStr::operator()(const char *a, const char *b) const
{
return std::strcmp(a, b) < 0;
}




bool Lv2Manager::isFeatureSupported(const char *featName) const
{
return m_supportedFeatureURIs.find(featName) != m_supportedFeatureURIs.end();
}




// unused + untested yet
bool Lv2Manager::isSubclassOf(const LilvPluginClass* clvss, const char* uriStr)
{
Expand Down
Loading