[SCM] calf/master: + Framework, LV2, JACK host: implement progress reporting for instantiation (the JACK host version is just a temporary hack)
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:38:48 UTC 2013
The following commit has been merged in the master branch:
commit 18cb5f13cfde459242691109d9235926b2802785
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Mon Jan 5 23:03:34 2009 +0000
+ Framework, LV2, JACK host: implement progress reporting for instantiation (the JACK host version is just a temporary hack)
diff --git a/src/calf/giface.h b/src/calf/giface.h
index 1a085fb..d5a1121 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -144,6 +144,12 @@ struct cairo_iface
virtual ~cairo_iface() {}
};
+struct progress_report_iface
+{
+ virtual void report_progress(float percentage, const std::string &message) = 0;
+ virtual ~progress_report_iface() {}
+};
+
/// 'provides live line graph values' interface
struct line_graph_iface
{
@@ -300,6 +306,12 @@ class audio_module: public Metadata
public:
typedef Metadata metadata_type;
+ progress_report_iface *progress_report;
+
+ audio_module() {
+ progress_report = NULL;
+ }
+
/// Handle MIDI Note On
inline void note_on(int note, int velocity) {}
/// Handle MIDI Note Off
@@ -327,6 +339,8 @@ public:
inline void send_configures(send_configure_iface *sci) {}
/// Reset parameter values for epp:trigger type parameters (ones activated by oneshot push button instead of check box)
inline void params_reset() {}
+ /// Called after instantiating (after all the feature pointers are set - including interfaces like progress_report_iface)
+ inline void post_instantiate() {}
/// Handle 'message context' port message
/// @arg output_ports pointer to bit array of output port "changed" flags, note that 0 = first audio input, not first parameter (use input_count + output_count)
inline uint32_t message_run(const void *valid_ports, void *output_ports) {
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
index c78cbad..98ce775 100644
--- a/src/calf/jackhost.h
+++ b/src/calf/jackhost.h
@@ -184,11 +184,12 @@ struct vumeter
};
template<class Module>
-class jack_host: public jack_host_base, public Module {
+class jack_host: public jack_host_base, public Module, public calf_plugins::progress_report_iface {
public:
using Module::in_count;
using Module::out_count;
using Module::param_count;
+ using Module::progress_report;
port inputs[in_count], outputs[out_count];
vumeter input_vus[in_count], output_vus[out_count];
@@ -203,6 +204,8 @@ public:
}
clear_preset();
midi_meter = 0;
+ progress_report = this;
+ Module::post_instantiate();
}
~jack_host()
@@ -211,6 +214,13 @@ public:
close();
}
+ virtual void report_progress(float percentage, const std::string &message) {
+ if (!message.empty())
+ printf("Message: %s\n", message.c_str());
+ printf("Percentage: %0.1f\n", percentage);
+ }
+
+
virtual void init_module() {
Module::set_sample_rate(client->sample_rate);
Module::activate();
diff --git a/src/calf/ladspa_wrap.h b/src/calf/ladspa_wrap.h
index 398e688..5e6ae53 100644
--- a/src/calf/ladspa_wrap.h
+++ b/src/calf/ladspa_wrap.h
@@ -300,6 +300,7 @@ struct ladspa_wrapper
{
instance *mod = new instance();
mod->srate = sample_rate;
+ mod->post_instantiate();
return mod;
}
diff --git a/src/calf/lv2_progress.h b/src/calf/lv2_progress.h
new file mode 100644
index 0000000..642dd4f
--- /dev/null
+++ b/src/calf/lv2_progress.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C ; c-basic-offset: 2 -*- */
+/*****************************************************************************
+ *
+ * This work is in public domain.
+ *
+ * This file 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.
+ *
+ * Author of this extension is Nedko Arnaudov <nedko at arnaudov.name>
+ *
+ * Several people helped improving the extension:
+ * * Krzysztof Foltman <wdev at foltman.com>
+ * * Dave Robillard <dave at drobilla.net>
+ *
+ * If you have questions ask in the #lv2 or #lad channel,
+ * FreeNode IRC network or use the lv2 mailing list.
+ *
+ *****************************************************************************/
+
+#ifndef LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED
+#define LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED
+
+/**
+ * @file lv2_progress.h
+ * @brief LV2 progress notification extension definition
+ *
+ * @par Purpose and scope
+ * The purpose of this extension is to prevent thread (often the main one)
+ * freeze for plugins doing intensive computations during instantiation.
+ * Host may want to display progress bar of some sort and if it is using
+ * GUI toolkit event loop, to dispatch queued events.
+ *
+ * @par
+ * Using this extension for reporting progress of other lengthy operations
+ * is possible and encouraged but not subject of this extension alone.
+ * It is probably not good idea to call progress callback from plugin created
+ * thread nor it is good idea to call it from a LV2 audio class function.
+ * Any extension that wants to work in conjuction with progress extension
+ * must define thread context semantics for calling the progress callback.
+ *
+ * @par Plugin instantiation progress usage
+ * Plugin calls the host provided callback on regular basis during
+ * instantiation. One second between calls is good target. Everything between
+ * half second and two seconds should provide enough motion so user does
+ * not get "the thing froze" impression.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+} /* Adjust editor indent */
+#endif
+
+/** URI for the plugin progress feature */
+#define LV2_PROGRESS_URI "http://lv2plug.in/ns/dev/progress"
+
+/** @brief host feature structure */
+typedef struct _LV2_Progress
+{
+ /** to be supplied as first parameter of progress() callback */
+ void * context;
+
+ /**
+ * This function is called by plugin to notify host about progress of a
+ * lengthy operation.
+ *
+ * @param context Host context
+ * @param progress Progress, from 0.0 to 100.0
+ * @param message Optional (may be NULL) string describing current operation.
+ * If called once with non-NULL message, subsequent calls will NULL message
+ * mean that host will reuse the previous message.
+ */
+ void (*progress)(void * context, float progress, const char * message);
+} LV2_Progress;
+
+#if 0
+{ /* Adjust editor indent */
+#endif
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* #ifndef LV2_PROGRESS_H__F576843C_CA13_49C3_9BF9_CFF3A15AD18C__INCLUDED */
diff --git a/src/calf/lv2wrap.h b/src/calf/lv2wrap.h
index 04d12ba..c8c3a52 100644
--- a/src/calf/lv2wrap.h
+++ b/src/calf/lv2wrap.h
@@ -28,15 +28,16 @@
#include <lv2.h>
#include <calf/giface.h>
#include <calf/lv2-midiport.h>
-#include <calf/lv2_event.h>
-#include <calf/lv2_uri_map.h>
#include <calf/lv2_contexts.h>
+#include <calf/lv2_event.h>
+#include <calf/lv2_progress.h>
#include <calf/lv2_string_port.h>
+#include <calf/lv2_uri_map.h>
namespace calf_plugins {
template<class Module>
-struct lv2_instance: public plugin_ctl_iface, public Module
+struct lv2_instance: public plugin_ctl_iface, public progress_report_iface, public Module
{
bool set_srate;
int srate_to_set;
@@ -46,6 +47,7 @@ struct lv2_instance: public plugin_ctl_iface, public Module
LV2_Event_Feature *event_feature;
uint32_t midi_event_type;
std::vector<int> message_params;
+ LV2_Progress *progress_report_feature;
lv2_instance()
{
for (int i=0; i < Module::in_count; i++)
@@ -61,8 +63,16 @@ struct lv2_instance: public plugin_ctl_iface, public Module
set_srate = true;
srate_to_set = 44100;
get_message_context_parameters(message_params);
+ progress_report_feature = NULL;
// printf("message params %d\n", (int)message_params.size());
}
+ /// This, and not Module::post_instantiate, is actually called by lv2_wrapper class
+ void post_instantiate()
+ {
+ if (progress_report_feature)
+ Module::progress_report = this;
+ Module::post_instantiate();
+ }
virtual parameter_properties *get_param_props(int param_no)
{
return &Module::param_props[param_no];
@@ -112,6 +122,10 @@ struct lv2_instance: public plugin_ctl_iface, public Module
virtual void execute(int cmd_no) {
Module::execute(cmd_no);
}
+ virtual void report_progress(float percentage, const std::string &message) {
+ if (progress_report_feature)
+ (*progress_report_feature->progress)(progress_report_feature->context, percentage, !message.empty() ? message.c_str() : NULL);
+ }
void send_configures(send_configure_iface *sci) {
Module::send_configures(sci);
}
@@ -229,8 +243,13 @@ struct lv2_wrapper
{
mod->event_feature = (LV2_Event_Feature *)((*features)->data);
}
+ else if (!strcmp((*features)->URI, LV2_PROGRESS_URI))
+ {
+ mod->progress_report_feature = (LV2_Progress *)((*features)->data);
+ }
features++;
}
+ mod->post_instantiate();
return mod;
}
static inline void zero_by_mask(Module *module, uint32_t mask, uint32_t offset, uint32_t nsamples)
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index c990ddf..76fdd3b 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -209,6 +209,11 @@ public:
{
var_map_curve = "2\n0 1\n1 1\n"; // XXXKF hacky bugfix
}
+
+ void post_instantiate()
+ {
+ dsp::organ_voice_base::precalculate_waves(progress_report);
+ }
void set_sample_rate(uint32_t sr) {
srate = sr;
diff --git a/src/calf/organ.h b/src/calf/organ.h
index ca52697..2c7dbd5 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -152,7 +152,7 @@ public:
static inline big_wave_family &get_big_wave(int wave) {
return (*big_waves)[wave];
}
- static void precalculate_waves();
+ static void precalculate_waves(calf_plugins::progress_report_iface *reporter);
void update_pitch()
{
float phase = dsp::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate_ref);
@@ -302,7 +302,6 @@ struct drawbar_organ: public dsp::basic_synth, public calf_plugins::organ_enums
drawbar_organ(organ_parameters *_parameters)
: parameters(_parameters)
, percussion(_parameters) {
- organ_voice_base::precalculate_waves();
}
void render_separate(float *output[], int nsamples)
{
diff --git a/src/organ.cpp b/src/organ.cpp
index 280e21b..65f7e63 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -39,7 +39,7 @@ using namespace calf_plugins;
bool organ_audio_module::get_graph(int index, int subindex, float *data, int points, cairo_iface *context)
{
if (index == par_master) {
- organ_voice_base::precalculate_waves();
+ organ_voice_base::precalculate_waves(progress_report);
if (subindex)
return false;
float *waveforms[9];
@@ -190,7 +190,10 @@ static void padsynth(bandlimiter<ORGAN_WAVE_BITS> blSrc, bandlimiter<ORGAN_BIG_W
#endif
}
-void organ_voice_base::precalculate_waves()
+#define LARGE_WAVEFORM_PROGRESS() do { if (reporter) { progress += 100; reporter->report_progress(floor(progress / totalwaves), "Precalculating large waveforms"); } } while(0)
+
+
+void organ_voice_base::precalculate_waves(progress_report_iface *reporter)
{
static bool inited = false;
if (!inited)
@@ -200,6 +203,10 @@ void organ_voice_base::precalculate_waves()
organ_voice_base::waves = &waves;
organ_voice_base::big_waves = &big_waves;
+ float progress = 0.0;
+ int totalwaves = 1 + wave_count_big;
+ if (reporter)
+ reporter->report_progress(0, "Precalculating small waveforms");
float tmp[ORGAN_WAVE_SIZE];
static bandlimiter<ORGAN_WAVE_BITS> bl;
static bandlimiter<ORGAN_BIG_WAVE_BITS> blBig;
@@ -360,24 +367,28 @@ void organ_voice_base::precalculate_waves()
phaseshift(bl, tmp);
waves[wave_dpls].make(bl, tmp);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
normalize_waveform(tmp, ORGAN_WAVE_SIZE);
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_strings - wave_count_small], 15);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
tmp[i] = -1 + (i * 2.0 / ORGAN_WAVE_SIZE);
normalize_waveform(tmp, ORGAN_WAVE_SIZE);
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_strings2 - wave_count_small], 40);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
tmp[i] = sin(i * 2 * M_PI / ORGAN_WAVE_SIZE);
normalize_waveform(tmp, ORGAN_WAVE_SIZE);
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_sinepad - wave_count_small], 20);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
{
float ph = i * 2 * M_PI / ORGAN_WAVE_SIZE;
@@ -388,6 +399,7 @@ void organ_voice_base::precalculate_waves()
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_bellpad - wave_count_small], 30, 30, true);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
{
float ph = i * 2 * M_PI / ORGAN_WAVE_SIZE;
@@ -398,6 +410,7 @@ void organ_voice_base::precalculate_waves()
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_space - wave_count_small], 30, 30);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
{
float ph = i * 2 * M_PI / ORGAN_WAVE_SIZE;
@@ -408,6 +421,7 @@ void organ_voice_base::precalculate_waves()
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_choir - wave_count_small], 50, 10);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
{
float ph = i * 2 * M_PI / ORGAN_WAVE_SIZE;
@@ -418,6 +432,7 @@ void organ_voice_base::precalculate_waves()
bl.compute_spectrum(tmp);
padsynth(bl, blBig, big_waves[wave_choir2 - wave_count_small], 50, 10);
+ LARGE_WAVEFORM_PROGRESS();
for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
{
float ph = i * 2 * M_PI / ORGAN_WAVE_SIZE;
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list