Adding Dry/Wet controls - Alex
authorterminatorX <>
Thu, 29 Jan 2004 22:41:00 +0000 (22:41 +0000)
committerterminatorX <>
Thu, 29 Jan 2004 22:41:00 +0000 (22:41 +0000)
ChangeLog
src/tX_global.h
src/tX_mastergui.cc
src/tX_vtt.cc
src/tX_vttfx.cc
src/tX_vttfx.h
src/tX_vttgui.cc

index 1a3fbcdc55787b38659449e57fd411954f1c65d1..c008e393176fa110f22fbab61f18c6376e2e6df9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@ All changes were done by me (Alexander K
 This is not a GNU-style ChangeLog but you sort of get the idea what was
 changed.
 
+[v3.82] (pre-release)
+- applied a fix from Juha Erkkila <erkkila@cc.jyu.fi> that makes tX work on
+  systems that don't have procfs mounted.
+- added an optional Dry/Wet control for all LADSPA plugins. Simply click on the
+  plugin's label to add or remove the additional control.
+
 [v3.81]
 - JACK doesn't seem to like SCHED_FIFO clients so I added a little test that
   will set SCHED_OTHER when jack output was selected. This will work for true
index 121ca609c0af66d5a185591c34e143e34faa0024..11a79f29873ad6ba96e71eba18573f30663ba9a6 100644 (file)
@@ -60,6 +60,14 @@ extern "C" {
 #define tX_error(fmt, args...); { fprintf(stderr, "* tX_error: "); fprintf(stderr, fmt , ## args); fprintf(stderr, "\n"); }
 #define tX_warning(fmt, args...); { fprintf(stderr, "+ tX_warning: "); fprintf(stderr, fmt , ## args); fprintf(stderr, "\n"); }
 
+#ifdef MEM_DEBUG
+#define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr);
+#define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr);
+#else
+#define tX_freemem(ptr, varname, comment); free(ptr);
+#define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size);
+#endif
+
 typedef enum {
        OSS =0,
        ALSA = 1,
index 38959018972d811f55945ce18ac6d140cac70ddf..30bdbc2b45dfd4230a51ea5a3a444d1cb699bed5 100644 (file)
@@ -222,8 +222,10 @@ void mg_update_status()
                                gtk_label_set_text(GTK_LABEL(used_mem), buffer);
                        }
                }
+               fclose(procfs); 
+       } else {
+               gtk_label_set_text(GTK_LABEL(used_mem), "");
        }
-       fclose(procfs); 
        
        sprintf(buffer, "%i", vtt_class::vtt_amount);
        gtk_label_set_text(GTK_LABEL(no_of_vtts), buffer);
index da78b3781713891d6b97ab5e37366315fd7afc8a..44e1c1113ece9ca90ab005126032b5b7ac209dcb 100644 (file)
 #include <config.h>
 #endif
 
-#ifdef DEBUG
-#define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr);
-#define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr);
-#else
-#define tX_freemem(ptr, varname, comment); free(ptr);
-#define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size);
-#endif
-
 #include "tX_loaddlg.h"
 
 #define USE_PREFETCH 1
@@ -514,12 +506,14 @@ void vtt_class :: ec_set_volume(f_prec volume)
 
 void vtt_class :: ec_clear_buffer()
 {
-       f_prec *ptr;
+/*     f_prec *ptr;
        
        for (ptr=ec_buffer; ptr<=ec_delay; ptr++) {
                *ptr=0.0;
-       }
-       ec_ptr=ec_buffer;
+       } */
+       
+       memset(ec_buffer, 0, sizeof(ec_buffer));
+       ec_ptr=ec_buffer; 
 }
 
 void vtt_class :: render()
index a34f3e5c43f1dc4990d4e4f62d5619d8ed881f49..08c1b6be1a8fa8bca30ca224d41e629b1771a76f 100644 (file)
@@ -37,6 +37,8 @@ void vtt_fx :: reconnect_buffer()
 }
 
 vtt_fx :: ~vtt_fx() {}
+void vtt_fx::toggle_drywet() {}
+tX_drywet_type vtt_fx::has_drywet_feature() { return NOT_DRYWET_CAPABLE; }
 
 /******************* builtin fx ***/
 
@@ -50,6 +52,7 @@ void vtt_fx_lp :: save (FILE *rc, gzFile rz, char *indent) {
        tX_store("%s<cutoff/>\n", indent);
 }
 
+
 const char *vtt_fx_lp :: get_info_string()
 {
        return "TerminatorX built-in resonant lowpass filter.";
@@ -71,7 +74,6 @@ const char *vtt_fx_ec :: get_info_string()
        return "TerminatorX built-in echo effect.";
 }
 
-
 /******************** LADSPA fx ***/
 /* short cut "cpd" macro to current port descriptor */
 
@@ -81,8 +83,12 @@ const char *vtt_fx_ec :: get_info_string()
 
 void vtt_fx_ladspa :: reconnect_buffer()
 {
-       plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);      
-       plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);             
+       plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);
+       if (wet_buffer) {
+               plugin->getDescriptor()->connect_port(instance, output_port, wet_buffer);       
+       } else {
+               plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);     
+       }
 }
 
 static void wrapstr(char *str)
@@ -154,18 +160,8 @@ vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
        sp->set_vtt(vtt);
        controls.push_back(sp); 
 
-       /* if (plugin->getDescriptor()->run_adding && plugin->getDescriptor()->set_run_adding_gain) {   
-               sp = sp_outgain = new tX_seqpar_vttfx_float();
-               sp->set_mapping_parameters(3, 0, 0.01, 1);
-               sprintf(buffer, "%s: Out Gain", plugin->getName());
-               sp->set_name(buffer, "Out Gain");
-               sp->set_vtt(vtt);
-               controls.push_back(sp);
-       } else {
-               sp_outgain = NULL;
-       } */
-       
-       sp_outgain=NULL;
+       sp_wet=NULL;
+       wet_buffer=NULL;
        
        /* connecting ports */
        for (port=0; port < plugin->getPortCount(); port++) {
@@ -209,23 +205,47 @@ vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
        reconnect_buffer();
 }
 
+void vtt_fx_ladspa :: realloc_drywet() 
+{
+       free_drywet();
+       wet_buffer=(f_prec *) malloc(sizeof(float)*vtt_class::samples_in_mix_buffer);
+}
+
+void vtt_fx_ladspa :: free_drywet()
+{
+       if (wet_buffer) {
+               free(wet_buffer);
+               wet_buffer=NULL;
+       }
+}
+
 void vtt_fx_ladspa :: activate()
 {
+       if (sp_wet) {
+               realloc_drywet();
+       }
+       reconnect_buffer(); // we always have to reconnect...
        if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance);
 }
 
 void vtt_fx_ladspa :: deactivate()
 {
        if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance);
+       
+       free_drywet();
 }
 
 void vtt_fx_ladspa :: run()
 {
-       if (sp_outgain) {
-               plugin->getDescriptor()->set_run_adding_gain(instance, sp_outgain->get_value());
-               plugin->getDescriptor()->run_adding(instance, (vtt_class :: samples_in_mix_buffer)>>1);
-       } else {
-               plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1);
+       plugin->getDescriptor()->run(instance, (vtt_class::samples_in_mix_buffer)>>1);
+       
+       if (wet_buffer) {
+               f_prec wet=sp_wet->get_value();
+               f_prec dry=1.0-wet;
+               
+               for (int sample=0; sample < (vtt_class::samples_in_mix_buffer)>>1; sample++) {
+                       myvtt->output_buffer[sample]=dry*myvtt->output_buffer[sample]+wet*wet_buffer[sample];
+               }
        }
 }
 
@@ -250,6 +270,8 @@ vtt_fx_ladspa :: ~vtt_fx_ladspa()
                delete (*sp);
        }               
        plugin->getDescriptor()->cleanup(instance);
+       
+       if (wet_buffer) free(wet_buffer);
        delete panel;
 }
 
@@ -262,6 +284,7 @@ void vtt_fx_ladspa :: save (FILE *rc, gzFile rz, char *indent) {
        strcat (indent, "\t");
        
        store_int("ladspa_id", ID);
+       store_bool("has_drywet", (sp_wet!=NULL));
        
        for (sp=controls.begin(); sp!=controls.end(); sp++) {
                store_float_sp("param", (*sp)->get_value(), (*(*sp)));
@@ -279,6 +302,7 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) {
        list <tX_seqpar_vttfx *> :: iterator sp=controls.begin();
        int elementFound;
        double val;
+       bool bdummy;
        
        for (xmlNodePtr cur=node->xmlChildrenNode; cur!=NULL; cur=cur->next) {
                if (cur->type == XML_ELEMENT_NODE) {
@@ -286,6 +310,7 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) {
                        
                        restore_int("ladspa_id", dummy);
                        restore_bool("panel_hidden", hidden);
+                       restore_bool_ac("has_drywet", bdummy, add_drywet());
                        
                        if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) {
                                val=0;
@@ -309,3 +334,46 @@ void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) {
        
        panel->hide(hidden);
 }
+
+void vtt_fx_ladspa :: toggle_drywet() {
+       if (sp_wet) {
+               remove_drywet();
+       } else {
+               add_drywet();
+       }
+}
+
+void vtt_fx_ladspa :: add_drywet() {
+       char buffer[1024];
+       
+       sp_wet=new tX_seqpar_vttfx_float();
+       sp_wet->set_mapping_parameters(1.0, 0, 0.01, 1);
+       sprintf(buffer, "%s: Dry/Wet", plugin->getLabel());
+       sp_wet->set_name(buffer, "Dry/Wet");
+       sp_wet->set_vtt(vtt);
+       panel->add_client_widget(sp_wet->get_widget());
+       
+       pthread_mutex_lock(&vtt_class::render_lock);
+       controls.push_back(sp_wet);
+       deactivate();
+       activate();
+       pthread_mutex_unlock(&vtt_class::render_lock);
+}
+
+void vtt_fx_ladspa :: remove_drywet() {
+       pthread_mutex_lock(&vtt_class::render_lock);
+       deactivate();
+
+       controls.remove(sp_wet);
+       delete sp_wet;
+       sp_wet=NULL;
+       
+       activate();
+       pthread_mutex_unlock(&vtt_class::render_lock);
+}
+
+tX_drywet_type vtt_fx_ladspa::has_drywet_feature()
+{ 
+       if (sp_wet) return DRYWET_ACTIVE;
+       else return DRYWET_AVAILABLE;
+}
index c0d22c312d4de85bbde962f4de85775ddcad52e5..3db5cdc826e5e36ffbc1f8da59d84271b8e11955 100644 (file)
 
 /* abstract super class vtt_fx */
 
+typedef enum  {
+       NOT_DRYWET_CAPABLE,
+       DRYWET_AVAILABLE,
+       DRYWET_ACTIVE
+} tX_drywet_type;
+
 class vtt_fx
 {
        protected:
@@ -61,6 +67,8 @@ class vtt_fx
        virtual void run()=NULL;        
        virtual int isEnabled()=NULL;
        virtual void reconnect_buffer();
+       virtual void toggle_drywet();
+       virtual tX_drywet_type has_drywet_feature();
        
        virtual const char *get_info_string()=NULL;
        
@@ -111,7 +119,8 @@ class vtt_fx_ladspa : public vtt_fx
        list <tX_seqpar_vttfx *> controls;
        private:
        tX_seqpar_vttfx *sp_enable;
-       tX_seqpar_vttfx *sp_outgain;
+       tX_seqpar_vttfx *sp_wet;
+       f_prec *wet_buffer;
        int input_port, output_port;
        LADSPA_Handle *instance;
        LADSPA_Plugin *plugin;
@@ -126,7 +135,14 @@ class vtt_fx_ladspa : public vtt_fx
        virtual void run();             
        virtual int isEnabled();
        virtual void reconnect_buffer();
-       virtual const char *get_info_string();  
+       virtual const char *get_info_string();
+       void realloc_drywet();
+       void free_drywet();
+       virtual void toggle_drywet();
+       void add_drywet();
+       void remove_drywet();
+       virtual tX_drywet_type has_drywet_feature();
+       
        virtual void save(FILE *rc, gzFile rz, char *indent);
 #ifdef ENABLE_TX_LEGACY        
        virtual void load(FILE *);
index e093c88d3c63f000485a16f7829fad1c5527e903..b0a0eab40986fd482d1836db3a7006f1de9e1c0c 100644 (file)
@@ -743,7 +743,9 @@ void gui_connect_signals(vtt_class *vtt)
                        G_CALLBACK(drop_file), (void *) vtt);
        
 }
-       
+
+void vg_show_fx_menu(GtkWidget *, vtt_fx *effect);
+
 void build_vtt_gui(vtt_class *vtt)
 {
        GtkWidget *tempbox;
@@ -935,6 +937,7 @@ void build_vtt_gui(vtt_class *vtt)
        /* Lowpass Panel */
 
        p=new tX_panel("Lowpass", g->control_subbox);
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", G_CALLBACK(vg_show_fx_menu), vtt->lp_fx);
        g->lp_panel=p;
                
        g->lp_enable=gtk_check_button_new_with_label("Enable");
@@ -966,6 +969,7 @@ void build_vtt_gui(vtt_class *vtt)
        /* Echo Panel */
 
        p=new tX_panel("Echo", g->control_subbox);
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked",  G_CALLBACK(vg_show_fx_menu), vtt->ec_fx);
        g->ec_panel=p;
 
        p->add_client_widget(vg_create_fx_bar(vtt, vtt->ec_fx, 0));
@@ -1170,6 +1174,44 @@ void vg_show_fx_info(GtkWidget *wid, vtt_fx *effect)
        tx_l_note(effect->get_info_string());
 }
 
+void vg_toggle_drywet(GtkWidget *wid, vtt_fx *effect)
+{
+       effect->toggle_drywet();
+}
+
+void vg_show_fx_menu(GtkWidget *wid, vtt_fx *effect)
+{
+       GtkWidget *menu=gtk_menu_new();
+       GtkWidget *item=gtk_menu_item_new_with_label("Show Info");
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+       gtk_widget_set_sensitive(item, (effect->has_drywet_feature()!=NOT_DRYWET_CAPABLE));
+       gtk_widget_show(item);
+       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_show_fx_info), effect);
+       
+       switch (effect->has_drywet_feature()) {
+               case (NOT_DRYWET_CAPABLE):
+                       item=gtk_menu_item_new_with_label("Add Dry/Wet Control");
+                       gtk_widget_set_sensitive(item, FALSE);
+                       break;
+               case (DRYWET_ACTIVE):
+                       item=gtk_menu_item_new_with_label("Remove Dry/Wet Control");
+                       break;
+               case (DRYWET_AVAILABLE):
+                       item=gtk_menu_item_new_with_label("Add Dry/Wet Control");
+                       break;
+       }
+       
+       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_toggle_drywet), effect);
+       
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+       gtk_widget_show(item);
+
+       gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
+
+       /* gtk+ is really waiting for this.. */
+       g_signal_emit_by_name(G_OBJECT(wid), "released", effect);
+}
+
 void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin)
 {
        char buffer[1024];
@@ -1197,8 +1239,8 @@ void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plug
                        p->add_client_widget((*sp)->get_widget());
        }
 
-       g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_info, (void *) effect);
-       gui_set_tooltip(p->get_labelbutton(), "Click here to learn more about this plugin.");
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_menu, (void *) effect);
+       gui_set_tooltip(p->get_labelbutton(), "Click here for menu");
        effect->set_panel_widget(p->get_widget());
        effect->set_panel(p);