File: wrapper.h

package info (click to toggle)
lsp-plugins 1.2.5-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 91,856 kB
  • sloc: cpp: 427,831; xml: 57,779; makefile: 9,961; php: 1,005; sh: 18
file content (215 lines) | stat: -rw-r--r-- 10,875 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * Copyright (C) 2021 Linux Studio Plugins Project <https://lsp-plug.in/>
 *           (C) 2021 Vladimir Sadovnikov <sadko4u@gmail.com>
 *
 * This file is part of lsp-plugin-fw
 * Created on: 20 нояб. 2021 г.
 *
 * lsp-plugin-fw is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * lsp-plugin-fw 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with lsp-plugin-fw. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef LSP_PLUG_IN_PLUG_FW_WRAP_LV2_WRAPPER_H_
#define LSP_PLUG_IN_PLUG_FW_WRAP_LV2_WRAPPER_H_

#include <lsp-plug.in/plug-fw/version.h>

#include <lsp-plug.in/ipc/NativeExecutor.h>
#include <lsp-plug.in/lltl/parray.h>
#include <lsp-plug.in/plug-fw/plug.h>
#include <lsp-plug.in/plug-fw/core/KVTDispatcher.h>
#include <lsp-plug.in/plug-fw/core/KVTStorage.h>
#include <lsp-plug.in/plug-fw/core/SamplePlayer.h>
#include <lsp-plug.in/plug-fw/wrap/lv2/executor.h>
#include <lsp-plug.in/plug-fw/wrap/lv2/extensions.h>
#include <lsp-plug.in/plug-fw/wrap/lv2/ports.h>
#include <lsp-plug.in/plug-fw/wrap/lv2/sink.h>

namespace lsp
{
    namespace lv2
    {
        /**
         * LV2 format plugin wrapper
         */
        class Wrapper: public plug::IWrapper
        {
            public:
                enum state_mode_t
                {
                    SM_SYNC,        // State is in sync with host
                    SM_CHANGED,     // State has been changed
                    SM_REPORTED,    // State change has been reported to the host
                    SM_LOADING      // State has been loaded but still not committed
                };

                enum kvt_parse_flags_t
                {
                    KP_KEY      = 1 << 0,       // KVT key has been deserialized
                    KP_VALUE    = 1 << 1,       // KVT value has been deserialized
                    KP_FLAGS    = 1 << 2        // KVT flags have been deserialized
                };

            private:
                class LV2KVTListener: public core::KVTListener
                {
                    private:
                        lv2::Wrapper *pWrapper;

                    public:
                        explicit LV2KVTListener(lv2::Wrapper *wrapper) { pWrapper = wrapper; }

                    public:
                        virtual void created(core::KVTStorage *storage, const char *id, const core::kvt_param_t *param, size_t pending);
                        virtual void changed(core::KVTStorage *storage, const char *id, const core::kvt_param_t *oval, const core::kvt_param_t *nval, size_t pending);
                        virtual void removed(core::KVTStorage *storage, const char *id, const core::kvt_param_t *param, size_t pending);
                };

            protected:
                lltl::parray<lv2::Port>         vExtPorts;
                lltl::parray<lv2::Port>         vAllPorts;      // List of all created ports, for garbage collection
                lltl::parray<lv2::Port>         vPluginPorts;   // All plugin ports sorted in urid order
                lltl::parray<lv2::Port>         vMeshPorts;
                lltl::parray<lv2::Port>         vFrameBufferPorts;
                lltl::parray<lv2::Port>         vStreamPorts;
                lltl::parray<lv2::Port>         vMidiPorts;
                lltl::parray<lv2::Port>         vOscPorts;
                lltl::parray<lv2::AudioPort>    vAudioPorts;
                lltl::parray<meta::port_t>      vGenMetadata;   // Generated metadata

                lv2::Extensions        *pExt;
                ipc::IExecutor         *pExecutor;      // Executor service
                void                   *pAtomIn;        // Atom input port
                void                   *pAtomOut;       // Atom output port
                float                  *pLatency;       // Latency output port
                size_t                  nPatchReqs;     // Number of patch requests
                size_t                  nStateReqs;     // Number of state requests
                ssize_t                 nSyncTime;      // Synchronization time
                ssize_t                 nSyncSamples;   // Synchronization counter
                ssize_t                 nClients;       // Number of clients
                ssize_t                 nDirectClients; // Number of direct clients
                bool                    bQueueDraw;     // Queue draw request
                bool                    bUpdateSettings;// Settings update
                float                   fSampleRate;
                uint8_t                *pOscPacket;     // OSC packet data
                volatile uatomic_t      nStateMode;     // State change flag
                volatile uatomic_t      nDumpReq;
                uatomic_t               nDumpResp;
                meta::package_t        *pPackage;

                core::KVTStorage        sKVT;
                LV2KVTListener          sKVTListener;
                ipc::Mutex              sKVTMutex;
                core::KVTDispatcher    *pKVTDispatcher;

                core::SamplePlayer     *pSamplePlayer;      // Sample player
                wssize_t                nPlayPosition;      // Sample playback position
                wssize_t                nPlayLength;        // Sample playback length

                LV2_Inline_Display_Image_Surface sSurface;  // Canvas surface

            protected:
                lv2::Port                      *create_port(lltl::parray<plug::IPort> *plugin_ports, const meta::port_t *meta, const char *postfix, bool virt);
                void                            clear_midi_ports();
                void                            save_kvt_parameters();
                void                            restore_kvt_parameters();

                void                            parse_kvt_v1(const LV2_Atom_Object_Body *data, size_t size);
                void                            parse_kvt_v2(const LV2_Atom *data, size_t size);
                bool                            parse_kvt_key(char const **key, const LV2_Atom *value);
                bool                            parse_kvt_flags(size_t *flags, const LV2_Atom *value);
                bool                            parse_kvt_value(core::kvt_param_t *param, const LV2_Atom *value);

                void                            transmit_port_data_to_clients(bool sync_req, bool patch_req, bool state_req);
                void                            transmit_time_position_to_clients();
                void                            transmit_play_position_to_clients();
                void                            transmit_midi_events(lv2::Port *p);
                void                            transmit_osc_events(lv2::Port *p);
                void                            transmit_kvt_events();
                void                            transmit_atoms(size_t samples);

                void                            receive_midi_event(const LV2_Atom_Event *ev);
                void                            receive_raw_osc_event(osc::parse_frame_t *frame);
                void                            receive_atom_object(const LV2_Atom_Event *ev);
                void                            receive_atoms(size_t samples);

                static ssize_t                  compare_ports_by_urid(const lv2::Port *a, const lv2::Port *b);

            public:
                explicit Wrapper(plug::Module *plugin, resource::ILoader *loader, lv2::Extensions *ext);
                virtual ~Wrapper() override;

                status_t                        init(float srate);
                void                            destroy();

            public:
                inline void                     activate()          { pPlugin->activate(); }
                inline void                     deactivate()        { pPlugin->deactivate(); }

                inline void                     connect(size_t id, void *data);
                inline void                     run(size_t samples);
                bool                            change_state_atomic(state_mode_t from, state_mode_t to);

                // State part
                inline void save_state(
                    LV2_State_Store_Function   store,
                    LV2_State_Handle           handle,
                    uint32_t                   flags,
                    const LV2_Feature *const * features
                );

                inline void restore_state(
                    LV2_State_Retrieve_Function retrieve,
                    LV2_State_Handle            handle,
                    uint32_t                    flags,
                    const LV2_Feature *const *  features
                );

                // Job part
                inline void job_run(
                    LV2_Worker_Respond_Handle   handle,
                    LV2_Worker_Respond_Function respond,
                    uint32_t                    size,
                    const void*                 data
                );

                inline void job_response(size_t size, const void *body) {}
                inline void job_end() {}

                // Inline display part
                LV2_Inline_Display_Image_Surface *render_inline_display(size_t width, size_t height);

                lv2::Port                      *port(const char *id);
                lv2::Port                      *port_by_urid(LV2_URID urid);

                void                            connect_direct_ui();

                void                            disconnect_direct_ui();

                inline float                    get_sample_rate() const { return fSampleRate; }

                inline core::KVTDispatcher     *kvt_dispatcher()        { return pKVTDispatcher; }

            public:
                virtual ipc::IExecutor         *executor() override;
                virtual core::KVTStorage       *kvt_lock() override;
                virtual core::KVTStorage       *kvt_trylock() override;
                virtual bool                    kvt_release() override;
                virtual void                    state_changed() override;
                virtual const meta::package_t  *package() const override;
                virtual void                    query_display_draw() override;
        };
    } /* namespace lv2 */
} /* namespace lsp */

#endif /* LSP_PLUG_IN_PLUG_FW_WRAP_LV2_WRAPPER_H_ */