ladspa.cpp 6.37 KB
Newer Older
1
2
3
4
/**
 * @file Implementation file for the LADSPA Format. The needed API functions are
 * defined here. Also the access to the Plugin is implemented here.
 */
5
#include "ladspa.h"
6
#include <cstring>
7
#include <interfaces/IPlugin.hpp>
8
#include <interfaces/Ports/IAudioPort.hpp>
Benjamin Heisch's avatar
Benjamin Heisch committed
9
#include <tools/PortHandling.hpp>
10
#include <vector>
Benjamin Heisch's avatar
Benjamin Heisch committed
11

12
using namespace XPlug;
13

14
15
16
17
struct LADSPAHandleDataType
{
  IPlugin* plug;
  const LADSPA_Descriptor* desc;
18
};
19

20
extern "C"
21
{
22
23
24
25
26
27
28
29
30
  /**
   * @brief entrypoint for the LADSPA-Format. In this Function an
   * LADSPA_Descriptor is created, which maps all needed Functioncalls to
   * functionality of the inernal API. Due to the Support of multiple Plugins,
   * multiple Plugins can be registered here.
   * @param index  INdex of a Plugin in the current Binary to load.
   * @return if no Plugin is available, a nullptr is returned otherwhise an
   * Instance which maps the internal API to the LADSPA-Format is returned.
   */
31
32
  const LADSPA_Descriptor* ladspa_descriptor(unsigned long index)
  {
33
34
35
    if (index >=
        GlobalData().getNumberOfRegisteredPlugins()) // index is obvously out of
                                                     // range, so return 0.
36
      return nullptr;
37
38
    PluginPtr plug = GlobalData().getPlugin(index);
    auto desc = new LADSPA_Descriptor();
39
    // add the needed Implementation data to the LADSPA_Descriptor
40
41
    desc->ImplementationData =
      new LADSPAHandleDataType{ GlobalData().getPlugin(index).get(), desc };
42
    /******************* INSTANTIATION**********************/
43
44
    desc->instantiate = [](const LADSPA_Descriptor* descriptor,
                           unsigned long) -> LADSPA_Handle {
45
46
47
48
      // because the ImplementationData and the LADSPA_Handle are the Same, we
      // can return the ImplementationData here. But we the pluginreference in
      // this Function, so we pass that and all other needed Data over the
      // ImplementationData.
49
50
51
52
      auto data =
        static_cast<LADSPAHandleDataType*>(descriptor->ImplementationData);
      data->plug->init();
      return data;
53
54
    };
    desc->activate = [](LADSPA_Handle instance) {
55
56
      auto data = static_cast<LADSPAHandleDataType*>(instance);
      data->plug->activate();
57
58
    };
    desc->deactivate = [](LADSPA_Handle instance) {
59
60
      auto data = static_cast<LADSPAHandleDataType*>(instance);
      data->plug->deactivate();
61
62
    };
    desc->cleanup = [](LADSPA_Handle instance) {
63
      auto data = static_cast<LADSPAHandleDataType*>(instance);
64
65
66
      data->plug
        ->deinit(); // is needed here, because its the opposite to instantiate.
      // free everything.
67
68
69
70
71
72
73
      for (size_t i = 0; i < data->desc->PortCount; i++) {
        delete[] data->desc->PortNames[i];
      }
      delete data->desc->PortNames;
      delete data->desc->PortDescriptors;
      delete data->desc;
      delete data;
74
    };
75
76
    // LADSPA_PROPERTY_HARD_RT_CAPABLE and other stuff, not supported yet.
    desc->Properties = 0;
77

78
    /*********************PORT HANDLING*********************/
79
80
81
82
83
84
    desc->PortCount =
      static_cast<unsigned long>(getAudioChannelCount(plug.get()));
    desc->connect_port = [](LADSPA_Handle instance,
                            unsigned long portIndex,
                            LADSPA_Data* DataLocation) {
      auto data = static_cast<LADSPAHandleDataType*>(instance);
85
86
      // portIndex is in or outputPort
      if (portIndex < getAudioChannelCount(data->plug)) {
87
88
89
90
        getAudioChannelFromIndex(data->plug, portIndex)->feed(DataLocation);
      } else {
        // Not SUpported yet
      }
91
    };
92
    // TODO: When adding Parameter, the have to be mapped to ports here.
93

94
95
    // Ugly allocations, but they are needed... Its just for compatiblity with
    // c.
96
    char** portNamesCArray = new char*[desc->PortCount * sizeof(const char*)];
97
98
99
100
101
    auto portDescripors =
      new LADSPA_PortDescriptor[desc->PortCount *
                                sizeof(LADSPA_PortDescriptor)];
    auto rangeHints =
      new LADSPA_PortRangeHint[desc->PortCount * sizeof(LADSPA_PortDescriptor)];
102
103
104
105
    int curIndex = 0;
    // Iterate through all Audioports and try to allocate Portname, rangehints.
    // Still needed for c compatibility. If someone has an more elegant and more
    // c++ Way, pls make a commit!
106
107
108
109
    iteratePorts<IAudioPort>(
      plug.get(),
      [&portNamesCArray, &portDescripors, &rangeHints, &curIndex](IAudioPort* p,
                                                                  size_t) {
110
        for (size_t i = 0; i < p->size(); i++) {
111
112
113
114
115
116
117
118
          std::string name = p->getPortName().to_string() +
                             (p->at(i)->getName() != ""
                                ? static_cast<std::string>(p->at(i)->getName())
                                : std::to_string(i));
          portNamesCArray[curIndex] = new char[name.length() + 1];
          std::strcpy(portNamesCArray[curIndex], name.c_str());
          rangeHints[curIndex] = { 0, 0, 0 };
          curIndex++;
119
120
        }
        return false;
121
      });
122

123
    desc->PortNames = portNamesCArray;
124

125
126
    desc->PortDescriptors = portDescripors;
    desc->PortRangeHints = rangeHints;
127

128
    /************************INFORMATION***************************/
129
    desc->Copyright = plug->getInfoComponent()->getPluginCopyright().data();
130
    desc->Label = nullptr;
131
132
    desc->Maker = plug->getInfoComponent()->getCreatorName().data();
    desc->Name = plug->getInfoComponent()->getPluginName().data();
133
    // desc->Name = "Hans peter";
134
    desc->UniqueID = plug->getInfoComponent()->getID();
135

136
    desc->run = [](LADSPA_Handle instance, unsigned long SampleCount) {
137
      auto data = static_cast<LADSPAHandleDataType*>(instance);
138
139
      // Set current Samplesize/Count on everyrun, because she can be different.
      // Maybe add some optimizations here.
140
141
      iteratePorts<IAudioPort>(data->plug,
                               [SampleCount](IAudioPort* p, size_t) {
142
                                 p->setSampleCount(SampleCount);
143
144
145
                                 return false;
                               });
      data->plug->processAudio();
146
    };
147

148
149
    /*    desc->run_adding = [](LADSPA_Handle instance, unsigned long
       SampleCount) { LADSPA_Descriptor* desc = (LADSPA_Descriptor*)instance;
150
                IPlugin* plug = (IPlugin*)desc->ImplementationData;
151
152
                plug->processAudio(plug->getPortComponent()->getInputPorts(),
       plug->getPortComponent()->getOutputPorts());
153
            };*/
154
    // desc->set_run_adding_gain;
155
    return desc;
156
  }
157
}