inline void init_plugin_container()

in pedalboard/PluginContainer.h [86:229]


inline void init_plugin_container(py::module &m) {
  py::class_<PluginContainer, Plugin, std::shared_ptr<PluginContainer>>(
      m, "PluginContainer",
      "A generic audio processing plugin that contains zero or more other "
      "plugins. Not intended for direct use.")
      .def(
          py::init([](std::vector<std::shared_ptr<Plugin>> plugins) {
            throw py::type_error(
                "PluginContainer is an abstract base class - don't instantiate "
                "this directly, use its subclasses instead.");
            // This will never be hit, but is required to provide a non-void
            // type to return from this lambda or else the compiler can't do
            // type inference.
            return nullptr;
          }),
          py::arg("plugins"))
      // Implement the Sequence protocol:
      .def(
          "__getitem__",
          [](PluginContainer &s, int i) {
            std::scoped_lock lock(s.mutex);
            if (i < 0)
              i = s.getPlugins().size() + i;
            if (i < 0)
              throw py::index_error("index out of range");
            if (i >= s.getPlugins().size())
              throw py::index_error("index out of range");
            return s.getPlugins()[i];
          },
          py::arg("index"),
          "Get a plugin by its index. Index may be negative. If the index is "
          "out of range, an IndexError will be thrown.")
      .def(
          "__setitem__",
          [](PluginContainer &s, int i, std::shared_ptr<Plugin> plugin) {
            std::scoped_lock lock(s.mutex);
            if (i < 0)
              i = s.getPlugins().size() + i;
            if (i < 0)
              throw py::index_error("index out of range");
            if (i >= s.getPlugins().size())
              throw py::index_error("index out of range");

            if (plugin && !plugin->acceptsAudioInput()) {
              throw std::domain_error(
                  "Provided plugin is an instrument plugin "
                  "that does not accept audio input. Instrument plugins cannot "
                  "be added to Pedalboard, Mix, or Chain objects.");
            }

            s.getPlugins()[i] = plugin;
          },
          py::arg("index"), py::arg("plugin"),
          "Replace a plugin at the specified index. Index may be negative. If "
          "the index is out of range, an IndexError will be thrown.")
      .def(
          "__delitem__",
          [](PluginContainer &s, int i) {
            std::scoped_lock lock(s.mutex);
            if (i < 0)
              i = s.getPlugins().size() + i;
            if (i < 0)
              throw py::index_error("index out of range");
            if (i >= s.getPlugins().size())
              throw py::index_error("index out of range");
            auto &plugins = s.getPlugins();
            plugins.erase(plugins.begin() + i);
          },
          py::arg("index"),
          "Delete a plugin by its index. Index may be negative. If the index "
          "is out of range, an IndexError will be thrown.")
      .def(
          "__len__",
          [](PluginContainer &s) {
            std::scoped_lock lock(s.mutex);
            return s.getPlugins().size();
          },
          "Get the number of plugins in this container.")
      .def(
          "insert",
          [](PluginContainer &s, int i, std::shared_ptr<Plugin> plugin) {
            std::scoped_lock lock(s.mutex);
            if (i < 0)
              i = s.getPlugins().size() + i;
            if (i < 0)
              throw py::index_error("index out of range");
            if (i > s.getPlugins().size())
              throw py::index_error("index out of range");

            if (plugin && !plugin->acceptsAudioInput()) {
              throw std::domain_error(
                  "Provided plugin is an instrument plugin "
                  "that does not accept audio input. Instrument plugins cannot "
                  "be added to Pedalboard, Mix, or Chain objects.");
            }

            auto &plugins = s.getPlugins();
            plugins.insert(plugins.begin() + i, plugin);
          },
          py::arg("index"), py::arg("plugin"),
          "Insert a plugin at the specified index.")
      .def(
          "append",
          [](PluginContainer &s, std::shared_ptr<Plugin> plugin) {
            std::scoped_lock lock(s.mutex);

            if (plugin && !plugin->acceptsAudioInput()) {
              throw std::domain_error(
                  "Provided plugin is an instrument plugin "
                  "that does not accept audio input. Instrument plugins cannot "
                  "be added to Pedalboard, Mix, or Chain objects.");
            }

            s.getPlugins().push_back(plugin);
          },
          py::arg("plugin"), "Append a plugin to the end of this container.")
      .def(
          "remove",
          [](PluginContainer &s, std::shared_ptr<Plugin> plugin) {
            std::scoped_lock lock(s.mutex);
            auto &plugins = s.getPlugins();
            auto position = std::find(plugins.begin(), plugins.end(), plugin);
            if (position == plugins.end())
              throw py::value_error("remove(x): x not in list");
            plugins.erase(position);
          },
          py::arg("plugin"), "Remove a plugin by its value.")
      .def(
          "__iter__",
          [](PluginContainer &s) {
            return py::make_iterator(s.getPlugins().begin(),
                                     s.getPlugins().end());
          },
          py::keep_alive<0, 1>())
      .def(
          "__contains__",
          [](PluginContainer &s, std::shared_ptr<Plugin> plugin) {
            std::scoped_lock lock(s.mutex);
            auto &plugins = s.getPlugins();
            return std::find(plugins.begin(), plugins.end(), plugin) !=
                   plugins.end();
          },
          py::arg("plugin"));
}