Browse Source

Delete unneeded files from DPF; Fix build

tags/1.9.8
falkTX 7 years ago
parent
commit
50cdb57c7c
14 changed files with 0 additions and 26853 deletions
  1. +0
    -18544
      source/modules/dgl/src/Resources.cpp
  2. +0
    -12
      source/modules/dgl/src/Resources.hpp
  3. +0
    -10
      source/modules/dgl/src/Window.cpp
  4. BIN
      source/modules/dgl/src/resources/DejaVuSans.ttf
  5. +0
    -97
      source/modules/dgl/src/resources/LICENSE-DejaVuSans.ttf.txt
  6. +0
    -2431
      source/modules/dgl/src/sofd/libsofd.c
  7. +0
    -175
      source/modules/dgl/src/sofd/libsofd.h
  8. +0
    -593
      source/modules/distrho/src/DistrhoPluginJack.cpp
  9. +0
    -735
      source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp
  10. +0
    -1254
      source/modules/distrho/src/DistrhoPluginLV2.cpp
  11. +0
    -720
      source/modules/distrho/src/DistrhoPluginLV2export.cpp
  12. +0
    -1229
      source/modules/distrho/src/DistrhoPluginVST.cpp
  13. +0
    -511
      source/modules/distrho/src/DistrhoUIDSSI.cpp
  14. +0
    -542
      source/modules/distrho/src/DistrhoUILV2.cpp

+ 0
- 18544
source/modules/dgl/src/Resources.cpp
File diff suppressed because it is too large
View File


+ 0
- 12
source/modules/dgl/src/Resources.hpp View File

@@ -1,12 +0,0 @@
/* (Auto-generated binary data file). */
#ifndef BINARY_DPF_RESOURCES_HPP_INCLUDED
#define BINARY_DPF_RESOURCES_HPP_INCLUDED
namespace dpf_resources
{
extern const char* dejavusans_ttf;
const unsigned int dejavusans_ttf_size = 741536;
};
#endif

+ 0
- 10
source/modules/dgl/src/Window.cpp View File

@@ -1317,16 +1317,6 @@ bool Window::handlePluginSpecial(const bool press, const Key key)
return pData->handlePluginSpecial(press, key);
}

bool Window::handlePluginKeyboard(const bool press, const uint key)
{
return pData->handlePluginKeyboard(press, key);
}

bool Window::handlePluginSpecial(const bool press, const Key key)
{
return pData->handlePluginSpecial(press, key);
}

// -----------------------------------------------------------------------

StandaloneWindow::StandaloneWindow()


BIN
source/modules/dgl/src/resources/DejaVuSans.ttf View File


+ 0
- 97
source/modules/dgl/src/resources/LICENSE-DejaVuSans.ttf.txt View File

@@ -1,97 +0,0 @@
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)

Bitstream Vera Fonts Copyright
------------------------------

Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
a trademark of Bitstream, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute the
Font Software, including without limitation the rights to use, copy, merge,
publish, distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to the
following conditions:

The above copyright and trademark notices and this permission notice shall
be included in all copies of one or more of the Font Software typefaces.

The Font Software may be modified, altered, or added to, and in particular
the designs of glyphs or characters in the Fonts may be modified and
additional glyphs or characters may be added to the Fonts, only if the fonts
are renamed to names not containing either the words "Bitstream" or the word
"Vera".

This License becomes null and void to the extent applicable to Fonts or Font
Software that has been modified and is distributed under the "Bitstream
Vera" names.

The Font Software may be sold as part of a larger software package but no
copy of one or more of the Font Software typefaces may be sold by itself.

THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
FONT SOFTWARE.

Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font Software
without prior written authorization from the Gnome Foundation or Bitstream
Inc., respectively. For further information, contact: fonts at gnome dot
org.

Arev Fonts Copyright
------------------------------

Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and
associated documentation files (the "Font Software"), to reproduce
and distribute the modifications to the Bitstream Vera Font Software,
including without limitation the rights to use, copy, merge, publish,
distribute, and/or sell copies of the Font Software, and to permit
persons to whom the Font Software is furnished to do so, subject to
the following conditions:

The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.

The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Tavmjong Bah" or the word "Arev".

This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Tavmjong Bah Arev" names.

The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.

THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Except as contained in this notice, the name of Tavmjong Bah shall not
be used in advertising or otherwise to promote the sale, use or other
dealings in this Font Software without prior written authorization
from Tavmjong Bah. For further information, contact: tavmjong @ free
. fr.

+ 0
- 2431
source/modules/dgl/src/sofd/libsofd.c
File diff suppressed because it is too large
View File


+ 0
- 175
source/modules/dgl/src/sofd/libsofd.h View File

@@ -1,175 +0,0 @@
/* libSOFD - Simple Open File Dialog [for X11 without toolkit]
*
* Copyright (C) 2014 Robin Gareus <robin@gareus.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#ifndef LIBSOFD_H
#define LIBSOFD_H

#include <X11/Xlib.h>

///////////////////////////////////////////////////////////////////////////////
/* public API */

/** open a file select dialog
* @param dpy X Display connection
* @param parent (optional) if not NULL, become transient for given window
* @param x if >0 set explict initial width of the window
* @param y if >0 set explict initial height of the window
* @return 0 on success
*/
int x_fib_show (Display *dpy, Window parent, int x, int y);

/** force close the dialog.
* This is normally not needed, the dialog closes itself
* when a file is selected or the user cancels selection.
* @param dpy X Display connection
*/
void x_fib_close (Display *dpy);

/** non-blocking X11 event handler.
* It is safe to run this function even if the dialog is
* closed or was not initialized.
*
* @param dpy X Display connection
* @param event the XEvent to process
* @return status
* 0: the event was not for this window, or file-dialog still
* active, or the dialog window is not displayed.
* >0: file was selected, dialog closed
* <0: file selection was cancelled.
*/
int x_fib_handle_events (Display *dpy, XEvent *event);

/** last status of the dialog
* @return >0: file was selected, <0: canceled or inactive. 0: active
*/
int x_fib_status ();

/** query the selected filename
* @return NULL if none set, or allocated string to be free()ed by the called
*/
char *x_fib_filename ();

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
* @param k key to change
* 0: set current dir to display (must end with slash)
* 1: set title of dialog window
* 2: specify a custom X11 font to use
* 3: specify a custom 'places' file to include
* (following gtk-bookmark convention)
* @param v value
* @return 0 on success.
*/
int x_fib_configure (int k, const char *v);

/** customize/configure the dialog before calling \ref x_fib_show
* changes only have any effect if the dialog is not visible.
*
* @param k button to change:
* 1: show hidden files
* 2: show places
* 3: show filter/list all (automatically hidden if there is no
* filter function)
* @param v <0 to hide the button >=0 show button,
* 0: set button-state to not-checked
* 1: set button-state to checked
* >1: retain current state
* @return 0 on success.
*/
int x_fib_cfg_buttons (int k, int v);

/** set custom callback to filter file-names.
* NULL will disable the filter and hide the 'show all' button.
* changes only have any effect if the dialog is not visible.
*
* @param cb callback function to check file
* the callback function is called with the file name (basename only)
* and is expected to return 1 if the file passes the filter
* and 0 if the file should not be listed by default.
* @return 0 on success.
*/
int x_fib_cfg_filter_callback (int (*cb)(const char*));

/* 'recently used' API. x-platform
* NOTE: all functions use a static cache and are not reentrant.
* It is expected that none of these functions are called in
* parallel from different threads.
*/

/** release static resources of 'recently used files'
*/
void x_fib_free_recent ();

/** add an entry to the recently used list
*
* The dialog does not add files automatically on open,
* if the application succeeds to open a selected file,
* this function should be called.
*
* @param path complete path to file
* @param atime time of last use, 0: NOW
* @return -1 on error, number of current entries otherwise
*/
int x_fib_add_recent (const char *path, time_t atime);

/** get a platform specific path to a good location for
* saving the recently used file list.
* (follows XDG_DATA_HOME on Unix, and CSIDL_LOCAL_APPDATA spec)
*
* @param application-name to use to include in file
* @return pointer to static path or NULL
*/
const char *x_fib_recent_file(const char *appname);

/** save the current list of recently used files to the given filename
* (the format is one file per line, filename URL encoded and space separated
* with last-used timestamp)
*
* This function tries to creates the containing directory if it does
* not exist.
*
* @param fn file to save the list to
* @return 0: on success
*/
int x_fib_save_recent (const char *fn);

/** load a recently used file list.
*
* @param fn file to load the list from
* @return 0: on success
*/
int x_fib_load_recent (const char *fn);

/** get number of entries in the current list
* @return number of entries in the recently used list
*/
unsigned int x_fib_recent_count ();

/** get recently used entry at given position
*
* @param i entry to query
* @return pointer to static string
*/
const char *x_fib_recent_at (unsigned int i);

#endif // LIBSOFD_H

+ 0
- 593
source/modules/distrho/src/DistrhoPluginJack.cpp View File

@@ -1,593 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
*
* This program 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.
*
* 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 Lesser General Public License for more details.
*
* For a full copy of the license see the LGPL.txt file
*/

#include "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_HAS_EMBED_UI
# undef DISTRHO_PLUGIN_HAS_UI
# define DISTRHO_PLUGIN_HAS_UI 0
#endif

#if DISTRHO_PLUGIN_HAS_UI
# include "DistrhoUIInternal.hpp"
#else
# include "../extra/Sleep.hpp"
#endif

#include "jack/jack.h"
#include "jack/midiport.h"
#include "jack/transport.h"

#ifndef DISTRHO_OS_WINDOWS
# include <signal.h>
#endif

// -----------------------------------------------------------------------

START_NAMESPACE_DISTRHO

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_STATE
static const setStateFunc setStateCallback = nullptr;
#endif

// -----------------------------------------------------------------------

static volatile bool gCloseSignalReceived = false;

#ifdef DISTRHO_OS_WINDOWS
static BOOL WINAPI winSignalHandler(DWORD dwCtrlType) noexcept
{
if (dwCtrlType == CTRL_C_EVENT)
{
gCloseSignalReceived = true;
return TRUE;
}
return FALSE;
}

static void initSignalHandler()
{
SetConsoleCtrlHandler(winSignalHandler, TRUE);
}
#else
static void closeSignalHandler(int) noexcept
{
gCloseSignalReceived = true;
}

static void initSignalHandler()
{
struct sigaction sig;
memset(&sig, 0, sizeof(sig));

sig.sa_handler = closeSignalHandler;
sig.sa_flags = SA_RESTART;
sigemptyset(&sig.sa_mask);
sigaction(SIGINT, &sig, nullptr);
sigaction(SIGTERM, &sig, nullptr);
}
#endif

// -----------------------------------------------------------------------

#if DISTRHO_PLUGIN_HAS_UI
class PluginJack : public IdleCallback
#else
class PluginJack
#endif
{
public:
PluginJack(jack_client_t* const client)
: fPlugin(),
#if DISTRHO_PLUGIN_HAS_UI
fUI(this, 0, nullptr, setParameterValueCallback, setStateCallback, nullptr, setSizeCallback, fPlugin.getInstancePointer()),
#endif
fClient(client)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0
char strBuf[0xff+1];
strBuf[0xff] = '\0';

# if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "in%i", i+1);
fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
}
# endif
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "out%i", i+1);
fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
# endif
#endif

fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fPlugin.getProgramCount() > 0)
{
fPlugin.loadProgram(0);
# if DISTRHO_PLUGIN_HAS_UI
fUI.programLoaded(0);
# endif
}
# if DISTRHO_PLUGIN_HAS_UI
fProgramChanged = -1;
# endif
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
fLastOutputValues = new float[count];
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged = new bool[count];
std::memset(fParametersChanged, 0, sizeof(bool)*count);
#endif

for (uint32_t i=0; i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
{
fLastOutputValues[i] = fPlugin.getParameterValue(i);
}
else
{
fLastOutputValues[i] = 0.0f;
#if DISTRHO_PLUGIN_HAS_UI
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
#endif
}
}
}
else
{
fLastOutputValues = nullptr;
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged = nullptr;
#endif
}

jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this);
jack_set_sample_rate_callback(fClient, jackSampleRateCallback, this);
jack_set_process_callback(fClient, jackProcessCallback, this);
jack_on_shutdown(fClient, jackShutdownCallback, this);

fPlugin.activate();

jack_activate(fClient);

#if DISTRHO_PLUGIN_HAS_UI
if (const char* const name = jack_get_client_name(fClient))
fUI.setWindowTitle(name);
else
fUI.setWindowTitle(fPlugin.getName());

fUI.exec(this);
#else
while (! gCloseSignalReceived)
d_sleep(1);
#endif
}

~PluginJack()
{
if (fClient != nullptr)
jack_deactivate(fClient);

if (fLastOutputValues != nullptr)
{
delete[] fLastOutputValues;
fLastOutputValues = nullptr;
}

fPlugin.deactivate();

if (fClient == nullptr)
return;

jack_port_unregister(fClient, fPortEventsIn);
fPortEventsIn = nullptr;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
jack_port_unregister(fClient, fPortAudioIns[i]);
fPortAudioIns[i] = nullptr;
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
jack_port_unregister(fClient, fPortAudioOuts[i]);
fPortAudioOuts[i] = nullptr;
}
#endif

jack_client_close(fClient);
}

// -------------------------------------------------------------------

protected:
#if DISTRHO_PLUGIN_HAS_UI
void idleCallback() override
{
if (gCloseSignalReceived)
return fUI.quit();

# if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fProgramChanged >= 0)
{
fUI.programLoaded(fProgramChanged);
fProgramChanged = -1;
}
# endif

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
{
const float value = fPlugin.getParameterValue(i);

if (d_isEqual(fLastOutputValues[i], value))
continue;

fLastOutputValues[i] = value;
fUI.parameterChanged(i, value);
}
else if (fParametersChanged[i])
{
fParametersChanged[i] = false;
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
}
}

fUI.exec_idle();
}
#endif

void jackBufferSize(const jack_nframes_t nframes)
{
fPlugin.setBufferSize(nframes, true);
}

void jackSampleRate(const jack_nframes_t nframes)
{
fPlugin.setSampleRate(nframes, true);
}

void jackProcess(const jack_nframes_t nframes)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
const float* audioIns[DISTRHO_PLUGIN_NUM_INPUTS];

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
audioIns[i] = (const float*)jack_port_get_buffer(fPortAudioIns[i], nframes);
#else
static const float** audioIns = nullptr;
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
float* audioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];

for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
audioOuts[i] = (float*)jack_port_get_buffer(fPortAudioOuts[i], nframes);
#else
static float** audioOuts = nullptr;
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
jack_position_t pos;
fTimePosition.playing = (jack_transport_query(fClient, &pos) == JackTransportRolling);

if (pos.unique_1 == pos.unique_2)
{
fTimePosition.frame = pos.frame;

if (pos.valid & JackTransportBBT)
{
fTimePosition.bbt.valid = true;

fTimePosition.bbt.bar = pos.bar;
fTimePosition.bbt.beat = pos.beat;
fTimePosition.bbt.tick = pos.tick;
fTimePosition.bbt.barStartTick = pos.bar_start_tick;

fTimePosition.bbt.beatsPerBar = pos.beats_per_bar;
fTimePosition.bbt.beatType = pos.beat_type;

fTimePosition.bbt.ticksPerBeat = pos.ticks_per_beat;
fTimePosition.bbt.beatsPerMinute = pos.beats_per_minute;
}
else
fTimePosition.bbt.valid = false;
}
else
{
fTimePosition.bbt.valid = false;
fTimePosition.frame = 0;
}

fPlugin.setTimePosition(fTimePosition);
#endif

void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes);

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{
#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];
#endif
jack_midi_event_t jevent;

for (uint32_t i=0; i < eventCount; ++i)
{
if (jack_midi_event_get(&jevent, midiBuf, i) != 0)
break;

// Check if message is control change on channel 1
if (jevent.buffer[0] == 0xB0 && jevent.size == 3)
{
const uint8_t control = jevent.buffer[1];
const uint8_t value = jevent.buffer[2];

/* NOTE: This is not optimal, we're iterating all parameters on every CC message.
Since the JACK standalone is more of a test tool, this will do for now. */
for (uint32_t j=0, paramCount=fPlugin.getParameterCount(); j < paramCount; ++j)
{
if (fPlugin.isParameterOutput(j))
continue;
if (fPlugin.getParameterMidiCC(j) != control)
continue;

const float scaled = static_cast<float>(value)/127.0f;
const float fvalue = fPlugin.getParameterRanges(j).getUnnormalizedValue(scaled);
fPlugin.setParameterValue(j, fvalue);
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged[j] = true;
#endif
break;
}
}
#if DISTRHO_PLUGIN_WANT_PROGRAMS
// Check if message is program change on channel 1
else if (jevent.buffer[0] == 0xC0 && jevent.size == 2)
{
const uint8_t program = jevent.buffer[1];

if (program < fPlugin.getProgramCount())
{
fPlugin.loadProgram(program);
# if DISTRHO_PLUGIN_HAS_UI
fProgramChanged = program;
# endif
}
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
MidiEvent& midiEvent(midiEvents[midiEventCount++]);

midiEvent.frame = jevent.time;
midiEvent.size = jevent.size;

if (midiEvent.size > MidiEvent::kDataSize)
midiEvent.dataExt = jevent.buffer;
else
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size);
#endif
}

#if DISTRHO_PLUGIN_IS_SYNTH
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount);
#endif
}
#if DISTRHO_PLUGIN_IS_SYNTH
else
{
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0);
}
#else
fPlugin.run(audioIns, audioOuts, nframes);
#endif
}

void jackShutdown()
{
d_stderr("jack has shutdown, quitting now...");
fClient = nullptr;
#if DISTRHO_PLUGIN_HAS_UI
fUI.quit();
#endif
}

// -------------------------------------------------------------------

void setParameterValue(const uint32_t index, const float value)
{
fPlugin.setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
void setState(const char* const key, const char* const value)
{
fPlugin.setState(key, value);
}
#endif

#if DISTRHO_PLUGIN_HAS_UI
void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}
#endif

// -------------------------------------------------------------------

private:
PluginExporter fPlugin;
#if DISTRHO_PLUGIN_HAS_UI
UIExporter fUI;
#endif

jack_client_t* fClient;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
jack_port_t* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
#endif
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#endif
jack_port_t* fPortEventsIn;
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
#endif

// Temporary data
float* fLastOutputValues;

#if DISTRHO_PLUGIN_HAS_UI
// Store DSP changes to send to UI
bool* fParametersChanged;
# if DISTRHO_PLUGIN_WANT_PROGRAMS
int fProgramChanged;
# endif
#endif

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((PluginJack*)ptr)

static int jackBufferSizeCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackBufferSize(nframes);
return 0;
}

static int jackSampleRateCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackSampleRate(nframes);
return 0;
}

static int jackProcessCallback(jack_nframes_t nframes, void* ptr)
{
uiPtr->jackProcess(nframes);
return 0;
}

static void jackShutdownCallback(void* ptr)
{
uiPtr->jackShutdown();
}

static void setParameterValueCallback(void* ptr, uint32_t index, float value)
{
uiPtr->setParameterValue(index, value);
}

#if DISTRHO_PLUGIN_WANT_STATE
static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}
#endif

#if DISTRHO_PLUGIN_HAS_UI
static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}
#endif

#undef uiPtr
};

END_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

int main()
{
USE_NAMESPACE_DISTRHO;

jack_status_t status = jack_status_t(0x0);
jack_client_t* client = jack_client_open(DISTRHO_PLUGIN_NAME, JackNoStartServer, &status);

if (client == nullptr)
{
String errorString;

if (status & JackFailure)
errorString += "Overall operation failed;\n";
if (status & JackInvalidOption)
errorString += "The operation contained an invalid or unsupported option;\n";
if (status & JackNameNotUnique)
errorString += "The desired client name was not unique;\n";
if (status & JackServerStarted)
errorString += "The JACK server was started as a result of this operation;\n";
if (status & JackServerFailed)
errorString += "Unable to connect to the JACK server;\n";
if (status & JackServerError)
errorString += "Communication error with the JACK server;\n";
if (status & JackNoSuchClient)
errorString += "Requested client does not exist;\n";
if (status & JackLoadFailure)
errorString += "Unable to load internal client;\n";
if (status & JackInitFailure)
errorString += "Unable to initialize client;\n";
if (status & JackShmFailure)
errorString += "Unable to access shared memory;\n";
if (status & JackVersionError)
errorString += "Client's protocol version does not match;\n";
if (status & JackBackendError)
errorString += "Backend Error;\n";
if (status & JackClientZombie)
errorString += "Client is being shutdown against its will;\n";

if (errorString.isNotEmpty())
{
errorString[errorString.length()-2] = '.';
d_stderr("Failed to create jack client, reason was:\n%s", errorString.buffer());
}
else
d_stderr("Failed to create jack client, cannot continue!");

return 1;
}

USE_NAMESPACE_DISTRHO;

initSignalHandler();

d_lastBufferSize = jack_get_buffer_size(client);
d_lastSampleRate = jack_get_sample_rate(client);
#if DISTRHO_PLUGIN_HAS_UI
d_lastUiSampleRate = d_lastSampleRate;
#endif

const PluginJack p(client);

return 0;
}

// -----------------------------------------------------------------------

+ 0
- 735
source/modules/distrho/src/DistrhoPluginLADSPA+DSSI.cpp View File

@@ -1,735 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoPluginInternal.hpp"

#if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
# error Cannot use MIDI Output with LADSPA or DSSI
#endif

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# include "dssi/dssi.h"
#else
# include "ladspa/ladspa.h"
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
# error Cannot use MIDI with LADSPA
# endif
# if DISTRHO_PLUGIN_WANT_STATE
# warning LADSPA cannot handle states
# endif
#endif

#if DISTRHO_PLUGIN_WANT_TIMEPOS
# warning LADSPA/DSSI does not support TimePos
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

class PluginLadspaDssi
{
public:
PluginLadspaDssi()
: fPortControls(nullptr),
fLastControlValues(nullptr)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
fPortAudioIns[i] = nullptr;
#else
fPortAudioIns = nullptr;
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
fPortAudioOuts[i] = nullptr;
#else
fPortAudioOuts = nullptr;
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
fPortControls = new LADSPA_Data*[count];
fLastControlValues = new LADSPA_Data[count];

for (uint32_t i=0; i < count; ++i)
{
fPortControls[i] = nullptr;
fLastControlValues[i] = fPlugin.getParameterValue(i);
}
}
else
{
fPortControls = nullptr;
fLastControlValues = nullptr;
}

#if DISTRHO_PLUGIN_WANT_LATENCY
fPortLatency = nullptr;
#endif
}

~PluginLadspaDssi() noexcept
{
if (fPortControls != nullptr)
{
delete[] fPortControls;
fPortControls = nullptr;
}

if (fLastControlValues != nullptr)
{
delete[] fLastControlValues;
fLastControlValues = nullptr;
}
}

// -------------------------------------------------------------------

void ladspa_activate()
{
fPlugin.activate();
}

void ladspa_deactivate()
{
fPlugin.deactivate();
}

// -------------------------------------------------------------------

void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept
{
ulong index = 0;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
if (port == index++)
{
fPortAudioIns[i] = dataLocation;
return;
}
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
if (port == index++)
{
fPortAudioOuts[i] = dataLocation;
return;
}
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
if (port == index++)
{
fPortLatency = dataLocation;
return;
}
#endif

for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (port == index++)
{
fPortControls[i] = dataLocation;
return;
}
}
}

// -------------------------------------------------------------------

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
void ladspa_run(const ulong sampleCount)
{
dssi_run_synth(sampleCount, nullptr, 0);
}

void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount)
#else
void ladspa_run(const ulong sampleCount)
#endif
{
// pre-roll
if (sampleCount == 0)
return updateParameterOutputs();

// Check for updated parameters
float curValue;

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPortControls[i] == nullptr)
continue;

curValue = *fPortControls[i];

if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
{
fLastControlValues[i] = curValue;
fPlugin.setParameterValue(i, curValue);
}
}

#if DISTRHO_PLUGIN_WANT_MIDI_INPUT
// Get MIDI Events
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];

for (uint32_t i=0, j; i < eventCount; ++i)
{
const snd_seq_event_t& seqEvent(events[i]);

// FIXME
if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF)
continue;

switch (seqEvent.type)
{
case SND_SEQ_EVENT_NOTEOFF:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = 0;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_NOTEON:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = seqEvent.data.note.velocity;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_KEYPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel;
midiEvents[j].data[1] = seqEvent.data.note.note;
midiEvents[j].data[2] = seqEvent.data.note.velocity;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_CONTROLLER:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel;
midiEvents[j].data[1] = seqEvent.data.control.param;
midiEvents[j].data[2] = seqEvent.data.control.value;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_CHANPRESS:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 2;
midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel;
midiEvents[j].data[1] = seqEvent.data.control.value;
midiEvents[j].data[2] = 0;
midiEvents[j].data[3] = 0;
break;
case SND_SEQ_EVENT_PITCHBEND:
j = midiEventCount++;
midiEvents[j].frame = seqEvent.time.tick;
midiEvents[j].size = 3;
midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel;
uint16_t tempvalue = seqEvent.data.control.value + 8192;
midiEvents[j].data[1] = tempvalue & 0x7F;
midiEvents[j].data[2] = tempvalue >> 7;
midiEvents[j].data[3] = 0;
break;
}
}

fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount);
#else
fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount);
#endif

updateParameterOutputs();

#if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT
return; // unused
(void)events; (void)eventCount;
#endif
}

// -------------------------------------------------------------------

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
char* dssi_configure(const char* const key, const char* const value)
{
if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX) == 0))
return nullptr;
if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX) == 0))
return nullptr;

fPlugin.setState(key, value);
return nullptr;
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
const DSSI_Program_Descriptor* dssi_get_program(const ulong index)
{
if (index >= fPlugin.getProgramCount())
return nullptr;

static DSSI_Program_Descriptor desc;

desc.Bank = index / 128;
desc.Program = index % 128;
desc.Name = fPlugin.getProgramName(index);

return &desc;
}

void dssi_select_program(const ulong bank, const ulong program)
{
const ulong realProgram(bank * 128 + program);

DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),);

fPlugin.loadProgram(realProgram);

// Update control inputs
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}
}
# endif

int dssi_get_midi_controller_for_port(const ulong port) noexcept
{
const uint32_t parameterOffset = fPlugin.getParameterOffset();

if (port > parameterOffset)
return DSSI_NONE;

const uint8_t midiCC = fPlugin.getParameterMidiCC(port-parameterOffset);

if (midiCC == 0 || midiCC == 32 || midiCC >= 0x78)
return DSSI_NONE;

return DSSI_CC(midiCC);
}
#endif

// -------------------------------------------------------------------

private:
PluginExporter fPlugin;

// LADSPA ports
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
const LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS];
#else
const LADSPA_Data** fPortAudioIns;
#endif
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#else
LADSPA_Data** fPortAudioOuts;
#endif
LADSPA_Data** fPortControls;
#if DISTRHO_PLUGIN_WANT_LATENCY
LADSPA_Data* fPortLatency;
#endif

// Temporary data
LADSPA_Data* fLastControlValues;

// -------------------------------------------------------------------

void updateParameterOutputs()
{
for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterOutput(i))
continue;

fLastControlValues[i] = fPlugin.getParameterValue(i);

if (fPortControls[i] != nullptr)
*fPortControls[i] = fLastControlValues[i];
}

#if DISTRHO_PLUGIN_WANT_LATENCY
if (fPortLatency != nullptr)
*fPortLatency = fPlugin.getLatency();
#endif
}
};

// -----------------------------------------------------------------------

static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate)
{
if (d_lastBufferSize == 0)
d_lastBufferSize = 2048;
d_lastSampleRate = sampleRate;

return new PluginLadspaDssi();
}

#define instancePtr ((PluginLadspaDssi*)instance)

static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation)
{
instancePtr->ladspa_connect_port(port, dataLocation);
}

static void ladspa_activate(LADSPA_Handle instance)
{
instancePtr->ladspa_activate();
}

static void ladspa_run(LADSPA_Handle instance, ulong sampleCount)
{
instancePtr->ladspa_run(sampleCount);
}

static void ladspa_deactivate(LADSPA_Handle instance)
{
instancePtr->ladspa_deactivate();
}

static void ladspa_cleanup(LADSPA_Handle instance)
{
delete instancePtr;
}

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
# if DISTRHO_PLUGIN_WANT_STATE
static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value)
{
return instancePtr->dssi_configure(key, value);
}
# endif

# if DISTRHO_PLUGIN_WANT_PROGRAMS
static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index)
{
return instancePtr->dssi_get_program(index);
}

static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program)
{
instancePtr->dssi_select_program(bank, program);
}
# endif

static int dssi_get_midi_controller_for_port(LADSPA_Handle instance, ulong port)
{
return instancePtr->dssi_get_midi_controller_for_port(port);
}

# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount)
{
instancePtr->dssi_run_synth(sampleCount, events, eventCount);
}
# endif
#endif

#undef instancePtr

// -----------------------------------------------------------------------

static LADSPA_Descriptor sLadspaDescriptor = {
/* UniqueID */ 0,
/* Label */ nullptr,
#if DISTRHO_PLUGIN_IS_RT_SAFE
/* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE,
#else
/* Properties */ 0x0,
#endif
/* Name */ nullptr,
/* Maker */ nullptr,
/* Copyright */ nullptr,
/* PortCount */ 0,
/* PortDescriptors */ nullptr,
/* PortNames */ nullptr,
/* PortRangeHints */ nullptr,
/* ImplementationData */ nullptr,
ladspa_instantiate,
ladspa_connect_port,
ladspa_activate,
ladspa_run,
/* run_adding */ nullptr,
/* set_run_adding_gain */ nullptr,
ladspa_deactivate,
ladspa_cleanup
};

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
static DSSI_Descriptor sDssiDescriptor = {
1,
&sLadspaDescriptor,
# if DISTRHO_PLUGIN_WANT_STATE
dssi_configure,
# else
/* configure */ nullptr,
# endif
# if DISTRHO_PLUGIN_WANT_PROGRAMS
dssi_get_program,
dssi_select_program,
# else
/* get_program */ nullptr,
/* select_program */ nullptr,
# endif
dssi_get_midi_controller_for_port,
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
dssi_run_synth,
# else
/* run_synth */ nullptr,
# endif
/* run_synth_adding */ nullptr,
/* run_multiple_synths */ nullptr,
/* run_multiple_synths_adding */ nullptr,
nullptr, nullptr
};
#endif

// -----------------------------------------------------------------------

class DescriptorInitializer
{
public:
DescriptorInitializer()
{
// Create dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

// Get port count, init
ulong port = 0;
ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount();
#if DISTRHO_PLUGIN_WANT_LATENCY
portCount += 1;
#endif
const char** const portNames = new const char*[portCount];
LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount];
LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount];

// Set ports
#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port)
{
const AudioPort& aport(plugin.getAudioPort(true, i));

portNames[port] = strdup(aport.name);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT;

portRangeHints[port].HintDescriptor = 0x0;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port)
{
const AudioPort& aport(plugin.getAudioPort(false, i));

portNames[port] = strdup(aport.name);
portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT;

portRangeHints[port].HintDescriptor = 0x0;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
}
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
// Set latency port
portNames[port] = strdup("_latency");
portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT;
portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER;
portRangeHints[port].LowerBound = 0.0f;
portRangeHints[port].UpperBound = 1.0f;
++port;
#endif

for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port)
{
portNames[port] = strdup((const char*)plugin.getParameterName(i));
portDescriptors[port] = LADSPA_PORT_CONTROL;

if (plugin.isParameterOutput(i))
portDescriptors[port] |= LADSPA_PORT_OUTPUT;
else
portDescriptors[port] |= LADSPA_PORT_INPUT;

{
const ParameterRanges& ranges(plugin.getParameterRanges(i));
const float defValue(ranges.def);

portRangeHints[port].HintDescriptor = LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE;
portRangeHints[port].LowerBound = ranges.min;
portRangeHints[port].UpperBound = ranges.max;

if (defValue == 0.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0;
else if (defValue == 1.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1;
else if (defValue == 100.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100;
else if (defValue == 440.0f)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440;
else if (ranges.min == defValue)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
else if (ranges.max == defValue)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
else
{
const float middleValue = ranges.min/2.0f + ranges.max/2.0f;
const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;
const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f;

if (defValue < middleLow)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
else if (defValue > middleHigh)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
else
portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
}
}

{
const uint32_t hints(plugin.getParameterHints(i));

if (hints & kParameterIsBoolean)
{
portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED;
}
else
{
if (hints & kParameterIsInteger)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER;
if (hints & kParameterIsLogarithmic)
portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
}
}
}

// Set data
sLadspaDescriptor.UniqueID = plugin.getUniqueId();
sLadspaDescriptor.Label = strdup(plugin.getLabel());
sLadspaDescriptor.Name = strdup(plugin.getName());
sLadspaDescriptor.Maker = strdup(plugin.getMaker());
sLadspaDescriptor.Copyright = strdup(plugin.getLicense());
sLadspaDescriptor.PortCount = portCount;
sLadspaDescriptor.PortNames = portNames;
sLadspaDescriptor.PortDescriptors = portDescriptors;
sLadspaDescriptor.PortRangeHints = portRangeHints;
}

~DescriptorInitializer()
{
if (sLadspaDescriptor.Label != nullptr)
{
std::free((void*)sLadspaDescriptor.Label);
sLadspaDescriptor.Label = nullptr;
}

if (sLadspaDescriptor.Name != nullptr)
{
std::free((void*)sLadspaDescriptor.Name);
sLadspaDescriptor.Name = nullptr;
}

if (sLadspaDescriptor.Maker != nullptr)
{
std::free((void*)sLadspaDescriptor.Maker);
sLadspaDescriptor.Maker = nullptr;
}

if (sLadspaDescriptor.Copyright != nullptr)
{
std::free((void*)sLadspaDescriptor.Copyright);
sLadspaDescriptor.Copyright = nullptr;
}

if (sLadspaDescriptor.PortDescriptors != nullptr)
{
delete[] sLadspaDescriptor.PortDescriptors;
sLadspaDescriptor.PortDescriptors = nullptr;
}

if (sLadspaDescriptor.PortRangeHints != nullptr)
{
delete[] sLadspaDescriptor.PortRangeHints;
sLadspaDescriptor.PortRangeHints = nullptr;
}

if (sLadspaDescriptor.PortNames != nullptr)
{
for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i)
{
if (sLadspaDescriptor.PortNames[i] != nullptr)
std::free((void*)sLadspaDescriptor.PortNames[i]);
}

delete[] sLadspaDescriptor.PortNames;
sLadspaDescriptor.PortNames = nullptr;
}
}
};

static DescriptorInitializer sDescInit;

// -----------------------------------------------------------------------

END_NAMESPACE_DISTRHO

DISTRHO_PLUGIN_EXPORT
const LADSPA_Descriptor* ladspa_descriptor(ulong index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLadspaDescriptor : nullptr;
}

#ifdef DISTRHO_PLUGIN_TARGET_DSSI
DISTRHO_PLUGIN_EXPORT
const DSSI_Descriptor* dssi_descriptor(ulong index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sDssiDescriptor : nullptr;
}
#endif

// -----------------------------------------------------------------------

+ 0
- 1254
source/modules/distrho/src/DistrhoPluginLV2.cpp
File diff suppressed because it is too large
View File


+ 0
- 720
source/modules/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -1,720 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoPluginInternal.hpp"

#include "lv2/atom.h"
#include "lv2/buf-size.h"
#include "lv2/data-access.h"
#include "lv2/instance-access.h"
#include "lv2/midi.h"
#include "lv2/options.h"
#include "lv2/port-props.h"
#include "lv2/presets.h"
#include "lv2/resize-port.h"
#include "lv2/state.h"
#include "lv2/time.h"
#include "lv2/ui.h"
#include "lv2/units.h"
#include "lv2/urid.h"
#include "lv2/worker.h"
#include "lv2/lv2_kxstudio_properties.h"
#include "lv2/lv2_programs.h"

#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
# include "mod-license.h"
#endif

#include <fstream>
#include <iostream>

#ifndef DISTRHO_PLUGIN_URI
# error DISTRHO_PLUGIN_URI undefined!
#endif

#ifndef DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE
# define DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE 2048
#endif

#ifndef DISTRHO_PLUGIN_USES_MODGUI
# define DISTRHO_PLUGIN_USES_MODGUI 0
#endif

#if DISTRHO_PLUGIN_HAS_EMBED_UI
# if DISTRHO_OS_HAIKU
# define DISTRHO_LV2_UI_TYPE "BeUI"
# elif DISTRHO_OS_MAC
# define DISTRHO_LV2_UI_TYPE "CocoaUI"
# elif DISTRHO_OS_WINDOWS
# define DISTRHO_LV2_UI_TYPE "WindowsUI"
# else
# define DISTRHO_LV2_UI_TYPE "X11UI"
# endif
#else
# define DISTRHO_LV2_UI_TYPE "UI"
#endif

#define DISTRHO_LV2_USE_EVENTS_IN (DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_TIMEPOS || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))
#define DISTRHO_LV2_USE_EVENTS_OUT (DISTRHO_PLUGIN_WANT_MIDI_OUTPUT || (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI))

// -----------------------------------------------------------------------

DISTRHO_PLUGIN_EXPORT
void lv2_generate_ttl(const char* const basename)
{
USE_NAMESPACE_DISTRHO

// Dummy plugin to get data from
d_lastBufferSize = 512;
d_lastSampleRate = 44100.0;
PluginExporter plugin;
d_lastBufferSize = 0;
d_lastSampleRate = 0.0;

String pluginDLL(basename);
String pluginTTL(pluginDLL + ".ttl");

#if DISTRHO_PLUGIN_HAS_UI
String pluginUI(pluginDLL);
# if ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
pluginUI.truncate(pluginDLL.rfind("_dsp"));
pluginUI += "_ui";
const String uiTTL(pluginUI + ".ttl");
# endif
#endif

// ---------------------------------------------

{
std::cout << "Writing manifest.ttl..."; std::cout.flush();
std::fstream manifestFile("manifest.ttl", std::ios::out);

String manifestString;
manifestString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
manifestString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
#if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
#endif
#if DISTRHO_PLUGIN_HAS_UI
manifestString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
#endif
manifestString += "\n";

manifestString += "<" DISTRHO_PLUGIN_URI ">\n";
manifestString += " a lv2:Plugin ;\n";
manifestString += " lv2:binary <" + pluginDLL + "." DISTRHO_DLL_EXTENSION "> ;\n";
#if DISTRHO_PLUGIN_USES_MODGUI
manifestString += " rdfs:seeAlso <" + pluginTTL + "> ,\n";
manifestString += " <modgui.ttl> .\n";
#else
manifestString += " rdfs:seeAlso <" + pluginTTL + "> .\n";
#endif
manifestString += "\n";

#if DISTRHO_PLUGIN_HAS_UI
manifestString += "<" DISTRHO_UI_URI ">\n";
manifestString += " a ui:" DISTRHO_LV2_UI_TYPE " ;\n";
manifestString += " ui:binary <" + pluginUI + "." DISTRHO_DLL_EXTENSION "> ;\n";
# if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
manifestString += "\n";
manifestString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
manifestString += " ui:showInterface ,\n";
manifestString += " <" LV2_PROGRAMS__Interface "> ;\n";
# else
manifestString += " ui:showInterface ;\n";
# endif
manifestString += "\n";
# if DISTRHO_PLUGIN_HAS_EMBED_UI
manifestString += " lv2:optionalFeature ui:noUserResize ,\n";
manifestString += " ui:resize ,\n";
manifestString += " ui:touch ;\n";
manifestString += "\n";
# endif
manifestString += " lv2:requiredFeature <" LV2_DATA_ACCESS_URI "> ,\n";
manifestString += " <" LV2_INSTANCE_ACCESS_URI "> ,\n";
manifestString += " <" LV2_OPTIONS__options "> ,\n";
manifestString += " <" LV2_URID__map "> .\n";
# else
manifestString += " rdfs:seeAlso <" + uiTTL + "> .\n";
# endif
manifestString += "\n";
#endif

#if DISTRHO_PLUGIN_WANT_PROGRAMS
const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");

char strBuf[0xff+1];
strBuf[0xff] = '\0';

String presetString;

// Presets
for (uint32_t i = 0; i < plugin.getProgramCount(); ++i)
{
std::snprintf(strBuf, 0xff, "%03i", i+1);

presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";
presetString += " a pset:Preset ;\n";
presetString += " lv2:appliesTo <" DISTRHO_PLUGIN_URI "> ;\n";
presetString += " rdfs:label \"" + plugin.getProgramName(i) + "\" ;\n";
presetString += " rdfs:seeAlso <presets.ttl> .\n";
presetString += "\n";

manifestString += presetString;
}
#endif

manifestFile << manifestString << std::endl;
manifestFile.close();
std::cout << " done!" << std::endl;
}

// ---------------------------------------------

{
std::cout << "Writing " << pluginTTL << "..."; std::cout.flush();
std::fstream pluginFile(pluginTTL, std::ios::out);

String pluginString;

// header
#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += "@prefix atom: <" LV2_ATOM_PREFIX "> .\n";
#endif
pluginString += "@prefix doap: <http://usefulinc.com/ns/doap#> .\n";
pluginString += "@prefix foaf: <http://xmlns.com/foaf/0.1/> .\n";
pluginString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
#ifdef DISTRHO_PLUGIN_BRAND
pluginString += "@prefix mod: <http://moddevices.com/ns/mod#> .\n";
#endif
pluginString += "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n";
pluginString += "@prefix rsz: <" LV2_RESIZE_PORT_PREFIX "> .\n";
#if DISTRHO_PLUGIN_HAS_UI
pluginString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
#endif
pluginString += "@prefix unit: <" LV2_UNITS_PREFIX "> .\n";
pluginString += "\n";

// plugin
pluginString += "<" DISTRHO_PLUGIN_URI ">\n";
#ifdef DISTRHO_PLUGIN_LV2_CATEGORY
pluginString += " a " DISTRHO_PLUGIN_LV2_CATEGORY ", lv2:Plugin ;\n";
#elif DISTRHO_PLUGIN_IS_SYNTH
pluginString += " a lv2:InstrumentPlugin, lv2:Plugin ;\n";
#else
pluginString += " a lv2:Plugin ;\n";
#endif
pluginString += "\n";

// extensionData
pluginString += " lv2:extensionData <" LV2_STATE__interface "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_OPTIONS__interface "> ";
pluginString += ",\n <" LV2_WORKER__interface "> ";
#endif
#if DISTRHO_PLUGIN_WANT_PROGRAMS
pluginString += ",\n <" LV2_PROGRAMS__Interface "> ";
#endif
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
pluginString += ",\n <" MOD_LICENSE__interface "> ";
#endif
pluginString += ";\n\n";

// optionalFeatures
#if DISTRHO_PLUGIN_IS_RT_SAFE
pluginString += " lv2:optionalFeature <" LV2_CORE__hardRTCapable "> ,\n";
pluginString += " <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
#else
pluginString += " lv2:optionalFeature <" LV2_BUF_SIZE__boundedBlockLength "> ;\n";
#endif
pluginString += "\n";

// requiredFeatures
pluginString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ";
pluginString += ",\n <" LV2_URID__map "> ";
#if DISTRHO_PLUGIN_WANT_STATE
pluginString += ",\n <" LV2_WORKER__schedule "> ";
#endif
#ifdef DISTRHO_PLUGIN_LICENSED_FOR_MOD
pluginString += ",\n <" MOD_LICENSE__feature "> ";
#endif
pluginString += ";\n\n";

// UI
#if DISTRHO_PLUGIN_HAS_UI
pluginString += " ui:ui <" DISTRHO_UI_URI "> ;\n";
pluginString += "\n";
#endif

{
uint32_t portIndex = 0;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(true, i));

if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:InputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:AudioPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
pluginString += " lv2:name \"" + port.name + "\" ;\n";

if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";

if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS)
pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}
pluginString += "\n";
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++portIndex)
{
const AudioPort& port(plugin.getAudioPort(false, i));

if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

if (port.hints & kAudioPortIsCV)
pluginString += " a lv2:OutputPort, lv2:CVPort ;\n";
else
pluginString += " a lv2:OutputPort, lv2:AudioPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:symbol \"lv2_" + port.symbol + "\" ;\n";
pluginString += " lv2:name \"" + port.name + "\" ;\n";

if (port.hints & kAudioPortIsSidechain)
pluginString += " lv2:portProperty lv2:isSideChain;\n";

if (i+1 == DISTRHO_PLUGIN_NUM_OUTPUTS)
pluginString += " ] ;\n";
else
pluginString += " ] ,\n";
}
pluginString += "\n";
#endif

#if DISTRHO_LV2_USE_EVENTS_IN
pluginString += " lv2:port [\n";
pluginString += " a lv2:InputPort, atom:AtomPort ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Events Input\" ;\n";
pluginString += " lv2:symbol \"lv2_events_in\" ;\n";
pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_MIDI_INPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_TIMEPOS
pluginString += " atom:supports <" LV2_TIME__Position "> ;\n";
# endif
pluginString += " ] ;\n\n";
++portIndex;
#endif

#if DISTRHO_LV2_USE_EVENTS_OUT
pluginString += " lv2:port [\n";
pluginString += " a lv2:OutputPort, atom:AtomPort ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Events Output\" ;\n";
pluginString += " lv2:symbol \"lv2_events_out\" ;\n";
pluginString += " rsz:minimumSize " + String(DISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE) + " ;\n";
pluginString += " atom:bufferType atom:Sequence ;\n";
# if (DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI)
pluginString += " atom:supports <" LV2_ATOM__String "> ;\n";
# endif
# if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
pluginString += " atom:supports <" LV2_MIDI__MidiEvent "> ;\n";
# endif
pluginString += " ] ;\n\n";
++portIndex;
#endif

#if DISTRHO_PLUGIN_WANT_LATENCY
pluginString += " lv2:port [\n";
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"Latency\" ;\n";
pluginString += " lv2:symbol \"lv2_latency\" ;\n";
pluginString += " lv2:designation lv2:latency ;\n";
pluginString += " lv2:portProperty lv2:reportsLatency, lv2:integer, <" LV2_PORT_PROPS__notOnGUI "> ;\n";
pluginString += " ] ;\n\n";
++portIndex;
#endif

for (uint32_t i=0, count=plugin.getParameterCount(); i < count; ++i, ++portIndex)
{
if (i == 0)
pluginString += " lv2:port [\n";
else
pluginString += " [\n";

if (plugin.isParameterOutput(i))
pluginString += " a lv2:OutputPort, lv2:ControlPort ;\n";
else
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";

bool designated = false;

// designation
if (! plugin.isParameterOutput(i))
{
switch (plugin.getParameterDesignation(i))
{
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
designated = true;
pluginString += " lv2:name \"Enabled\" ;\n";
pluginString += " lv2:symbol \"lv2_enabled\" ;\n";
pluginString += " lv2:default 1 ;\n";
pluginString += " lv2:minimum 0 ;\n";
pluginString += " lv2:maximum 1 ;\n";
pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
pluginString += " lv2:designation lv2:enabled ;\n";
break;
}
}

// name and symbol
if (! designated)
{
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

String symbol(plugin.getParameterSymbol(i));

if (symbol.isEmpty())
symbol = "lv2_port_" + String(portIndex-1);

pluginString += " lv2:symbol \"" + symbol + "\" ;\n";
}

// ranges
if (! designated)
{
const ParameterRanges& ranges(plugin.getParameterRanges(i));

if (plugin.getParameterHints(i) & kParameterIsInteger)
{
if (! plugin.isParameterOutput(i))
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
}
else
{
if (! plugin.isParameterOutput(i))
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
}
}

// unit
if (! designated)
{
const String& unit(plugin.getParameterUnit(i));

if (! unit.isEmpty())
{
if (unit == "db" || unit == "dB")
{
pluginString += " unit:unit unit:db ;\n";
}
else if (unit == "hz" || unit == "Hz")
{
pluginString += " unit:unit unit:hz ;\n";
}
else if (unit == "khz" || unit == "kHz")
{
pluginString += " unit:unit unit:khz ;\n";
}
else if (unit == "mhz" || unit == "mHz")
{
pluginString += " unit:unit unit:mhz ;\n";
}
else if (unit == "ms")
{
pluginString += " unit:unit unit:ms ;\n";
}
else if (unit == "s")
{
pluginString += " unit:unit unit:s ;\n";
}
else if (unit == "%")
{
pluginString += " unit:unit unit:pc ;\n";
}
else
{
pluginString += " unit:unit [\n";
pluginString += " rdfs:label \"" + unit + "\" ;\n";
pluginString += " unit:symbol \"" + unit + "\" ;\n";
pluginString += " unit:render \"%f " + unit + "\" ;\n";
pluginString += " ] ;\n";
}
}
}

// hints
if (! designated)
{
const uint32_t hints(plugin.getParameterHints(i));

if (hints & kParameterIsBoolean)
pluginString += " lv2:portProperty lv2:toggled ;\n";
if (hints & kParameterIsInteger)
pluginString += " lv2:portProperty lv2:integer ;\n";
if (hints & kParameterIsLogarithmic)
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__logarithmic "> ;\n";
if ((hints & kParameterIsAutomable) == 0 && ! plugin.isParameterOutput(i))
{
pluginString += " lv2:portProperty <" LV2_PORT_PROPS__expensive "> ,\n";
pluginString += " <" LV2_KXSTUDIO_PROPERTIES__NonAutomable "> ;\n";
}
}

if (i+1 == count)
pluginString += " ] ;\n\n";
else
pluginString += " ] ,\n";
}
}

// comment
{
const String comment(plugin.getDescription());

if (comment.isNotEmpty())
pluginString += " rdfs:comment \"\"\"\n" + comment + "\n\"\"\" ;\n\n";
}

#ifdef DISTRHO_PLUGIN_BRAND
// MOD
pluginString += " mod:brand \"" DISTRHO_PLUGIN_BRAND "\" ;\n";
pluginString += " mod:label \"" DISTRHO_PLUGIN_NAME "\" ;\n\n";
#endif

// name
pluginString += " doap:name \"" + String(plugin.getName()) + "\" ;\n";

// license
{
const String license(plugin.getLicense());

if (license.contains("://"))
pluginString += " doap:license <" + license + "> ;\n\n";
else
pluginString += " doap:license \"" + license + "\" ;\n\n";
}

// developer
{
const String homepage(plugin.getHomePage());

pluginString += " doap:maintainer [\n";
pluginString += " foaf:name \"" + String(plugin.getMaker()) + "\" ;\n";

if (homepage.isNotEmpty())
pluginString += " foaf:homepage <" + homepage + "> ;\n";

pluginString += " ] ;\n\n";
}

{
const uint32_t version(plugin.getVersion());

const uint32_t majorVersion = (version & 0xFF0000) >> 16;
const uint32_t microVersion = (version & 0x00FF00) >> 8;
/* */ uint32_t minorVersion = (version & 0x0000FF) >> 0;

// NOTE: LV2 ignores 'major' version and says 0 for minor is pre-release/unstable.
if (majorVersion > 0)
minorVersion += 2;

pluginString += " lv2:microVersion " + String(microVersion) + " ;\n";
pluginString += " lv2:minorVersion " + String(minorVersion) + " .\n";
}

pluginFile << pluginString << std::endl;
pluginFile.close();
std::cout << " done!" << std::endl;
}

// ---------------------------------------------

#if DISTRHO_PLUGIN_HAS_UI && ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
{
std::cout << "Writing " << uiTTL << "..."; std::cout.flush();
std::fstream uiFile(uiTTL, std::ios::out);

String uiString;
uiString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
uiString += "@prefix ui: <" LV2_UI_PREFIX "> .\n";
uiString += "\n";

uiString += "<" DISTRHO_UI_URI ">\n";
uiString += " lv2:extensionData ui:idleInterface ,\n";
# if DISTRHO_PLUGIN_WANT_PROGRAMS
uiString += " ui:showInterface ,\n";
uiString += " <" LV2_PROGRAMS__Interface "> ;\n";
# else
uiString += " ui:showInterface ;\n";
# endif
uiString += "\n";
# if DISTRHO_PLUGIN_HAS_EMBED_UI
uiString += " lv2:optionalFeature ui:noUserResize ,\n";
uiString += " ui:resize ,\n";
uiString += " ui:touch ;\n";
uiString += "\n";
# endif
uiString += " lv2:requiredFeature <" LV2_OPTIONS__options "> ,\n";
uiString += " <" LV2_URID__map "> .\n";

uiFile << uiString << std::endl;
uiFile.close();
std::cout << " done!" << std::endl;
}
#endif

// ---------------------------------------------

#if DISTRHO_PLUGIN_WANT_PROGRAMS
{
std::cout << "Writing presets.ttl..."; std::cout.flush();
std::fstream presetsFile("presets.ttl", std::ios::out);

String presetsString;
presetsString += "@prefix lv2: <" LV2_CORE_PREFIX "> .\n";
presetsString += "@prefix pset: <" LV2_PRESETS_PREFIX "> .\n";
# if DISTRHO_PLUGIN_WANT_STATE
presetsString += "@prefix state: <" LV2_STATE_PREFIX "> .\n";
# endif
presetsString += "\n";

const uint32_t numParameters = plugin.getParameterCount();
const uint32_t numPrograms = plugin.getProgramCount();
# if DISTRHO_PLUGIN_WANT_FULL_STATE
const uint32_t numStates = plugin.getStateCount();
# endif

const String presetSeparator(std::strstr(DISTRHO_PLUGIN_URI, "#") != nullptr ? ":" : "#");

char strBuf[0xff+1];
strBuf[0xff] = '\0';

String presetString;

for (uint32_t i=0; i<numPrograms; ++i)
{
std::snprintf(strBuf, 0xff, "%03i", i+1);

plugin.loadProgram(i);

presetString = "<" DISTRHO_PLUGIN_URI + presetSeparator + "preset" + strBuf + ">\n";

# if DISTRHO_PLUGIN_WANT_FULL_STATE
if (numParameters == 0 && numStates == 0)
#else
if (numParameters == 0)
#endif
{
presetString += " .";
presetsString += presetString;
continue;
}

# if DISTRHO_PLUGIN_WANT_FULL_STATE
presetString += " state:state [\n";
for (uint32_t j=0; j<numStates; ++j)
{
const String key = plugin.getStateKey(j);
const String value = plugin.getState(key);

presetString += " <urn:distrho:" + key + ">";

if (value.length() < 10)
presetString += " \"" + value + "\" ;\n";
else
presetString += "\n\"\"\"\n" + value + "\n\"\"\" ;\n";
}

if (numParameters > 0)
presetString += " ] ;\n\n";
else
presetString += " ] .\n\n";
# endif

bool firstParameter = true;

for (uint32_t j=0; j <numParameters; ++j)
{
if (plugin.isParameterOutput(j))
continue;

if (firstParameter)
{
presetString += " lv2:port [\n";
firstParameter = false;
}
else
{
presetString += " [\n";
}

presetString += " lv2:symbol \"" + plugin.getParameterSymbol(j) + "\" ;\n";

if (plugin.getParameterHints(j) & kParameterIsInteger)
presetString += " pset:value " + String(int(plugin.getParameterValue(j))) + " ;\n";
else
presetString += " pset:value " + String(plugin.getParameterValue(j)) + " ;\n";

if (j+1 == numParameters || plugin.isParameterOutput(j+1))
presetString += " ] .\n\n";
else
presetString += " ] ,\n";
}

presetsString += presetString;
}

presetsFile << presetsString << std::endl;
presetsFile.close();
std::cout << " done!" << std::endl;
}
#endif
}

+ 0
- 1229
source/modules/distrho/src/DistrhoPluginVST.cpp
File diff suppressed because it is too large
View File


+ 0
- 511
source/modules/distrho/src/DistrhoUIDSSI.cpp View File

@@ -1,511 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoUIInternal.hpp"

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
# error DSSI UIs do not support direct access!
#endif

#include "../extra/Sleep.hpp"

#include <lo/lo.h>

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

struct OscData {
lo_address addr;
const char* path;
lo_server server;

OscData()
: addr(nullptr),
path(nullptr),
server(nullptr) {}

void idle() const
{
if (server == nullptr)
return;

while (lo_server_recv_noblock(server, 0) != 0) {}
}

void send_configure(const char* const key, const char* const value) const
{
char targetPath[std::strlen(path)+11];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/configure");
lo_send(addr, targetPath, "ss", key, value);
}

void send_control(const int32_t index, const float value) const
{
char targetPath[std::strlen(path)+9];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/control");
lo_send(addr, targetPath, "if", index, value);
}

void send_midi(uchar data[4]) const
{
char targetPath[std::strlen(path)+6];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/midi");
lo_send(addr, targetPath, "m", data);
}

void send_update(const char* const url) const
{
char targetPath[std::strlen(path)+8];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/update");
lo_send(addr, targetPath, "s", url);
}

void send_exiting() const
{
char targetPath[std::strlen(path)+9];
std::strcpy(targetPath, path);
std::strcat(targetPath, "/exiting");
lo_send(addr, targetPath, "");
}
};

// -----------------------------------------------------------------------

class UIDssi
{
public:
UIDssi(const OscData& oscData, const char* const uiTitle)
: fUI(this, 0, nullptr, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback),
fHostClosed(false),
fOscData(oscData)
{
fUI.setWindowTitle(uiTitle);
}

~UIDssi()
{
if (fOscData.server != nullptr && ! fHostClosed)
fOscData.send_exiting();
}

void exec()
{
for (;;)
{
fOscData.idle();

if (fHostClosed || ! fUI.idle())
break;

d_msleep(30);
}
}

// -------------------------------------------------------------------

#if DISTRHO_PLUGIN_WANT_STATE
void dssiui_configure(const char* key, const char* value)
{
fUI.stateChanged(key, value);
}
#endif

void dssiui_control(ulong index, float value)
{
fUI.parameterChanged(index, value);
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void dssiui_program(ulong bank, ulong program)
{
fUI.programLoaded(bank * 128 + program);
}
#endif

void dssiui_samplerate(const double sampleRate)
{
fUI.setSampleRate(sampleRate, true);
}

void dssiui_show()
{
fUI.setWindowVisible(true);
}

void dssiui_hide()
{
fUI.setWindowVisible(false);
}

void dssiui_quit()
{
fHostClosed = true;
fUI.quit();
}

// -------------------------------------------------------------------

protected:
void setParameterValue(const uint32_t rindex, const float value)
{
if (fOscData.server == nullptr)
return;

fOscData.send_control(rindex, value);
}

void setState(const char* const key, const char* const value)
{
if (fOscData.server == nullptr)
return;

fOscData.send_configure(key, value);
}

void sendNote(const uint8_t channel, const uint8_t note, const uint8_t velocity)
{
if (fOscData.server == nullptr)
return;
if (channel > 0xF)
return;

uint8_t mdata[4] = { 0, channel, note, velocity };
mdata[1] += (velocity != 0) ? 0x90 : 0x80;

fOscData.send_midi(mdata);
}

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);
}

private:
UIExporter fUI;
bool fHostClosed;

const OscData& fOscData;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((UIDssi*)ptr)

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
uiPtr->setParameterValue(rindex, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->sendNote(channel, note, velocity);
}

static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}

#undef uiPtr
};

// -----------------------------------------------------------------------

static OscData gOscData;
static const char* gUiTitle = nullptr;
static UIDssi* globalUI = nullptr;

static void initUiIfNeeded()
{
if (globalUI != nullptr)
return;

if (d_lastUiSampleRate == 0.0)
d_lastUiSampleRate = 44100.0;

globalUI = new UIDssi(gOscData, gUiTitle);
}

// -----------------------------------------------------------------------

int osc_debug_handler(const char* path, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_debug_handler(\"%s\")", path);
return 0;

#ifndef DEBUG
// unused
(void)path;
#endif
}

void osc_error_handler(int num, const char* msg, const char* path)
{
d_stderr("osc_error_handler(%i, \"%s\", \"%s\")", num, msg, path);
}

#if DISTRHO_PLUGIN_WANT_STATE
int osc_configure_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const char* const key = &argv[0]->s;
const char* const value = &argv[1]->s;
d_debug("osc_configure_handler(\"%s\", \"%s\")", key, value);

initUiIfNeeded();

globalUI->dssiui_configure(key, value);

return 0;
}
#endif

int osc_control_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t rindex = argv[0]->i;
const float value = argv[1]->f;
d_debug("osc_control_handler(%i, %f)", rindex, value);

int32_t index = rindex - DISTRHO_PLUGIN_NUM_INPUTS - DISTRHO_PLUGIN_NUM_OUTPUTS;

// latency
#if DISTRHO_PLUGIN_WANT_LATENCY
index -= 1;
#endif

if (index < 0)
return 0;

initUiIfNeeded();

globalUI->dssiui_control(index, value);

return 0;
}

#if DISTRHO_PLUGIN_WANT_PROGRAMS
int osc_program_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t bank = argv[0]->i;
const int32_t program = argv[1]->f;
d_debug("osc_program_handler(%i, %i)", bank, program);

initUiIfNeeded();

globalUI->dssiui_program(bank, program);

return 0;
}
#endif

int osc_sample_rate_handler(const char*, const char*, lo_arg** argv, int, lo_message, void*)
{
const int32_t sampleRate = argv[0]->i;
d_debug("osc_sample_rate_handler(%i)", sampleRate);

d_lastUiSampleRate = sampleRate;

if (globalUI != nullptr)
globalUI->dssiui_samplerate(sampleRate);

return 0;
}

int osc_show_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_show_handler()");

initUiIfNeeded();

globalUI->dssiui_show();

return 0;
}

int osc_hide_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_hide_handler()");

if (globalUI != nullptr)
globalUI->dssiui_hide();

return 0;
}

int osc_quit_handler(const char*, const char*, lo_arg**, int, lo_message, void*)
{
d_debug("osc_quit_handler()");

if (globalUI != nullptr)
globalUI->dssiui_quit();

return 0;
}

END_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

int main(int argc, char* argv[])
{
USE_NAMESPACE_DISTRHO

// dummy test mode
if (argc == 1)
{
gUiTitle = "DSSI UI Test";

initUiIfNeeded();
globalUI->dssiui_show();
globalUI->exec();

delete globalUI;
globalUI = nullptr;

return 0;
}

if (argc != 5)
{
fprintf(stderr, "Usage: %s <osc-url> <plugin-dll> <plugin-label> <instance-name>\n", argv[0]);
return 1;
}

const char* oscUrl = argv[1];
const char* uiTitle = argv[4];

char* const oscHost = lo_url_get_hostname(oscUrl);
char* const oscPort = lo_url_get_port(oscUrl);
char* const oscPath = lo_url_get_path(oscUrl);
size_t oscPathSize = strlen(oscPath);
lo_address oscAddr = lo_address_new(oscHost, oscPort);
lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler);

char* const oscServerPath = lo_server_get_url(oscServer);

char pluginPath[strlen(oscServerPath)+oscPathSize];
strcpy(pluginPath, oscServerPath);
strcat(pluginPath, oscPath+1);

#if DISTRHO_PLUGIN_WANT_STATE
char oscPathConfigure[oscPathSize+11];
strcpy(oscPathConfigure, oscPath);
strcat(oscPathConfigure, "/configure");
lo_server_add_method(oscServer, oscPathConfigure, "ss", osc_configure_handler, nullptr);
#endif

char oscPathControl[oscPathSize+9];
strcpy(oscPathControl, oscPath);
strcat(oscPathControl, "/control");
lo_server_add_method(oscServer, oscPathControl, "if", osc_control_handler, nullptr);

d_stdout("oscServerPath: \"%s\"", oscServerPath);
d_stdout("pluginPath: \"%s\"", pluginPath);
d_stdout("oscPathControl: \"%s\"", oscPathControl);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
char oscPathProgram[oscPathSize+9];
strcpy(oscPathProgram, oscPath);
strcat(oscPathProgram, "/program");
lo_server_add_method(oscServer, oscPathProgram, "ii", osc_program_handler, nullptr);
#endif

char oscPathSampleRate[oscPathSize+13];
strcpy(oscPathSampleRate, oscPath);
strcat(oscPathSampleRate, "/sample-rate");
lo_server_add_method(oscServer, oscPathSampleRate, "i", osc_sample_rate_handler, nullptr);

char oscPathShow[oscPathSize+6];
strcpy(oscPathShow, oscPath);
strcat(oscPathShow, "/show");
lo_server_add_method(oscServer, oscPathShow, "", osc_show_handler, nullptr);

char oscPathHide[oscPathSize+6];
strcpy(oscPathHide, oscPath);
strcat(oscPathHide, "/hide");
lo_server_add_method(oscServer, oscPathHide, "", osc_hide_handler, nullptr);

char oscPathQuit[oscPathSize+6];
strcpy(oscPathQuit, oscPath);
strcat(oscPathQuit, "/quit");
lo_server_add_method(oscServer, oscPathQuit, "", osc_quit_handler, nullptr);

lo_server_add_method(oscServer, nullptr, nullptr, osc_debug_handler, nullptr);

gUiTitle = uiTitle;

gOscData.addr = oscAddr;
gOscData.path = oscPath;
gOscData.server = oscServer;
gOscData.send_update(pluginPath);

// wait for init
for (int i=0; i < 100; ++i)
{
lo_server_recv(oscServer);

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
break;

d_msleep(50);
}

int ret = 1;

if (d_lastUiSampleRate != 0.0 || globalUI != nullptr)
{
initUiIfNeeded();

globalUI->exec();

delete globalUI;
globalUI = nullptr;

ret = 0;
}

#if DISTRHO_PLUGIN_WANT_STATE
lo_server_del_method(oscServer, oscPathConfigure, "ss");
#endif
lo_server_del_method(oscServer, oscPathControl, "if");
#if DISTRHO_PLUGIN_WANT_PROGRAMS
lo_server_del_method(oscServer, oscPathProgram, "ii");
#endif
lo_server_del_method(oscServer, oscPathSampleRate, "i");
lo_server_del_method(oscServer, oscPathShow, "");
lo_server_del_method(oscServer, oscPathHide, "");
lo_server_del_method(oscServer, oscPathQuit, "");
lo_server_del_method(oscServer, nullptr, nullptr);

std::free(oscServerPath);
std::free(oscHost);
std::free(oscPort);
std::free(oscPath);

lo_address_free(oscAddr);
lo_server_free(oscServer);

return ret;
}

+ 0
- 542
source/modules/distrho/src/DistrhoUILV2.cpp View File

@@ -1,542 +0,0 @@
/*
* DISTRHO Plugin Framework (DPF)
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
* permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include "DistrhoUIInternal.hpp"

#include "../extra/String.hpp"

#include "lv2/atom.h"
#include "lv2/atom-util.h"
#include "lv2/data-access.h"
#include "lv2/instance-access.h"
#include "lv2/options.h"
#include "lv2/parameters.h"
#include "lv2/ui.h"
#include "lv2/urid.h"
#include "lv2/lv2_kxstudio_properties.h"
#include "lv2/lv2_programs.h"

#ifndef DISTRHO_PLUGIN_LV2_STATE_PREFIX
# define DISTRHO_PLUGIN_LV2_STATE_PREFIX "urn:distrho:"
#endif

START_NAMESPACE_DISTRHO

// -----------------------------------------------------------------------

class UiLv2
{
public:
UiLv2(const char* const bundlePath, const intptr_t winId,
const LV2_Options_Option* options, const LV2_URID_Map* const uridMap, const LV2UI_Resize* const uiResz, const LV2UI_Touch* uiTouch,
const LV2UI_Controller controller, const LV2UI_Write_Function writeFunc,
LV2UI_Widget* const widget, void* const dspPtr)
: fUI(this, winId, editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback, setSizeCallback, dspPtr, bundlePath),
fUridMap(uridMap),
fUiResize(uiResz),
fUiTouch(uiTouch),
fController(controller),
fWriteFunction(writeFunc),
fEventTransferURID(uridMap->map(uridMap->handle, LV2_ATOM__eventTransfer)),
fKeyValueURID(uridMap->map(uridMap->handle, DISTRHO_PLUGIN_LV2_STATE_PREFIX "KeyValueState")),
fWinIdWasNull(winId == 0)
{
if (fUiResize != nullptr && winId != 0)
fUiResize->ui_resize(fUiResize->handle, fUI.getWidth(), fUI.getHeight());

if (widget != nullptr)
*widget = (LV2UI_Widget)fUI.getWindowId();

#if DISTRHO_PLUGIN_WANT_STATE
// tell the DSP we're ready to receive msgs
setState("__dpf_ui_data__", "");
#endif

if (winId != 0)
return;

// if winId == 0 then options must not be null
DISTRHO_SAFE_ASSERT_RETURN(options != nullptr,);

const LV2_URID uridWindowTitle(uridMap->map(uridMap->handle, LV2_UI__windowTitle));
const LV2_URID uridTransientWinId(uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TransientWindowId));

bool hasTitle = false;

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridTransientWinId)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Long))
{
if (const int64_t transientWinId = *(const int64_t*)options[i].value)
fUI.setWindowTransientWinId(static_cast<intptr_t>(transientWinId));
}
else
d_stderr("Host provides transientWinId but has wrong value type");
}
else if (options[i].key == uridWindowTitle)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__String))
{
if (const char* const windowTitle = (const char*)options[i].value)
{
hasTitle = true;
fUI.setWindowTitle(windowTitle);
}
}
else
d_stderr("Host provides windowTitle but has wrong value type");
}
}

if (! hasTitle)
fUI.setWindowTitle(DISTRHO_PLUGIN_NAME);
}

// -------------------------------------------------------------------

void lv2ui_port_event(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
{
if (format == 0)
{
const uint32_t parameterOffset(fUI.getParameterOffset());

if (rindex < parameterOffset)
return;

DISTRHO_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),)

const float value(*(const float*)buffer);
fUI.parameterChanged(rindex-parameterOffset, value);
}
#if DISTRHO_PLUGIN_WANT_STATE
else if (format == fEventTransferURID)
{
const LV2_Atom* const atom((const LV2_Atom*)buffer);

DISTRHO_SAFE_ASSERT_RETURN(atom->type == fKeyValueURID,);

const char* const key = (const char*)LV2_ATOM_BODY_CONST(atom);
const char* const value = key+(std::strlen(key)+1);

fUI.stateChanged(key, value);
}
#endif
}

// -------------------------------------------------------------------

int lv2ui_idle()
{
if (fWinIdWasNull)
return (fUI.idle() && fUI.isVisible()) ? 0 : 1;

return fUI.idle() ? 0 : 1;
}

int lv2ui_show()
{
return fUI.setWindowVisible(true) ? 0 : 1;
}

int lv2ui_hide()
{
return fUI.setWindowVisible(false) ? 0 : 1;
}

int lv2ui_resize(uint width, uint height)
{
fUI.setWindowSize(width, height, true);
return 0;
}

// -------------------------------------------------------------------

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/)
{
// currently unused
return LV2_OPTIONS_ERR_UNKNOWN;
}

uint32_t lv2_set_options(const LV2_Options_Option* const options)
{
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate))
{
if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Float))
{
const float sampleRate(*(const float*)options[i].value);
fUI.setSampleRate(sampleRate);
continue;
}
else
{
d_stderr("Host changed UI sample-rate but with wrong value type");
continue;
}
}
}

return LV2_OPTIONS_SUCCESS;
}

// -------------------------------------------------------------------

#if DISTRHO_PLUGIN_WANT_PROGRAMS
void lv2ui_select_program(const uint32_t bank, const uint32_t program)
{
const uint32_t realProgram(bank * 128 + program);

fUI.programLoaded(realProgram);
}
#endif

// -------------------------------------------------------------------

protected:
void editParameterValue(const uint32_t rindex, const bool started)
{
if (fUiTouch != nullptr && fUiTouch->touch != nullptr)
fUiTouch->touch(fUiTouch->handle, rindex, started);
}

void setParameterValue(const uint32_t rindex, const float value)
{
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,);

fWriteFunction(fController, rindex, sizeof(float), 0, &value);
}

void setState(const char* const key, const char* const value)
{
DISTRHO_SAFE_ASSERT_RETURN(fWriteFunction != nullptr,);

const uint32_t eventInPortIndex(DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS);

// join key and value
String tmpStr;
tmpStr += key;
tmpStr += "\xff";
tmpStr += value;

tmpStr[std::strlen(key)] = '\0';

// set msg size (key + separator + value + null terminator)
const size_t msgSize(tmpStr.length()+1);

// reserve atom space
const size_t atomSize(sizeof(LV2_Atom) + msgSize);
char atomBuf[atomSize];
std::memset(atomBuf, 0, atomSize);

// set atom info
LV2_Atom* const atom((LV2_Atom*)atomBuf);
atom->size = msgSize;
atom->type = fKeyValueURID;

// set atom data
std::memcpy(atomBuf + sizeof(LV2_Atom), tmpStr.buffer(), msgSize);

// send to DSP side
fWriteFunction(fController, eventInPortIndex, atomSize, fEventTransferURID, atom);
}

void sendNote(const uint8_t /*channel*/, const uint8_t /*note*/, const uint8_t /*velocity*/)
{
}

void setSize(const uint width, const uint height)
{
fUI.setWindowSize(width, height);

if (fUiResize != nullptr && ! fWinIdWasNull)
fUiResize->ui_resize(fUiResize->handle, width, height);
}

private:
UIExporter fUI;

// LV2 features
const LV2_URID_Map* const fUridMap;
const LV2UI_Resize* const fUiResize;
const LV2UI_Touch* const fUiTouch;

// LV2 UI stuff
const LV2UI_Controller fController;
const LV2UI_Write_Function fWriteFunction;

// Need to save this
const LV2_URID fEventTransferURID;
const LV2_URID fKeyValueURID;

// using ui:showInterface if true
bool fWinIdWasNull;

// -------------------------------------------------------------------
// Callbacks

#define uiPtr ((UiLv2*)ptr)

static void editParameterCallback(void* ptr, uint32_t rindex, bool started)
{
uiPtr->editParameterValue(rindex, started);
}

static void setParameterCallback(void* ptr, uint32_t rindex, float value)
{
uiPtr->setParameterValue(rindex, value);
}

static void setStateCallback(void* ptr, const char* key, const char* value)
{
uiPtr->setState(key, value);
}

static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
{
uiPtr->sendNote(channel, note, velocity);
}

static void setSizeCallback(void* ptr, uint width, uint height)
{
uiPtr->setSize(width, height);
}

#undef uiPtr
};

// -----------------------------------------------------------------------

static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char* uri, const char* bundlePath,
LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
{
if (uri == nullptr || std::strcmp(uri, DISTRHO_PLUGIN_URI) != 0)
{
d_stderr("Invalid plugin URI");
return nullptr;
}

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2UI_Resize* uiResize = nullptr;
const LV2UI_Touch* uiTouch = nullptr;
void* parentId = nullptr;
void* instance = nullptr;

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
struct LV2_DirectAccess_Interface {
void* (*get_instance_pointer)(LV2_Handle handle);
};
const LV2_Extension_Data_Feature* extData = nullptr;
#endif

for (int i=0; features[i] != nullptr; ++i)
{
if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
options = (const LV2_Options_Option*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
uridMap = (const LV2_URID_Map*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__resize) == 0)
uiResize = (const LV2UI_Resize*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_UI__parent) == 0)
parentId = features[i]->data;
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
else if (std::strcmp(features[i]->URI, LV2_DATA_ACCESS_URI) == 0)
extData = (const LV2_Extension_Data_Feature*)features[i]->data;
else if (std::strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0)
instance = features[i]->data;
#endif
}

if (options == nullptr && parentId == nullptr)
{
d_stderr("Options feature missing (needed for show-interface), cannot continue!");
return nullptr;
}

if (uridMap == nullptr)
{
d_stderr("URID Map feature missing, cannot continue!");
return nullptr;
}

if (parentId == nullptr)
{
d_stdout("Parent Window Id missing, host should be using ui:showInterface...");
}

#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
if (extData == nullptr || instance == nullptr)
{
d_stderr("Data or instance access missing, cannot continue!");
return nullptr;
}

if (const LV2_DirectAccess_Interface* const directAccess = (const LV2_DirectAccess_Interface*)extData->data_access(DISTRHO_PLUGIN_LV2_STATE_PREFIX "direct-access"))
instance = directAccess->get_instance_pointer(instance);
else
instance = nullptr;

if (instance == nullptr)
{
d_stderr("Failed to get direct access, cannot continue!");
return nullptr;
}
#endif

const intptr_t winId((intptr_t)parentId);

if (options != nullptr)
{
const LV2_URID uridSampleRate(uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate));

for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == uridSampleRate)
{
if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Float))
d_lastUiSampleRate = *(const float*)options[i].value;
else
d_stderr("Host provides UI sample-rate but has wrong value type");

break;
}
}
}

if (d_lastUiSampleRate < 1.0)
{
d_stdout("WARNING: this host does not send sample-rate information for LV2 UIs, using 44100 as fallback (this could be wrong)");
d_lastUiSampleRate = 44100.0;
}

return new UiLv2(bundlePath, winId, options, uridMap, uiResize, uiTouch, controller, writeFunction, widget, instance);
}

#define uiPtr ((UiLv2*)ui)

static void lv2ui_cleanup(LV2UI_Handle ui)
{
delete uiPtr;
}

static void lv2ui_port_event(LV2UI_Handle ui, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
{
uiPtr->lv2ui_port_event(portIndex, bufferSize, format, buffer);
}

// -----------------------------------------------------------------------

static int lv2ui_idle(LV2UI_Handle ui)
{
return uiPtr->lv2ui_idle();
}

static int lv2ui_show(LV2UI_Handle ui)
{
return uiPtr->lv2ui_show();
}

static int lv2ui_hide(LV2UI_Handle ui)
{
return uiPtr->lv2ui_hide();
}

static int lv2ui_resize(LV2UI_Handle ui, int width, int height)
{
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, 1);
DISTRHO_SAFE_ASSERT_RETURN(width > 0, 1);
DISTRHO_SAFE_ASSERT_RETURN(height > 0, 1);

return 1; // This needs more testing
//return uiPtr->lv2ui_resize(width, height);
}

// -----------------------------------------------------------------------

static uint32_t lv2_get_options(LV2UI_Handle ui, LV2_Options_Option* options)
{
return uiPtr->lv2_get_options(options);
}

static uint32_t lv2_set_options(LV2UI_Handle ui, const LV2_Options_Option* options)
{
return uiPtr->lv2_set_options(options);
}

// -----------------------------------------------------------------------

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program)
{
uiPtr->lv2ui_select_program(bank, program);
}
#endif

// -----------------------------------------------------------------------

static const void* lv2ui_extension_data(const char* uri)
{
static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options };
static const LV2UI_Idle_Interface uiIdle = { lv2ui_idle };
static const LV2UI_Show_Interface uiShow = { lv2ui_show, lv2ui_hide };
static const LV2UI_Resize uiResz = { nullptr, lv2ui_resize };

if (std::strcmp(uri, LV2_OPTIONS__interface) == 0)
return &options;
if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
return &uiIdle;
if (std::strcmp(uri, LV2_UI__showInterface) == 0)
return &uiShow;
if (std::strcmp(uri, LV2_UI__resize) == 0)
return &uiResz;

#if DISTRHO_PLUGIN_WANT_PROGRAMS
static const LV2_Programs_UI_Interface uiPrograms = { lv2ui_select_program };

if (std::strcmp(uri, LV2_PROGRAMS__UIInterface) == 0)
return &uiPrograms;
#endif

return nullptr;
}

#undef instancePtr

// -----------------------------------------------------------------------

static const LV2UI_Descriptor sLv2UiDescriptor = {
DISTRHO_UI_URI,
lv2ui_instantiate,
lv2ui_cleanup,
lv2ui_port_event,
lv2ui_extension_data
};

// -----------------------------------------------------------------------

END_NAMESPACE_DISTRHO

DISTRHO_PLUGIN_EXPORT
const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
{
USE_NAMESPACE_DISTRHO
return (index == 0) ? &sLv2UiDescriptor : nullptr;
}

// -----------------------------------------------------------------------

Loading…
Cancel
Save