Skip to content

Commit

Permalink
Implement Lv2 UI
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesLorenz committed Jul 28, 2024
1 parent 1c86584 commit 6d97a85
Show file tree
Hide file tree
Showing 39 changed files with 1,428 additions and 151 deletions.
3 changes: 3 additions & 0 deletions Brewfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ brew "libsoundio"
brew "libvorbis"
brew "lilv"
brew "lv2"
brew "suil"
brew "serd"
brew "sratom"
brew "pkg-config"
brew "portaudio"
brew "qt@5"
Expand Down
41 changes: 41 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ OPTION(WANT_JACK "Include JACK (Jack Audio Connection Kit) support" ON)
OPTION(WANT_WEAKJACK "Loosely link JACK libraries" ON)
OPTION(WANT_LV2 "Include Lv2 plugins" ON)
OPTION(WANT_SUIL "Include SUIL for LV2 plugin UIs" ON)
OPTION(WANT_SERD "Include SERD for LV2 debugging" ON)
OPTION(WANT_SRATOM "Include SRATOM for LV2 debugging" ON)
OPTION(WANT_MP3LAME "Include MP3/Lame support" ON)
OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON)
OPTION(WANT_PULSEAUDIO "Include PulseAudio support" ON)
Expand Down Expand Up @@ -253,6 +255,11 @@ IF(WANT_LV2)
IF(LV2_FOUND AND LILV_FOUND)
SET(LMMS_HAVE_LV2 TRUE)
SET(STATUS_LV2 "OK")
IF (DEFINED LV2_VERSION AND LV2_VERSION VERSION_GREATER_EQUAL "1.17.2")
SET(LMMS_HAVE_LV2_1_17_2 TRUE)
ELSE()
SET(LMMS_HAVE_LV2_1_17_2 FALSE)
ENDIF()
ELSE()
SET(STATUS_LV2 "not found, install it or set PKG_CONFIG_PATH appropriately")
ENDIF()
Expand All @@ -276,6 +283,38 @@ ELSE(WANT_SUIL)
SET(STATUS_SUIL "not built as requested")
ENDIF(WANT_SUIL)

IF(WANT_SERD)
IF(PKG_CONFIG_FOUND)
PKG_CHECK_MODULES(SERD serd-0)
IF(SERD_FOUND)
SET(LMMS_HAVE_SERD TRUE)
SET(STATUS_SERD "OK")
ELSE()
SET(STATUS_SERD "not found, install it or set PKG_CONFIG_PATH appropriately")
ENDIF()
ELSE()
SET(STATUS_SERD "not found, requires pkg-config")
ENDIF()
ELSE(WANT_SERD)
SET(STATUS_SERD "not built as requested")
ENDIF(WANT_SERD)

IF(WANT_SRATOM)
IF(PKG_CONFIG_FOUND)
PKG_CHECK_MODULES(SRATOM sratom-0)
IF(SRATOM_FOUND)
SET(LMMS_HAVE_SRATOM TRUE)
SET(STATUS_SRATOM "OK")
ELSE()
SET(STATUS_SRATOM "not found, install it or set PKG_CONFIG_PATH appropriately")
ENDIF()
ELSE()
SET(STATUS_SRATOM "not found, requires pkg-config")
ENDIF()
ELSE(WANT_SRATOM)
SET(STATUS_SRATOM "not built as requested")
ENDIF(WANT_SRATOM)

IF(WANT_CALF)
SET(LMMS_HAVE_CALF TRUE)
SET(STATUS_CALF "OK")
Expand Down Expand Up @@ -830,6 +869,8 @@ MESSAGE(
"----------------\n"
"* Lv2 plugins : ${STATUS_LV2}\n"
"* SUIL for plugin UIs : ${STATUS_SUIL}\n"
"* SERD for Lv2 debugging : ${STATUS_SERD}\n"
"* SRATOM for Lv2 debugging : ${STATUS_SRATOM}\n"
"* ZynAddSubFX instrument : ${STATUS_ZYN}\n"
"* Carla Patchbay & Rack : ${STATUS_CARLA}\n"
"* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n"
Expand Down
16 changes: 16 additions & 0 deletions cmake/apple/install_apple.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ for file in "$APP/Contents/lib/lmms/ladspa/"*.so; do
_executables="${_executables} -executable=$_thisfile"
done

# Build a list of shared objects in lib/suil-0
if [ -f "@SUIL_LINK_LIBRARIES@" ]; then
# Try to guess where modules are located (e.g. lib/suil-0) based on lib name
# SUIL_LINK_LIBRARIES: @SUIL_LINK_LIBRARIES@
# SUIL_LIBRARIES: @SUIL_LIBRARIES@
SUIL_MODULES="$(dirname "@SUIL_LINK_LIBRARIES@")/@SUIL_LIBRARIES@"
if [ -d "$SUIL_MODULES" ]; then
mkdir -p "$APP/Contents/Frameworks/suil-0"
for file in "$SUIL_MODULES/"*.dylib; do
# Copy to a predictable location
cp "$file" "$APP/Contents/Frameworks/suil-0/"
_executables="${_executables} -executable=$APP/Contents/Frameworks/suil-0/$(basename "$file")"
done
fi
fi

# Finalize .app
# shellcheck disable=SC2086
macdeployqt "$APP" $_executables
Expand Down
16 changes: 16 additions & 0 deletions cmake/linux/package_linux.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ fi
sed -i 's/.*Exec=.*/Exec=lmms.real/' "$DESKTOPFILE"
echo "X-AppImage-Version=@VERSION@" >> "$DESKTOPFILE"

# Build a list of shared objects in lib/suil-0
if [ -f "@SUIL_LINK_LIBRARIES@" ]; then
# Try to guess where modules are located (e.g. lib/suil-0) based on lib name
# SUIL_LINK_LIBRARIES: @SUIL_LINK_LIBRARIES@
# SUIL_LIBRARIES: @SUIL_LIBRARIES@
SUIL_MODULES="$(dirname "@SUIL_LINK_LIBRARIES@")/@SUIL_LIBRARIES@"
if [ -d "$SUIL_MODULES" ]; then
mkdir -p "${APPDIR}usr/lib/suil-0"
for file in "$SUIL_MODULES/"*.so; do
# Copy to a predictable location
cp "$file" "${APPDIR}usr/lib/suil-0"
executables="${executables} -executable=${APPDIR}usr/lib/suil-0/$(basename "$file")"
done
fi
fi

# Fix linking for soft-linked plugins
for file in "${APPDIR}usr/lib/lmms/"*.so; do
thisfile="${APPDIR}usr/lib/lmms/${file##*/}"
Expand Down
2 changes: 1 addition & 1 deletion include/GuiApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class LMMS_EXPORT GuiApplication : public QObject
{
Q_OBJECT;
public:
explicit GuiApplication();
explicit GuiApplication(int* argc, char*** argv);
~GuiApplication() override;

static GuiApplication* instance();
Expand Down
2 changes: 2 additions & 0 deletions include/InstrumentView.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class LMMS_EXPORT InstrumentView : public PluginView
InstrumentView( Instrument * _instrument, QWidget * _parent );
~InstrumentView() override;

virtual bool isResizable() const { return false; }

Instrument * model()
{
return( castModel<Instrument>() );
Expand Down
7 changes: 6 additions & 1 deletion include/LinkedModelGroupViews.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* LinkedModelGroupViews.h - view for groups of linkable models
*
* Copyright (c) 2019-2019 Johannes Lorenz <j.git$$$lorenz-ho.me, $$$=@>
* Copyright (c) 2019-2024 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
Expand Down Expand Up @@ -29,6 +29,8 @@
#include <memory>
#include <QWidget>

class QVBoxLayout;

namespace lmms
{

Expand Down Expand Up @@ -83,11 +85,14 @@ class LinkedModelGroupView : public QWidget

void removeFocusFromSearchBar();

const LinkedModelGroup* model() const { return m_model; }

private:
class LinkedModelGroup* m_model;

//! column number in surrounding grid in LinkedModelGroupsView
std::size_t m_colNum;
QVBoxLayout* m_vbox;
class ControlLayout* m_layout;
std::map<std::string, std::unique_ptr<class Control>> m_widgets;
};
Expand Down
14 changes: 14 additions & 0 deletions include/Lv2Basics.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ QString qStringFromPortName(const LilvPlugin* plug, const LilvPort* port);
//! Return port name as std::string, everything will be freed automatically
std::string stdStringFromPortName(const LilvPlugin* plug, const LilvPort* port);

//! Control change event, sent through ring buffers for UI updates
struct Lv2UiControlChange
{
uint32_t index;
uint32_t protocol;
uint32_t size;
// Followed immediately by size bytes of data
};

float lv2UiRefreshRate();
float lv2UiScaleFactor();

const bool lv2Dump = true;

} // namespace lmms

#endif // LMMS_HAVE_LV2
Expand Down
1 change: 0 additions & 1 deletion include/Lv2ControlBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ class LMMS_EXPORT Lv2ControlBase : public LinkedModelGroups
const Lv2Proc *control(std::size_t idx) const { return m_procs[idx].get(); }

bool hasGui() const { return m_hasGUI; }
void setHasGui(bool val) { m_hasGUI = val; }

protected:
/*
Expand Down
10 changes: 7 additions & 3 deletions include/Lv2Features.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Lv2Features.h - Lv2Features class
*
* Copyright (c) 2020-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
* Copyright (c) 2020-2024 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
*
* This file is part of LMMS - https://lmms.io
*
Expand Down Expand Up @@ -33,6 +33,7 @@
#include <string_view>
#include <vector>
#include "Lv2Manager.h"
#include <lv2/data-access/data-access.h>


namespace lmms
Expand Down Expand Up @@ -62,7 +63,7 @@ class Lv2Features
//! Register only plugin-common features
void initCommon();
//! Return reference to feature data with given URI featName
void*& operator[](const char* featName);
LV2_Feature& 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
Expand All @@ -73,13 +74,16 @@ class Lv2Features
//! Clear everything
void clear();

//! data features is a UI feature, it is not in the map
LV2_Extension_Data_Feature m_extData;

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<std::string_view, void*> m_featureByUri;
std::map<std::string_view, LV2_Feature> m_featureByUri;
};


Expand Down
17 changes: 16 additions & 1 deletion include/Lv2Manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
#include <string_view>
#include <lilv/lilv.h>

#ifdef LMMS_HAVE_SERD
#include "serd/serd.h"
#ifdef LMMS_HAVE_SRATOM
#include "sratom/sratom.h"
#endif // LMMS_HAVE_SRATOM
#endif // LMMS_HAVE_SERD

#include "Lv2Basics.h"
#include "Lv2UridCache.h"
#include "Lv2UridMap.h"
Expand Down Expand Up @@ -78,7 +85,7 @@ namespace lmms


//! Class to keep track of all LV2 plugins
class Lv2Manager
class LMMS_EXPORT Lv2Manager
{
public:
void initPlugins();
Expand Down Expand Up @@ -149,12 +156,20 @@ class Lv2Manager
//! Since we do not generally support UI right now, this will always return false...
static bool wantUi();

#if defined(LMMS_HAVE_SRATOM) && defined(LMMS_HAVE_SERD)
Sratom* sratom; //!< Atom serialiser
Sratom* ui_sratom; //!< Atom serialiser for UI thread
#endif

private:
// general data
bool m_debug; //!< if set, debug output will be printed
LilvWorld* m_world;
Lv2InfoMap m_lv2InfoMap;
std::set<std::string_view> m_supportedFeatureURIs;
#ifdef LMMS_HAVE_SERD
SerdEnv* env;
#endif

// feature data that are common for all Lv2Proc
UridMap m_uridMap;
Expand Down
4 changes: 2 additions & 2 deletions include/Lv2Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class Lv2Options
//! Mark option as supported
static void supportOption(LV2_URID key);

//! Initialize an option
//! Initialize an option from Cache ID
template<typename Opt, typename Arg>
void initOption(Lv2UridCache::Id key, Arg&& value,
LV2_Options_Context context = LV2_OPTIONS_INSTANCE,
Expand All @@ -88,7 +88,7 @@ class Lv2Options

private:
//! Initialize an option internally
void initOption(LV2_URID key,
void initOption(LV2_URID keyAsUrid,
uint32_t size,
LV2_URID type,
std::shared_ptr<void> value,
Expand Down
Loading

0 comments on commit 6d97a85

Please sign in to comment.