123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- /*
- * Lv2Proc.h - Lv2 processor class
- *
- * Copyright (c) 2019-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 LV2PROC_H
- #define LV2PROC_H
- #include "lmmsconfig.h"
- #ifdef LMMS_HAVE_LV2
- #include <lilv/lilv.h>
- #include <memory>
- #include <QObject>
- #include "Lv2Basics.h"
- #include "Lv2Features.h"
- #include "Lv2Options.h"
- #include "LinkedModelGroups.h"
- #include "MidiEvent.h"
- #include "Plugin.h"
- #include "PluginIssue.h"
- #include "../src/3rdparty/ringbuffer/include/ringbuffer/ringbuffer.h"
- #include "TimePos.h"
- // forward declare port structs/enums
- namespace Lv2Ports
- {
- struct Audio;
- struct PortBase;
- struct AtomSeq;
- enum class Type;
- enum class Flow;
- enum class Vis;
- }
- //! Class representing one Lv2 processor, i.e. one Lv2 handle
- //! For Mono effects, 1 Lv2ControlBase references 2 Lv2Proc
- class Lv2Proc : public LinkedModelGroup
- {
- public:
- static Plugin::PluginTypes check(const LilvPlugin* plugin,
- std::vector<PluginIssue> &issues);
- /*
- ctor/dtor
- */
- Lv2Proc(const LilvPlugin* plugin, Model *parent);
- ~Lv2Proc() override;
- //! Must be checked after ctor or reload
- bool isValid() const { return m_valid; }
- /*
- port access
- */
- struct StereoPortRef
- {
- //! mono port or left port in case of stereo
- Lv2Ports::Audio* m_left = nullptr;
- //! unused, or right port in case of stereo
- Lv2Ports::Audio* m_right = nullptr;
- };
- StereoPortRef& inPorts() { return m_inPorts; }
- const StereoPortRef& inPorts() const { return m_inPorts; }
- StereoPortRef& outPorts() { return m_outPorts; }
- const StereoPortRef& outPorts() const { return m_outPorts; }
- template<class Functor>
- void foreach_port(const Functor& ftor)
- {
- for (std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
- {
- ftor(port.get());
- }
- }
- template<class Functor>
- void foreach_port(const Functor& ftor) const
- {
- for (const std::unique_ptr<Lv2Ports::PortBase>& port : m_ports)
- {
- ftor(port.get());
- }
- }
- //! Debug function to print ports to stdout
- void dumpPorts();
- /*
- utils for the run thread
- */
- //! Copy values from the LMMS core (connected models, MIDI events, ...) into
- //! the respective ports
- void copyModelsFromCore();
- //! Bring values from all ports to the LMMS core
- void copyModelsToCore();
- /**
- * Copy buffer passed by the core into our ports
- * @param buf buffer of sample frames, each sample frame is something like
- * a `float[<number-of-procs> * <channels per proc>]` array.
- * @param firstChan The offset for @p buf where we have to read our
- * first channel.
- * This marks the first sample in each sample frame where we read from.
- * If we are the 2nd of 2 mono procs, this can be greater than 0.
- * @param num Number of channels we must read from @param buf (starting at
- * @p offset)
- */
- void copyBuffersFromCore(const sampleFrame *buf,
- unsigned firstChan, unsigned num, fpp_t frames);
- /**
- * Copy our ports into buffers passed by the core
- * @param buf buffer of sample frames, each sample frame is something like
- * a `float[<number-of-procs> * <channels per proc>]` array.
- * @param firstChan The offset for @p buf where we have to write our
- * first channel.
- * This marks the first sample in each sample frame where we write to.
- * If we are the 2nd of 2 mono procs, this can be greater than 0.
- * @param num Number of channels we must write to @param buf (starting at
- * @p offset)
- */
- void copyBuffersToCore(sampleFrame *buf, unsigned firstChan, unsigned num,
- fpp_t frames) const;
- //! Run the Lv2 plugin instance for @param frames frames
- void run(fpp_t frames);
- void handleMidiInputEvent(const class MidiEvent &event,
- const TimePos &time, f_cnt_t offset);
- /*
- misc
- */
- class AutomatableModel *modelAtPort(const QString &uri); // unused currently
- std::size_t controlCount() const { return LinkedModelGroup::modelNum(); }
- bool hasNoteInput() const;
- protected:
- /*
- load and save
- */
- //! Create ports and instance, connect ports, activate plugin
- void initPlugin();
- //! Deactivate instance
- void shutdownPlugin();
- private:
- bool m_valid = true;
- const LilvPlugin* m_plugin;
- LilvInstance* m_instance;
- Lv2Features m_features;
- Lv2Options m_options;
- // full list of ports
- std::vector<std::unique_ptr<Lv2Ports::PortBase>> m_ports;
- // quick reference to specific, unique ports
- StereoPortRef m_inPorts, m_outPorts;
- Lv2Ports::AtomSeq *m_midiIn = nullptr, *m_midiOut = nullptr;
- // MIDI
- // many things here may be moved into the `Instrument` class
- constexpr const static std::size_t m_maxMidiInputEvents = 1024;
- //! spinlock for the MIDI ringbuffer (for MIDI events going to the plugin)
- std::atomic_flag m_ringLock = ATOMIC_FLAG_INIT;
- //! MIDI ringbuffer (for MIDI events going to the plugin)
- ringbuffer_t<struct MidiInputEvent> m_midiInputBuf;
- //! MIDI ringbuffer reader
- ringbuffer_reader_t<struct MidiInputEvent> m_midiInputReader;
- // other
- static int32_t defaultEvbufSize() { return 1 << 15; /* ardour uses this*/ }
- //! models for the controls, sorted by port symbols
- std::map<std::string, AutomatableModel *> m_connectedModels;
- void initMOptions(); //!< initialize m_options
- 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
- void createPorts();
- //! fill m_ports[portNum] with metadata
- void createPort(std::size_t portNum);
- //! connect m_ports[portNum] with Lv2
- void connectPort(std::size_t num);
- void dumpPort(std::size_t num);
- static bool portIsSideChain(const LilvPlugin* plugin, const LilvPort *port);
- static bool portIsOptional(const LilvPlugin* plugin, const LilvPort *port);
- static AutoLilvNode uri(const char* uriStr);
- };
- #endif // LMMS_HAVE_LV2
- #endif // LV2PROC_H
|