diff options
| -rw-r--r-- | lv2/input_lv2.cc | 27 | ||||
| -rw-r--r-- | lv2/lv2.cc | 328 | ||||
| -rw-r--r-- | lv2/lv2_instance.h | 5 | ||||
| -rw-r--r-- | lv2/output_lv2.cc | 2 | ||||
| -rw-r--r-- | lv2/output_lv2.h | 1 | ||||
| -rw-r--r-- | src/configuration.cc | 17 | ||||
| -rw-r--r-- | src/configuration.h | 2 | ||||
| -rw-r--r-- | src/drumgizmo.cc | 41 | ||||
| -rw-r--r-- | test/Makefile.am | 14 | ||||
| -rw-r--r-- | test/kit/instr1.xml | 2 | ||||
| -rw-r--r-- | test/kit/instr2.xml | 2 | ||||
| -rw-r--r-- | test/kit/kit1.xml | 2 | ||||
| -rw-r--r-- | test/kit/kit2.xml | 2 | ||||
| -rw-r--r-- | test/lv2.cc | 332 | ||||
| -rw-r--r-- | test/lv2_test_host.cc | 403 | ||||
| -rw-r--r-- | test/lv2_test_host.h | 83 | 
16 files changed, 908 insertions, 355 deletions
| diff --git a/lv2/input_lv2.cc b/lv2/input_lv2.cc index d995e75..e70d293 100644 --- a/lv2/input_lv2.cc +++ b/lv2/input_lv2.cc @@ -66,6 +66,11 @@ void InputLV2::pre()  event_t *InputLV2::run(size_t pos, size_t len, size_t *nevents)  { +  if(eventPort == NULL) { +    *nevents = 0; +    return NULL; +  } +    event_t *list;    size_t listsize; @@ -99,11 +104,6 @@ event_t *InputLV2::run(size_t pos, size_t len, size_t *nevents)          list[listsize].offset = ev->time.frames;          listsize++;        } -      /* -				start_frame = ev->frames; -				plugin->frame = 0; -				plugin->play  = true; -      */      }      ev = lv2_atom_sequence_next(ev);    } @@ -115,20 +115,3 @@ event_t *InputLV2::run(size_t pos, size_t len, size_t *nevents)  void InputLV2::post()  {  } - -#ifdef TEST_INPUT_LV2 -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_INPUT_LV2*/ @@ -25,24 +25,20 @@   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.   */  #include <lv2/lv2plug.in/ns/lv2core/lv2.h> +#include <lv2/lv2plug.in/ns/ext/atom/atom.h>  #include <stdlib.h>  #include <string.h>  #include "lv2_gui.h" -  #include "lv2_instance.h"  #include <hugin.hpp> -#include <lv2/lv2plug.in/ns/ext/atom/atom.h> - -#define NS_ATOM "http://lv2plug.in/ns/ext/atom#" -#define NS_DG "http://drumgizmo.org/lv2/atom#" +#define DRUMGIZMO_URI "http://drumgizmo.org/lv2" +#define NS_DG DRUMGIZMO_URI "/atom#" -/* - * Stuff to handle DrumGizmo* transmission from instance to GUI. - */ +// Stuff to handle DrumGizmo* transmission from instance to GUI.  static LV2_DrumGizmo_Descriptor dg_descriptor;  static DrumGizmo *dg_get_pci(LV2_Handle instance) @@ -51,56 +47,6 @@ static DrumGizmo *dg_get_pci(LV2_Handle instance)    return dglv2->dg;  } -/* - * Stuff to save/restore plugin state. - */ -/* -void dg_save(LV2_Handle                 instance, -             LV2_State_Store_Function   store, -             void*                      callback_data, -             uint32_t                   flags, -             const LV2_Feature *const * features) -{ -  DGLV2 *dglv2 = (DGLV2 *)instance; -  printf("dg_save\n"); - -  std::string config = dglv2->dg->configString(); -  printf("%s\n", config.c_str()); - -  store(callback_data, -        dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                 NULL, NS_DG "config"), -        config.data(), config.length(), -        dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                 NULL, NS_ATOM "String"), -        LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); -} - -void dg_restore(LV2_Handle                  instance, -                LV2_State_Retrieve_Function retrieve, -                void*                       callback_data, -                uint32_t                    flags, -                const LV2_Feature *const *  features) -{ -  DGLV2 *dglv2 = (DGLV2 *)instance; -  printf("dg_restore\n"); - -  size_t      size; -  uint32_t    type; -  //  uint32_t    flags; - -  const char* data = -    (const char*)retrieve(callback_data, -                          dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                                   NULL, NS_DG "config"), -                          &size, &type, &flags); -  std::string config; -  config.append(data, size); -  dglv2->dg->setConfigString(config); - -  dglv2->in->loadMidiMap(dglv2->dg->midimapfile); -} -*/  LV2_State_Status  dg_save(LV2_Handle                 instance,          LV2_State_Store_Function   store, @@ -109,32 +55,26 @@ dg_save(LV2_Handle                 instance,          const LV2_Feature *const * features)  {    DGLV2 *dglv2 = (DGLV2 *)instance; -  printf("dg_save\n"); + +  if(!dglv2 || !dglv2->map || !dglv2->map->map) { +    // Missing urid feature? +    return  LV2_STATE_ERR_NO_FEATURE; +  }    std::string config = dglv2->dg->configString(); -  printf("%s\n", config.c_str()); + +  // Backwards compatible fix for errornously stored '\0' byte in < v0.9.8. +  // Remove when we reach v1.0 +  config += "\n";    store(handle, -        dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                 NULL, NS_DG "config"), -        config.c_str(), -        config.length() + 1, // Careful!  Need space for terminator -        dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                 NULL, NS_ATOM "chunk"), +        dglv2->map->map(dglv2->map->handle, NS_DG "config"), +        config.data(), +        config.length(), +        dglv2->map->map(dglv2->map->handle, LV2_ATOM__Chunk),          LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); -/* -    MyPlugin*   plugin   = (MyPlugin*)instance; -    const char* greeting = plugin->state.greeting; - -    store(handle, -          plugin->uris.my_greeting, -          greeting, -          strlen(greeting) + 1,  // Careful!  Need space for terminator -          plugin->uris.atom_String, -          LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); -*/ -  printf("dg_save\n"); -    return LV2_STATE_SUCCESS; + +  return LV2_STATE_SUCCESS;  }  LV2_State_Status @@ -145,43 +85,32 @@ dg_restore(LV2_Handle                  instance,             const LV2_Feature *const *  features)  {    DGLV2 *dglv2 = (DGLV2 *)instance; -  DEBUG(lv2, "dg_restore begin\n"); -  size_t      size; -  uint32_t    type; -  //  uint32_t    flags; +  if(!dglv2 || !dglv2->map || !dglv2->map->map) { +    // Missing urid feature? +    return  LV2_STATE_ERR_NO_FEATURE; +  } + +  size_t size; +  uint32_t type;    const char* data =      (const char*)retrieve(handle, -                          dglv2->urimap->uri_to_id(dglv2->urimap->callback_data, -                                                   NULL, NS_DG "config"), +                          dglv2->map->map(dglv2->map->handle, NS_DG "config"),                            &size, &type, &flags); +    DEBUG(lv2, "Config string size: %d, data*: %p\n", (int)size, data);    if(data && size) {      std::string config; -    config.append(data, size - 1); + +    // Fix for errornously stored '\0' byte in < v0.9.8. +    // Remove when we reach v1.0 +    if(data[size - 1] == '\0') size--; + +    config.append(data, size);      dglv2->dg->setConfigString(config); -    //dglv2->in->loadMidiMap(dglv2->dg->midimapfile);    } -  -  /* -    MyPlugin* plugin = (MyPlugin*)instance; - -    size_t      size; -    uint32_t    type; -    uint32_t    flags; -    const char* greeting = retrieve( -        handle, plugin->uris.my_greeting, &size, &type, &flags); - -    if (greeting) { -        free(plugin->state->greeting); -        plugin->state->greeting = strdup(greeting); -    } else { -        plugin->state->greeting = strdup(DEFAULT_GREETING); -    } -  */ -  DEBUG(lv2, "dg_restore done\n");    return LV2_STATE_SUCCESS;  } @@ -191,42 +120,6 @@ static LV2_State_Interface dg_persist = {    dg_restore  }; -/** A globally unique, case-sensitive identifier for this plugin type. - * - * All plugins with the same URI MUST be compatible in terms of 'port - * signature', meaning they have the same number of ports, same port - * shortnames, and roughly the same functionality.  URIs should - * probably contain a version number (or similar) for this reason. - * - * Rationale:  When serializing session/patch/etc files, hosts MUST - * refer to a loaded plugin by the plugin URI only.  In the future - * loading a plugin with this URI MUST yield a plugin with the - * same ports (etc) which is 100% compatible. */ -#define DRUMGIZMO_URI "http://drumgizmo.org/lv2" - -/** Function pointer that instantiates a plugin. - * - * A handle is returned indicating the new plugin instance. The - * instantiation function accepts a sample rate as a parameter as well - * as the plugin descriptor from which this instantiate function was - * found. This function must return NULL if instantiation fails. - * - * bundle_path is a string of the path to the LV2 bundle which contains - * this plugin binary.  It MUST include the trailing directory separator - * (e.g. '/') so that BundlePath + filename gives the path to a file - * in the bundle. - * - * features is a NULL terminated array of LV2_Feature structs which - * represent the features the host supports. Plugins may refuse to - * instantiate if required features are not found here (however hosts - * SHOULD NOT use this as a discovery mechanism, instead reading the - * data file before attempting to instantiate the plugin).  This array - * must always exist; if a host has no features, it MUST pass a single - * element array containing NULL (to simplify plugins). - * - * Note that instance initialisation should generally occur in - * activate() rather than here.  If a host calls instantiate, it MUST - * call cleanup() at some point in the future. */  LV2_Handle instantiate(const struct _LV2_Descriptor *descriptor,                         double sample_rate,                         const char *bundle_path, @@ -234,14 +127,10 @@ LV2_Handle instantiate(const struct _LV2_Descriptor *descriptor,  {    DGLV2 *dglv2 = new DGLV2; -  dglv2->urimap = NULL; +  dglv2->map = NULL;    for (int i = 0 ; features[i] ; i++) { -    printf("DG: feature: %s\n", features[i]->URI); -    if (!strcmp(features[i]->URI, LV2_URI_MAP_URI)) { -      dglv2->urimap = (LV2_URI_Map_Feature*)features[i]->data; -    } -    if (!strcmp(features[i]->URI, LV2_STATE__makePath)) { -      dglv2->makepath = (LV2_State_Make_Path*)features[i]->data; +    if (!strcmp(features[i]->URI,  LV2_URID_URI "#map")) { +      dglv2->map = (LV2_URID_Map*)features[i]->data;      }   } @@ -253,57 +142,12 @@ LV2_Handle instantiate(const struct _LV2_Descriptor *descriptor,    dglv2->buffer = NULL;    dglv2->buffer_size = 0; -  /* -  char* path = dglv2->makepath->path(dglv2->makepath->handle, -                                      "hello.txt"); -  FILE* myfile = fopen(path, "w"); -  fprintf(myfile, "world"); -  fclose(myfile); -  */ -    dglv2->dg = new DrumGizmo(dglv2->out, dglv2->in);    dglv2->dg->setSamplerate(sample_rate); -  //  dglv2->dg->loadkit(getenv("DRUMGIZMO_DRUMKIT")); -  //  dglv2->dg->init(true);    return (LV2_Handle)dglv2;  } -/** Function pointer that connects a port on a plugin instance to a memory - * location where the block of data for the port will be read/written. - * - * The data location is expected to be of the type defined in the - * plugin's data file (e.g. an array of float for an lv2:AudioPort). - * Memory issues are managed by the host. The plugin must read/write - * the data at these locations every time run() is called, data - * present at the time of this connection call MUST NOT be - * considered meaningful.  - * - * The host MUST NOT try to connect a data buffer to a port index  - * that is not defined in the RDF data for the plugin. If it does,  - * the plugin's behaviour is undefined. - * - * connect_port() may be called more than once for a plugin instance - * to allow the host to change the buffers that the plugin is reading - * or writing. These calls may be made before or after activate() - * or deactivate() calls.  Note that there may be realtime constraints - * on connect_port (see lv2:hardRTCapable in lv2.ttl). - * - * connect_port() MUST be called at least once for each port before - * run() is called.  The plugin must pay careful attention to the block - * size passed to the run function as the block allocated may only just - * be large enough to contain the block of data (typically samples), and - * is not guaranteed to be constant. - * - * Plugin writers should be aware that the host may elect to use the - * same buffer for more than one port and even use the same buffer for - * both input and output (see lv2:inPlaceBroken in lv2.ttl). - * However, overlapped buffers or use of a single buffer for both - * audio and control data may result in unexpected behaviour. - * - * If the plugin has the feature lv2:hardRTCapable then there are  - * various things that the plugin MUST NOT do within the connect_port() - * function (see lv2.ttl). */  void connect_port(LV2_Handle instance,                    uint32_t port,                    void *data_location) @@ -320,99 +164,31 @@ void connect_port(LV2_Handle instance,    }  } -/** Function pointer that initialises a plugin instance and activates - * it for use. - *  - * This is separated from instantiate() to aid real-time support and so - * that hosts can reinitialise a plugin instance by calling deactivate() - * and then activate(). In this case the plugin instance must reset all - * state information dependent on the history of the plugin instance - * except for any data locations provided by connect_port(). If there - * is nothing for activate() to do then the plugin writer may provide - * a NULL rather than an empty function. - * - * When present, hosts MUST call this function once before run() - * is called for the first time. This call SHOULD be made as close - * to the run() call as possible and indicates to real-time plugins - * that they are now live, however plugins MUST NOT rely on a prompt - * call to run() after activate().  activate() may not be called again - * unless deactivate() is called first (after which activate() may be - * called again, followed by deactivate, etc. etc.).  If a host calls - * activate, it MUST call deactivate at some point in the future. - * - * Note that connect_port() may be called before or after a call to - * activate(). */  void activate(LV2_Handle instance)  { +  // We don't really need to do anything here.    DGLV2 *dglv2 = (DGLV2 *)instance; -  //dglv2->dg->run();    (void)dglv2;  } -/** Function pointer that runs a plugin instance for a block. - * - * Two parameters are required: the first is a handle to the particular - * instance to be run and the second indicates the block size (in - * samples) for which the plugin instance may run. - * - * Note that if an activate() function exists then it must be called - * before run(). If deactivate() is called for a plugin instance then - * the plugin instance may not be reused until activate() has been - * called again. - * - * If the plugin has the feature lv2:hardRTCapable then there are  - * various things that the plugin MUST NOT do within the run() - * function (see lv2.ttl). */  void run(LV2_Handle instance,           uint32_t sample_count)  {    static size_t pos = 0;    DGLV2 *dglv2 = (DGLV2 *)instance; -  // The buffer is not used anymore - declared NULL in 'instantiate'. -  /* -  if(dglv2->buffer_size != sample_count) { -    if(dglv2->buffer) free(dglv2->buffer); -    dglv2->buffer_size = sample_count; -    dglv2->buffer = (sample_t*)malloc(sizeof(sample_t) * dglv2->buffer_size); -    printf("(Re)allocate buffer: %d samples\n", dglv2->buffer_size); -  } -  */    dglv2->dg->run(pos, dglv2->buffer, sample_count);    pos += sample_count;  } -/** This is the counterpart to activate() (see above). If there is - * nothing for deactivate() to do then the plugin writer may provide - * a NULL rather than an empty function. - * - * Hosts must deactivate all activated units after they have been run() - * for the last time. This call SHOULD be made as close to the last - * run() call as possible and indicates to real-time plugins that - * they are no longer live, however plugins MUST NOT rely on prompt - * deactivation. Note that connect_port() may be called before or - * after a call to deactivate(). - * - * Note that deactivation is not similar to pausing as the plugin - * instance will be reinitialised when activate() is called to reuse it. - * Hosts MUST NOT call deactivate() unless activate() was previously - * called. */  void deactivate(LV2_Handle instance)  { +  // We don't really need to do anything here.    DGLV2 *dglv2 = (DGLV2 *)instance;    dglv2->dg->stop();  } -/** This is the counterpart to instantiate() (see above).  Once an instance - * of a plugin has been finished with it can be deleted using this - * function. The instance handle passed ceases to be valid after - * this call. - *  - * If activate() was called for a plugin instance then a corresponding - * call to deactivate() MUST be made before cleanup() is called. - * Hosts MUST NOT call cleanup() unless instantiate() was previously - * called. */  void cleanup(LV2_Handle instance)  {    DGLV2 *dglv2 = (DGLV2 *)instance; @@ -421,34 +197,8 @@ void cleanup(LV2_Handle instance)    delete dglv2->out;  } -/** Function pointer that can be used to return additional instance data for - * a plugin defined by some extenion (e.g. a struct containing additional - * function pointers). - * - * The actual type and meaning of the returned object MUST be specified  - * precisely by the extension if it defines any extra data.  If a particular - * extension does not define extra instance data, this function MUST return - * NULL for that extension's URI.  If a plugin does not support any - * extensions that define extra instance data, this function pointer may be - * set to NULL rather than providing an empty function. - *  - * The only parameter is the URI of the extension. The plugin MUST return - * NULL if it does not support the extension, but hosts SHOULD NOT use this - * as a discovery method (e.g. hosts should only call this function for - * extensions known to be supported by the plugin from the data file). - * - * The host is never responsible for freeing the returned value. - *  - * NOTE: This function should return a struct (likely containing function - * pointers) and NOT a direct function pointer.  Standard C and C++ do not - * allow type casts from void* to a function pointer type.  To provide - * additional functions a struct should be returned containing the extra - * function pointers (which is valid standard code, and a much better idea - * for extensibility anyway). */  const void* extension_data(const char *uri)  { -  printf("extension_data(%s)\n", uri); -    if(!strcmp(uri, PLUGIN_INSTANCE_URI)) return &dg_descriptor;    if(!strcmp(uri, LV2_STATE__interface)) return &dg_persist;    return NULL; diff --git a/lv2/lv2_instance.h b/lv2/lv2_instance.h index b4772f6..e050e22 100644 --- a/lv2/lv2_instance.h +++ b/lv2/lv2_instance.h @@ -29,7 +29,7 @@  #include <lv2/lv2plug.in/ns/lv2core/lv2.h>  #include <lv2/lv2plug.in/ns/ext/state/state.h> -#include <lv2/lv2plug.in/ns/ext/uri-map/uri-map.h> +#include <lv2/lv2plug.in/ns/ext/urid/urid.h>  #include "input_lv2.h"  #include "output_lv2.h" @@ -42,8 +42,7 @@ typedef struct {    DrumGizmo *dg;    sample_t *buffer;    size_t buffer_size; -  LV2_URI_Map_Feature *urimap; -  LV2_State_Make_Path *makepath; +  LV2_URID_Map* map;  } DGLV2;  #endif/*__DRUMGIZMO_LV2_INSTANCE_H__*/ diff --git a/lv2/output_lv2.cc b/lv2/output_lv2.cc index ef2500b..09999cb 100644 --- a/lv2/output_lv2.cc +++ b/lv2/output_lv2.cc @@ -62,11 +62,9 @@ void OutputLV2::pre(size_t nsamples)  {  } -#include <stdio.h>  void OutputLV2::run(int ch, sample_t *samples, size_t nsamples)  {    if(ch < NUM_OUTPUTS) { -    //    if(outputPorts[ch].size != nsamples) printf("port.%d nsamples.%d\n", outputPorts[ch].size, nsamples);      if(outputPorts[ch].samples) {        memcpy(outputPorts[ch].samples, samples, nsamples * sizeof(sample_t));      } diff --git a/lv2/output_lv2.h b/lv2/output_lv2.h index 1b4e8c9..a3a2555 100644 --- a/lv2/output_lv2.h +++ b/lv2/output_lv2.h @@ -55,7 +55,6 @@ public:    sample_t *getBuffer(int c); -  //  sample_t *outputPort[NUM_OUTPUTS];    OutputPort outputPorts[NUM_OUTPUTS];  }; diff --git a/src/configuration.cc b/src/configuration.cc index 965dcf9..5c733ee 100644 --- a/src/configuration.cc +++ b/src/configuration.cc @@ -35,19 +35,4 @@ float Conf::velocity_randomiser_weight = 0.1;  int Conf::samplerate = 44100; -#ifdef TEST_CONFIGURATION -//Additional dependency files -//deps: -//Required cflags (autoconf vars may be used) -//cflags: -//Required link options (autoconf vars may be used) -//libs: -#include "test.h" - -TEST_BEGIN; - -// TODO: Put some testcode here (see test.h for usable macros). - -TEST_END; - -#endif/*TEST_CONFIGURATION*/ +bool Conf::enable_resampling = true; diff --git a/src/configuration.h b/src/configuration.h index c49f997..b8be49f 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -36,6 +36,8 @@ namespace Conf {    extern float velocity_randomiser_weight;    extern int samplerate; + +  extern bool enable_resampling;  }; diff --git a/src/drumgizmo.cc b/src/drumgizmo.cc index ddb6358..6fd454e 100644 --- a/src/drumgizmo.cc +++ b/src/drumgizmo.cc @@ -282,24 +282,26 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)    //    // Write audio    // -#ifndef WITH_RESAMPLER -  // No resampling needed -  for(size_t c = 0; c < kit.channels.size(); c++) { -    sample_t *buf = samples; -    bool internal = false; -    if(oe->getBuffer(c)) { -      buf = oe->getBuffer(c); -      internal = true; -    } -    if(buf) { -      memset(buf, 0, nsamples * sizeof(sample_t)); -       -      getSamples(c, pos, buf, nsamples); +#ifdef WITH_RESAMPLER +  if(Conf::enable_resampling == false) { // No resampling needed +#endif +    for(size_t c = 0; c < kit.channels.size(); c++) { +      sample_t *buf = samples; +      bool internal = false; +      if(oe->getBuffer(c)) { +        buf = oe->getBuffer(c); +        internal = true; +      } +      if(buf) { +        memset(buf, 0, nsamples * sizeof(sample_t)); + +        getSamples(c, pos, buf, nsamples); -      if(!internal) oe->run(c, samples, nsamples); +        if(!internal) oe->run(c, samples, nsamples); +      }      } -  } -#else/*WITH_RESAMPLER*/ +#ifdef WITH_RESAMPLER +  } else {    // Resampling needed    // @@ -337,6 +339,8 @@ bool DrumGizmo::run(size_t pos, sample_t *samples, size_t nsamples)    for(size_t c = 0; c < kit.channels.size(); c++) {      oe->run(c, resampler_output_buffer[c], nsamples);    } + +  }  #endif/*WITH_RESAMPLER*/    ie->post(); @@ -546,6 +550,11 @@ bool DrumGizmo::setConfigString(std::string cfg)        str2float(p.value("velocity_randomiser_weight"));    } +  if(p.value("enable_resampling") != "") { +    Conf::enable_resampling = +      p.value("enable_resampling") == "true"; +  } +    std::string newkit = p.value("drumkitfile");    if(newkit != "" && kit.file() != newkit) {      /* diff --git a/test/Makefile.am b/test/Makefile.am index e43a6ba..5aaf33f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,7 +1,7 @@  # Rules for the test code (use `make check` to execute)  include $(top_srcdir)/src/Makefile.am.drumgizmo -TESTS = engine gui resampler +TESTS = engine gui resampler lv2  check_PROGRAMS = $(TESTS) @@ -29,4 +29,14 @@ resampler_LDFLAGS = $(ZITA_LIBS) $(SAMPLERATE_LIBS) $(CPPUNIT_LIBS)  resampler_SOURCES = \  	$(top_srcdir)/src/chresampler.cc \  	test.cc \ -	resampler.cc
\ No newline at end of file +	resampler.cc + +lv2_CXXFLAGS = -DOUTPUT=\"lv2\" $(CPPUNIT_CFLAGS) \ +	 `pkg-config --cflags serd-0` `pkg-config --cflags lilv-0` \ +	-DLV2_PATH=\"$(libdir)/lv2\" +lv2_LDFLAGS = $(CPPUNIT_LIBS) `pkg-config --libs serd-0` \ +	`pkg-config --libs lilv-0` -lcrypto +lv2_SOURCES = \ +	test.cc \ +	lv2_test_host.cc \ +	lv2.cc diff --git a/test/kit/instr1.xml b/test/kit/instr1.xml index 3257c95..6b600d5 100644 --- a/test/kit/instr1.xml +++ b/test/kit/instr1.xml @@ -1,5 +1,5 @@  <?xml version='1.0' encoding='UTF-8'?> -<instrument name="snare"> +<instrument name="instr1">   <samples>    <sample name="stroke1">     <audiofile channel="ch1" file="1111.wav"/> diff --git a/test/kit/instr2.xml b/test/kit/instr2.xml index 30a988a..76cbc80 100644 --- a/test/kit/instr2.xml +++ b/test/kit/instr2.xml @@ -1,5 +1,5 @@  <?xml version='1.0' encoding='UTF-8'?> -<instrument name="snare"> +<instrument name="instr2">   <samples>    <sample name="stroke1">     <audiofile channel="ch1" file="2222.wav"/> diff --git a/test/kit/kit1.xml b/test/kit/kit1.xml index 41cede4..dd4c93e 100644 --- a/test/kit/kit1.xml +++ b/test/kit/kit1.xml @@ -13,7 +13,7 @@  			<channelmap in="ch3" out="ch3"/>  			<channelmap in="ch4" out="ch4"/>  		</instrument> -    <instrument name="instr1" file="instr2.xml"> +    <instrument name="instr2" file="instr2.xml">  			<channelmap in="ch1" out="ch1"/>  			<channelmap in="ch2" out="ch2"/>  			<channelmap in="ch3" out="ch3"/> diff --git a/test/kit/kit2.xml b/test/kit/kit2.xml index 41cede4..dd4c93e 100644 --- a/test/kit/kit2.xml +++ b/test/kit/kit2.xml @@ -13,7 +13,7 @@  			<channelmap in="ch3" out="ch3"/>  			<channelmap in="ch4" out="ch4"/>  		</instrument> -    <instrument name="instr1" file="instr2.xml"> +    <instrument name="instr2" file="instr2.xml">  			<channelmap in="ch1" out="ch1"/>  			<channelmap in="ch2" out="ch2"/>  			<channelmap in="ch3" out="ch3"/> diff --git a/test/lv2.cc b/test/lv2.cc new file mode 100644 index 0000000..bfd2ce5 --- /dev/null +++ b/test/lv2.cc @@ -0,0 +1,332 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            lv2.cc + * + *  Thu Feb 12 14:55:41 CET 2015 + *  Copyright 2015 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <cppunit/extensions/HelperMacros.h> + +#include <unistd.h> +#include <memory.h> +#include <stdio.h> +#include <arpa/inet.h> + +#include "lv2_test_host.h" + +#define DG_URI "http://drumgizmo.org/lv2" + +/** + * Tests that should be performed: + * ------------------------------- + * - Run without port connects (shouldn't crash) + * - Run without output ports connects (shouldn't crash) + * - Run with buffer size 0 + * - Run with VERY LARGE buffer size (>1MB?) + * - Run with buffer size a prime number (and thereby not power of 2) + * - Run with HUGE number of midi events in one buffer (10000) + */ +class test_lv2 : public CppUnit::TestFixture +{ +  CPPUNIT_TEST_SUITE(test_lv2); +	CPPUNIT_TEST(open_and_verify); +	CPPUNIT_TEST(run_no_ports_connected); +	CPPUNIT_TEST(run_no_output_ports_connected); +	CPPUNIT_TEST(test1); +	CPPUNIT_TEST_SUITE_END(); + +public: +	void setUp() {} +	void tearDown() {} + +  void open_and_verify() +  { +    int res; + +    LV2TestHost h(LV2_PATH); + +    res = h.open(DG_URI); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.verify(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.close(); +    CPPUNIT_ASSERT_EQUAL(0, res); +  } + +  void run_no_ports_connected() +  { +    int res; + +    LV2TestHost h(LV2_PATH); + +    res = h.open(DG_URI); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.verify(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.createInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    const char config_fmt[] =  +      "<config>\n" +      "  <value name=\"drumkitfile\">%s</value>\n" +      "  <value name=\"midimapfile\">%s</value>\n" +      "  <value name=\"enable_velocity_modifier\">%s</value>\n" +      "  <value name=\"velocity_modifier_falloff\">%f</value>\n" +      "  <value name=\"velocity_modifier_weight\">%f</value>\n" +      "  <value name=\"enable_velocity_randomiser\">%s</value>\n" +      "  <value name=\"velocity_randomiser_weight\">%f</value>\n" +      "  <value name=\"enable_resampling\">%s</value>\n" +      "</config>"; + +    const char drumkitfile[] = "kit/kit1.xml"; +    const char midimapfile[] = "kit/midimap.xml"; +    bool enable_velocity_modifier = true; +    float velocity_modifier_falloff = 0.5; +    float velocity_modifier_weight = 0.25; +    bool enable_velocity_randomiser = false; +    float velocity_randomiser_weight = 0.1; +    bool enable_resampling = false; + +    char config[sizeof(config_fmt) * 2]; +    sprintf(config, config_fmt, +            drumkitfile, +            midimapfile, +            enable_velocity_modifier?"true":"false", +            velocity_modifier_falloff, +            velocity_modifier_weight, +            enable_velocity_randomiser?"true":"false", +            velocity_randomiser_weight, +            enable_resampling?"true":"false" +            ); + +    res = h.loadConfig(config, strlen(config)); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    // run for 1 samples to trigger kit loading +    res = h.run(1); +    CPPUNIT_ASSERT_EQUAL(0, res); +    sleep(1); // wait for kit to get loaded (async), + +    res = h.run(100); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.destroyInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.close(); +    CPPUNIT_ASSERT_EQUAL(0, res); +  } + +  void run_no_output_ports_connected() +  { +    int res; + +    LV2TestHost h(LV2_PATH); + +    res = h.open(DG_URI); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.verify(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.createInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    const char config_fmt[] =  +      "<config>\n" +      "  <value name=\"drumkitfile\">%s</value>\n" +      "  <value name=\"midimapfile\">%s</value>\n" +      "  <value name=\"enable_velocity_modifier\">%s</value>\n" +      "  <value name=\"velocity_modifier_falloff\">%f</value>\n" +      "  <value name=\"velocity_modifier_weight\">%f</value>\n" +      "  <value name=\"enable_velocity_randomiser\">%s</value>\n" +      "  <value name=\"velocity_randomiser_weight\">%f</value>\n" +      "  <value name=\"enable_resampling\">%s</value>\n" +      "</config>"; + +    const char drumkitfile[] = "kit/kit1.xml"; +    const char midimapfile[] = "kit/midimap.xml"; +    bool enable_velocity_modifier = true; +    float velocity_modifier_falloff = 0.5; +    float velocity_modifier_weight = 0.25; +    bool enable_velocity_randomiser = false; +    float velocity_randomiser_weight = 0.1; +    bool enable_resampling = false; + +    char config[sizeof(config_fmt) * 2]; +    sprintf(config, config_fmt, +            drumkitfile, +            midimapfile, +            enable_velocity_modifier?"true":"false", +            velocity_modifier_falloff, +            velocity_modifier_weight, +            enable_velocity_randomiser?"true":"false", +            velocity_randomiser_weight, +            enable_resampling?"true":"false" +            ); + +    res = h.loadConfig(config, strlen(config)); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    // Port buffers: +    char sequence_buffer[4096]; + +    LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); +    res = h.connectPort(0, seq.data()); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    // run for 1 samples to trigger kit loading +    res = h.run(1); +    CPPUNIT_ASSERT_EQUAL(0, res); +    sleep(1); // wait for kit to get loaded (async), + +    seq.addMidiNote(5, 1, 127); +    res = h.run(100); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.destroyInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.close(); +    CPPUNIT_ASSERT_EQUAL(0, res); +  } + +  void test1() +  { +    int res; + +    LV2TestHost h(LV2_PATH); + +    res = h.open(DG_URI); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.verify(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.createInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    const char config_fmt[] =  +      "<config>\n" +      "  <value name=\"drumkitfile\">%s</value>\n" +      "  <value name=\"midimapfile\">%s</value>\n" +      "  <value name=\"enable_velocity_modifier\">%s</value>\n" +      "  <value name=\"velocity_modifier_falloff\">%f</value>\n" +      "  <value name=\"velocity_modifier_weight\">%f</value>\n" +      "  <value name=\"enable_velocity_randomiser\">%s</value>\n" +      "  <value name=\"velocity_randomiser_weight\">%f</value>\n" +      "  <value name=\"enable_resampling\">%s</value>\n" +      "</config>"; + +    const char drumkitfile[] = "kit/kit1.xml"; +    const char midimapfile[] = "kit/midimap.xml"; +    bool enable_velocity_modifier = true; +    float velocity_modifier_falloff = 0.5; +    float velocity_modifier_weight = 0.25; +    bool enable_velocity_randomiser = false; +    float velocity_randomiser_weight = 0.1; +    bool enable_resampling = false; + +    char config[sizeof(config_fmt) * 2]; +    sprintf(config, config_fmt, +            drumkitfile, +            midimapfile, +            enable_velocity_modifier?"true":"false", +            velocity_modifier_falloff, +            velocity_modifier_weight, +            enable_velocity_randomiser?"true":"false", +            velocity_randomiser_weight, +            enable_resampling?"true":"false" +            ); + +    res = h.loadConfig(config, strlen(config)); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    // Port buffers: +    char sequence_buffer[4096]; +    float pcm_buffer[16][10]; + +    LV2TestHost::Sequence seq(sequence_buffer, sizeof(sequence_buffer)); +    res = h.connectPort(0, seq.data()); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    for(int i = 1; i <= 16; i++) { +      memset(pcm_buffer, 1, sizeof(pcm_buffer)); +      res += h.connectPort(i, pcm_buffer[i-1]); +    } +    CPPUNIT_ASSERT_EQUAL(0, res); + +    // run for 1 samples to trigger kit loading +    res = h.run(1); +    CPPUNIT_ASSERT_EQUAL(0, res); +    sleep(1); // wait for kit to get loaded (async), + +    /* +    seq.addMidiNote(5, 1, 127); +    for(int i = 0; i < 10; i++) { +      res = h.run(10); +      CPPUNIT_ASSERT_EQUAL(0, res); + +      printf("Iteration:\n"); +      for(int k = 0; k < 4; k++) { +        printf("#%d ", k); +        for(int j = 0; j < 10; j++) printf("[%f]", pcm_buffer[k][j]); +        printf("\n"); +      } +      printf("\n"); + +      seq.clear(); +    } +    */ + +    seq.addMidiNote(5, 1, 127); +    res = h.run(10); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    union { +      float f; +      unsigned int u; +    } comp_val; + +    comp_val.u = 1040744448; + +    for(int k = 0; k < 4; k++) { +      for(int j = 0; j < 10; j++) { +        CPPUNIT_ASSERT(pcm_buffer[k][j] == ((j==4)?comp_val.f:0)); +      } +    } +    seq.clear(); + +    res = h.destroyInstance(); +    CPPUNIT_ASSERT_EQUAL(0, res); + +    res = h.close(); +    CPPUNIT_ASSERT_EQUAL(0, res); +  } +}; + +// Registers the fixture into the 'registry' +CPPUNIT_TEST_SUITE_REGISTRATION(test_lv2); diff --git a/test/lv2_test_host.cc b/test/lv2_test_host.cc new file mode 100644 index 0000000..07685d0 --- /dev/null +++ b/test/lv2_test_host.cc @@ -0,0 +1,403 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            lv2_test_host.cc + * + *  Wed Feb 11 23:11:21 CET 2015 + *  Copyright 2015 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "lv2_test_host.h" + +#include <serd/serd.h> + +#include <string.h> +#include <stdlib.h> + +#include <lv2/lv2plug.in/ns/ext/atom/forge.h> +#include <lv2/lv2plug.in/ns/ext/state/state.h> +#include <lv2/lv2plug.in/ns/ext/midi/midi.h> + +/////////////////////////////// +// Base64 encoder: +// +#include <openssl/bio.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <string> +class Base64 { +public: +	Base64() +	{ +		mbio = (void*)BIO_new(BIO_s_mem()); +		BIO *b64bio = BIO_new(BIO_f_base64()); +		bio = (void*)BIO_push(b64bio, (BIO*)mbio); +	} + +	~Base64() +	{ +		BIO_free_all((BIO*)bio); +	} + +	std::string write(std::string in) +	{ +		return this->write(in.data(), in.length()); +	} + +	std::string write(const char *in, size_t size) +	{ +		std::string out; +		 +		BIO_write((BIO*)bio, in, size); + +		size_t osize = BIO_ctrl_pending((BIO*)mbio); +		char *outbuf = (char*)malloc(osize); + +		int len = BIO_read((BIO*)mbio, outbuf, osize); +		if(len < 1) return ""; +		out.append(outbuf, len); + +		free(outbuf); +		 +		return out; +	} +	 +	std::string flush() +	{ +		std::string out; +		 +		(void)BIO_flush((BIO*)bio); + +		size_t size = BIO_ctrl_pending((BIO*)mbio); +		char *outbuf = (char*)malloc(size); + +		int len = BIO_read((BIO*)mbio, outbuf, size); +		if(len < 1) return ""; +		out.append(outbuf, len); + +		free(outbuf); +		 +		return out; +	} + +private: +	void *bio; +	void *mbio; +}; +// +// Base64 encoder +/////////////////////////////// + + +// TODO: Use map<int, std::string> instead +static char** uris = NULL; +static size_t n_uris = 0; + +static LV2_URID map_uri(LV2_URID_Map_Handle handle, const char* uri) +{ +	for(size_t i = 0; i < n_uris; ++i) { +		if(!strcmp(uris[i], uri)) { +			return i + 1; +		} +	} + +	uris = (char**)realloc(uris, ++n_uris * sizeof(char*)); +	uris[n_uris - 1] = strdup(uri); + +	return n_uris; +} + +static const char* unmap_uri(LV2_URID_Map_Handle handle, LV2_URID urid) +{ +	if(urid > 0 && urid <= n_uris) { +		return uris[urid - 1]; +	} +	return NULL; +} + +LV2_URID_Map       map           = { NULL, map_uri }; +LV2_Feature        map_feature   = { LV2_URID_MAP_URI, &map }; +LV2_URID_Unmap     unmap         = { NULL, unmap_uri }; +LV2_Feature        unmap_feature = { LV2_URID_UNMAP_URI, &unmap }; +const LV2_Feature* features[]    = { &map_feature, &unmap_feature, NULL }; + +LV2TestHost::Sequence::Sequence(void *buffer, size_t buffer_size) +{ +  this->buffer = buffer; +  this->buffer_size = buffer_size; + +	seq = (LV2_Atom_Sequence *)buffer; + +	seq->atom.size = sizeof(LV2_Atom_Sequence_Body); +	seq->atom.type = map.map(map.handle, LV2_ATOM__Sequence); +	seq->body.unit = 0; +	seq->body.pad = 0; +} + +// Keep this to support atom extension from lv2 < 1.10 +static inline void +_lv2_atom_sequence_clear(LV2_Atom_Sequence* seq) +{ +  seq->atom.size = sizeof(LV2_Atom_Sequence_Body); +} + +void LV2TestHost::Sequence::clear() +{ +  _lv2_atom_sequence_clear(seq); +} + +// Keep this to support atom extension from lv2 < 1.10 +static inline LV2_Atom_Event* +_lv2_atom_sequence_append_event(LV2_Atom_Sequence*    seq, +                               uint32_t              capacity, +                               const LV2_Atom_Event* event) +{ +  const uint32_t total_size = (uint32_t)sizeof(*event) + event->body.size; +  if (capacity - seq->atom.size < total_size) { +    return NULL; +  } + +  LV2_Atom_Event* e = lv2_atom_sequence_end(&seq->body, seq->atom.size); +  memcpy(e, event, total_size); +   +  seq->atom.size += lv2_atom_pad_size(total_size); +   +  return e; +} + +void LV2TestHost::Sequence::addMidiNote(uint64_t pos, +                                        uint8_t key, int8_t velocity) +{ +	typedef struct { +		LV2_Atom_Event event; +		uint8_t        msg[3]; +	} MIDINoteEvent; + +	uint8_t note_on = 0x90; + +	MIDINoteEvent ev; +	ev.event.time.frames = pos;// sample position +	ev.event.body.type = map.map(map.handle, LV2_MIDI__MidiEvent); +	ev.event.body.size = sizeof(MIDINoteEvent); +  +	ev.msg[0] = note_on; +	ev.msg[1] = key; +	ev.msg[2] = velocity; + +	LV2_Atom_Event *e = +		_lv2_atom_sequence_append_event(seq, this->buffer_size, &ev.event); +  (void)e; +} + +void *LV2TestHost::Sequence::data() +{ +  return buffer; +} + +LV2TestHost::LV2TestHost(const char *lv2_path) +{ +	if(lv2_path) { +    setenv("LV2_PATH", lv2_path, 1); +  } + +	world = lilv_world_new(); +  if(world == NULL) return; + +	lilv_world_load_all(world); +} + +LV2TestHost::~LV2TestHost() +{ +	if(world) lilv_world_free(world); +} + +int LV2TestHost::open(const char *plugin_uri) +{ +  if(world == NULL) return 1; + +	plugins = lilv_world_get_all_plugins(world); +  if(plugins == NULL) return 2; + +	uri = lilv_new_uri(world, plugin_uri); +	if(uri == NULL) return 3; + +	plugin = lilv_plugins_get_by_uri(plugins, uri); +  if(plugin == NULL) return 4; + + +  return 0; +} + +int LV2TestHost::verify() +{ +	bool verify = lilv_plugin_verify(plugin); +  if(!verify) return 1; +  return 0; +} + +int LV2TestHost::close() +{ +  // plugin is a const pointer; nothing to close here. +  return 0; +} + +/* // Get metadata + +static void dumpNodes(LilvNodes *nodes) +{ +	LilvIter* iter = lilv_nodes_begin(nodes); +	while(iter) { +		const LilvNode* node = lilv_nodes_get(nodes, iter); +		printf(" - '%s'\n", lilv_node_as_uri(node)); +		iter = lilv_nodes_next(nodes, iter); +	} +} + +void getMetadata() +{ +	LilvNode* name = lilv_plugin_get_name(plugin); +	if(name) printf("Name: %s\n", lilv_node_as_uri(name)); + +	// ---> line 731 in lilv.h +	bool has_latency = lilv_plugin_has_latency(plugin); +	printf("Has latency: %d\n", has_latency); + +	if(has_latency) { +		uint32_t latency_port_index = lilv_plugin_get_latency_port_index(plugin); +		const LilvPort* port = +			lilv_plugin_get_port_by_index(plugin, latency_port_index); +		// Do something to actually get latency from port.... +	} + +	LilvNode* author = lilv_plugin_get_author_name(plugin); +	if(author) printf("Author: %s\n", lilv_node_as_uri(author)); + +	LilvNode* email = lilv_plugin_get_author_email(plugin); +	if(email) printf("Email: %s\n", lilv_node_as_uri(email)); + +	LilvNode* homepage = lilv_plugin_get_author_homepage(plugin); +	if(homepage) printf("Homepage: %s\n", lilv_node_as_uri(homepage)); + +	LilvNodes* supported = lilv_plugin_get_supported_features(plugin); +	LilvNodes* required = lilv_plugin_get_required_features(plugin); +	LilvNodes* optional = lilv_plugin_get_optional_features(plugin); + +	printf("Supported:\n"); +	dumpNodes(supported); + +	printf("Required:\n"); +	dumpNodes(required); + +	printf("Optional:\n"); +	dumpNodes(optional); + +	lilv_nodes_free(supported); +	lilv_nodes_free(required); +	lilv_nodes_free(optional); +} +*/ +/* +int LV2TestHost::getPorts() +{ +	// Iterate ports: +	const LilvPort* port; +	uint32_t portidx = 0; +	while( (port = lilv_plugin_get_port_by_index(plugin, portidx)) != 0) { +		printf("Port: %d\n", portidx); + +		LilvNode* port_name = lilv_port_get_name(plugin, port); +		if(port_name) printf("  Name: %s\n", lilv_node_as_uri(port_name)); + +		portidx++; +	} +} +*/ +int LV2TestHost::createInstance() +{ +	instance = lilv_plugin_instantiate(plugin, 48000, features); +  if(instance == NULL) return 1; +  return 0; +} + +int LV2TestHost::destroyInstance() +{ +  if(instance) lilv_instance_free(instance); +  return 0; +} + +int LV2TestHost::activate() +{ +	lilv_instance_activate(instance); +  return 0; +} + +int LV2TestHost::deactivate() +{ +	lilv_instance_deactivate(instance); +  return 0; +} + +int LV2TestHost::loadConfig(const char *config, size_t size) +{ +	Base64 b64; +	std::string b64_config = b64.write(config, size); +	b64_config += b64.flush(); + +	//printf("Base 64 config: [%s]\n", b64_config.c_str()); + +	const char ttl_config_fmt[] = +		"<http://drumgizmo.org/lv2/atom#config>\n" +		"        a pset:Preset ;\n" +		"        lv2:appliesTo <http://drumgizmo.org/lv2> ;\n" +		"        state:state [\n" +		"                <http://drumgizmo.org/lv2/atom#config> \"\"\"%s\"\"\"^^xsd:base64Binary\n" +		"        ] .\n"; + +	char ttl_config[sizeof(ttl_config_fmt) * 2 + b64_config.size()]; +	sprintf(ttl_config, ttl_config_fmt, b64_config.c_str()); + +	//printf("ttl config: [%s]\n", ttl_config); + +	{ +		LilvState* restore_state = +			lilv_state_new_from_string(world, &map, ttl_config); +		 +		lilv_state_restore(restore_state, instance, NULL, NULL, +											 LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE, +											 features); +	} + +  return 0; +} + +int LV2TestHost::connectPort(int port, void *portdata) +{ +  //  if(lilv_port_is_a(p, port, lv2_ControlPort)) ... + +	lilv_instance_connect_port(instance, port, portdata); + +  return 0; +} + +int LV2TestHost::run(int num_samples) +{ +  lilv_instance_run(instance, num_samples); +  return 0; +} diff --git a/test/lv2_test_host.h b/test/lv2_test_host.h new file mode 100644 index 0000000..04f48c6 --- /dev/null +++ b/test/lv2_test_host.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            lv2_test_host.h + * + *  Wed Feb 11 23:11:20 CET 2015 + *  Copyright 2015 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of DrumGizmo. + * + *  DrumGizmo is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  DrumGizmo is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with DrumGizmo; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#ifndef __DRUMGIZMO_LV2_TEST_HOST_H__ +#define __DRUMGIZMO_LV2_TEST_HOST_H__ + +#include <lilv/lilv.h> +#include <lv2/lv2plug.in/ns/ext/atom/atom.h> + +class LV2TestHost { +public: +  class Sequence { +  public: +    Sequence(void *buffer, size_t buffer_size); +    void clear(); +    void addMidiNote(uint64_t pos, uint8_t key, int8_t velocity); +    void *data(); + +  private: +    void *buffer; +    size_t buffer_size; +    LV2_Atom_Sequence *seq; +  }; + +  LV2TestHost(const char *lv2_path); +  ~LV2TestHost(); + +  int open(const char *plugin_uri); +  int close(); + +  int verify(); + +  //void getMetadata(); +  //int getPorts(); + +  int createInstance(); +  int destroyInstance(); + +  int connectPort(int port, void *portdata); + +  int activate(); +  int deactivate(); + +  int loadConfig(const char *config, size_t size); +  int run(int num_samples); + + + +private: +  LilvWorld* world; +  const LilvPlugins* plugins;   +	LilvNode* uri; +	const LilvPlugin* plugin; + +  LilvInstance* instance; + +  size_t buffer_size; +}; + +#endif/*__DRUMGIZMO_LV2_TEST_HOST_H__*/ | 
