Adding stereo plugins, fixed LADSPA menus, ignoring NON-RT plugins - Alex
authorterminatorX <>
Sat, 31 Jan 2004 19:27:53 +0000 (19:27 +0000)
committerterminatorX <>
Sat, 31 Jan 2004 19:27:53 +0000 (19:27 +0000)
13 files changed:
ChangeLog
configure.in
src/main.cc
src/tX_ladspa.cc
src/tX_ladspa.h
src/tX_ladspa_class.cc
src/tX_ladspa_class.h
src/tX_vtt.cc
src/tX_vtt.h
src/tX_vttfx.cc
src/tX_vttfx.h
src/tX_vttgui.cc
src/tX_vttgui.h

index c008e393176fa110f22fbab61f18c6376e2e6df9..6d3cc669352fc872af6862552b57f66f19f672b7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,11 @@ changed.
   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.
+- added an additional stereo effects queue that allows loading stereo LADPSA 
+  plugins. The stereo effects are located below the mono effects - to add a new
+  instance press the "Stereo FX" button and select the plugin of your choice.
+- fixed the plugin menu - empty categories no longer get a menu entry.
+- plugins that do not qualify as realtime capable will now be disabled.
 
 [v3.81]
 - JACK doesn't seem to like SCHED_FIFO clients so I added a little test that
index ffaa594893df2a97b7836b77ece91f2920f48b3c..58a092c8acb0dff48e97ada6984191f1c9382380 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/tX_global.h)
-AM_INIT_AUTOMAKE(terminatorX, 3.81)
+AM_INIT_AUTOMAKE(terminatorX, 3.82)
 AM_CONFIG_HEADER(config.h)
 
 AC_ARG_ENABLE(sox,             [  --enable-sox            use sox as input converter. (default=auto) ])
index 4afcb912cfc52efa2c98bf8db1ab6dd59c358525..909a04a5f7d6fc7f66863e4292124f7ff35de156 100644 (file)
@@ -242,6 +242,7 @@ int main(int argc, char **argv)
 
        LADSPA_Class::init();
        LADSPA_Plugin::init();
+       //LADSPA_Class::dump();
 #ifdef USE_JACK        
        tX_jack_client::init();
 #endif 
index 8c17c9732e2c36ae712c54703cf5cb14409486a8..faf1c2687138f66b397ea64ab70d4d2b5491693d 100644 (file)
@@ -33,6 +33,7 @@
 #include <string.h>
 
 std::list <LADSPA_Plugin *> LADSPA_Plugin :: plugin_list;
+std::list <LADSPA_Stereo_Plugin *> LADSPA_Stereo_Plugin :: stereo_plugin_list;
 
 void LADSPA_Plugin :: init ()
 {
@@ -83,6 +84,8 @@ void LADSPA_Plugin :: handlelib(void *lib, LADSPA_Descriptor_Function desc_func,
        for (i=0; (descriptor = desc_func(i)) != NULL; i++) {           
                if (LADSPA_IS_INPLACE_BROKEN(descriptor->Properties)) {
                        tX_warning("Plugin \"%s\" disabled. No in-place processing support.", descriptor->Name);
+               } else if (!LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties)) {
+                       tX_warning("Plugin \"%s\" disabled. Not realtime capable.", descriptor->Name);                  
                } else {                
                        in_audio=0; out_audio=0; in_ctrl=0;
                
@@ -97,8 +100,10 @@ void LADSPA_Plugin :: handlelib(void *lib, LADSPA_Descriptor_Function desc_func,
                        
                        if ((in_audio == 1) && (out_audio == 1)) {
                                new LADSPA_Plugin(descriptor, filename);
+                       } if ((in_audio == 2) && (out_audio == 2)) {
+                               new LADSPA_Stereo_Plugin(descriptor, filename);
                        }
-                       else { tX_warning("Plugin \"%s\" disabled. Not a 1-in/1-out plugin.", descriptor->Name); }
+                       else { tX_warning("Plugin \"%s\" disabled. Neither mono nor stereo.", descriptor->Name); }
                }
        }
 }
@@ -200,3 +205,42 @@ LADSPA_Plugin * LADSPA_Plugin :: getPluginByUniqueID(long ID)
 
        return NULL;
 }
+
+/* STEREO */
+
+LADSPA_Stereo_Plugin :: LADSPA_Stereo_Plugin (const LADSPA_Descriptor *ld, char *filename)
+{
+       ladspa_descriptor = ld;
+       
+       stereo_plugin_list.push_back(this);
+       strcpy(file, filename);
+       sprintf(info_string, "LADSPA-Stereo-Plugin: %s\nLabel: %s\nFile: %s\nUnique ID: %li\nMaker: %s\nCopyright: %s", ld->Name, ld->Label, file, ld->UniqueID, ld->Maker, ld->Copyright);
+       LADSPA_Class::add_stereo_plugin(this);
+}
+
+LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByIndex(int i)
+{
+       std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
+       int p;
+       
+       plugin = stereo_plugin_list.begin();
+       for (p=0; (p<i) && (plugin != stereo_plugin_list.end()); p++, plugin++);
+       
+       if (plugin==stereo_plugin_list.end()) return NULL;
+       
+       else return (*plugin);
+}
+
+LADSPA_Stereo_Plugin * LADSPA_Stereo_Plugin :: getPluginByUniqueID(long ID)
+{
+       std::list <LADSPA_Stereo_Plugin *> :: iterator plugin;
+       
+       for (plugin=stereo_plugin_list.begin(); plugin != stereo_plugin_list.end(); plugin++) {
+               if ((*plugin)->getUniqueID()==ID) return (*plugin);
+       }
+
+       return NULL;
+}
+
+bool LADSPA_Stereo_Plugin::is_stereo() { return true; }
+bool LADSPA_Plugin::is_stereo() { return false; }
index 1af4e7daf94965ae10e50e0ab1829847099072f2..de508035f81ef4adf782fc1061fe4a5247338e6e 100644 (file)
@@ -31,12 +31,14 @@ using namespace std;
 
 class LADSPA_Plugin
 {
-       private:
+       protected:
        const LADSPA_Descriptor *ladspa_descriptor;
        LADSPA_Plugin(const LADSPA_Descriptor *ld, char *filename);
+       LADSPA_Plugin() {}
        char info_string[4096];
        char file[1024];
        
+       private:
        static list <LADSPA_Plugin *> plugin_list;
        static void scandir(char *dir);
        static void handlelib(void *lib, LADSPA_Descriptor_Function desc_func, char* filename);
@@ -45,6 +47,7 @@ class LADSPA_Plugin
        static void init();
        static void status();
        static void debug_display();
+       virtual bool is_stereo();
        char *get_info_string() { return info_string; }
        char *get_file_name() { return file; }
        
@@ -59,4 +62,18 @@ class LADSPA_Plugin
        const LADSPA_Descriptor *getDescriptor() { return ladspa_descriptor; }
 };
 
+class LADSPA_Stereo_Plugin : public LADSPA_Plugin
+{
+       private:
+       static list <LADSPA_Stereo_Plugin *> stereo_plugin_list;
+       
+       public:
+       LADSPA_Stereo_Plugin(const LADSPA_Descriptor *ld, char *filename);
+
+       public:
+       virtual bool is_stereo();
+       static LADSPA_Stereo_Plugin * getPluginByIndex(int i);
+       static LADSPA_Stereo_Plugin * getPluginByUniqueID(long ID);     
+};
+
 #endif
index 5cfe6a9ce98f9f8012fc2c6201313cd00ce03fff..3d236907f02b6432d9577aa935a4ed2a12fe1e1f 100644 (file)
@@ -202,12 +202,16 @@ LADSPA_Class :: LADSPA_Class() : label("Unclassified"), accept_all(true) {
 }
 
 bool LADSPA_Class :: add_plugin(LADSPA_Plugin *plugin) {
-       return root->add_plugin_instance(plugin);
+       return root->add_plugin_instance(plugin, MONO);
 }
 
-bool LADSPA_Class :: add_plugin_instance(LADSPA_Plugin *plugin) {
+bool LADSPA_Class :: add_stereo_plugin(LADSPA_Stereo_Plugin *plugin) {
+       return root->add_plugin_instance(plugin, STEREO);
+}
+
+bool LADSPA_Class :: add_plugin_instance(LADSPA_Plugin *plugin, LADSPA_Plugin_Type type) {
        if (accept_all) {
-               insert_plugin(plugin);
+               insert_plugin(plugin, type);
                return true;
        }
        
@@ -219,7 +223,7 @@ bool LADSPA_Class :: add_plugin_instance(LADSPA_Plugin *plugin) {
        for (i=registered_ids.begin(); i!=registered_ids.end(); i++) {
                if ((*i)==id) {
                        /* The plugin belongs to this class... */
-                       insert_plugin(plugin);
+                       insert_plugin(plugin, type);
                        return true;
                }
        }
@@ -230,7 +234,7 @@ bool LADSPA_Class :: add_plugin_instance(LADSPA_Plugin *plugin) {
        for (cls=subclasses.begin(); cls!=subclasses.end(); cls++) {
                LADSPA_Class *lrdf_class=(*cls);
                
-               if (lrdf_class->add_plugin_instance(plugin)) return true;
+               if (lrdf_class->add_plugin_instance(plugin, type)) return true;
        }
        
        /* Giving up... */
@@ -238,20 +242,27 @@ bool LADSPA_Class :: add_plugin_instance(LADSPA_Plugin *plugin) {
        return false;
 }
 
-void LADSPA_Class::insert_plugin(LADSPA_Plugin *plugin) {
+void LADSPA_Class::insert_plugin(LADSPA_Plugin *plugin, LADSPA_Plugin_Type type) {
        std::list <LADSPA_Plugin *> :: iterator i;
+       std::list <LADSPA_Plugin *> *list;
        
-       for (i=plugins.begin(); i!=plugins.end(); i++) {
+       if (type==MONO) {
+               list=&plugins;
+       } else {
+               list=(std::list <LADSPA_Plugin *> *) &stereo_plugins;
+       }
+       
+       for (i=list->begin(); i!=list->end(); i++) {
                LADSPA_Plugin *a_plug=(*i);
                int res=compare(plugin->getName(), a_plug->getName());
                
                if (res < 2) {
-                       plugins.insert(i, plugin);
+                       list->insert(i, plugin);
                        return;
                }
        }
        
-       plugins.push_back(plugin);
+       list->push_back(plugin);
 }
 
 void LADSPA_Class::list(char *buffer) {
@@ -265,6 +276,11 @@ void LADSPA_Class::list(char *buffer) {
                printf("%s - plugin: %s\n", buffer, (*i)->getName());
        }
        
+       std::list <LADSPA_Stereo_Plugin *> :: iterator s;       
+       for (s=stereo_plugins.begin(); s!=stereo_plugins.end(); s++) {
+               printf("%s - stereo plugin: %s\n", buffer, (*s)->getName());
+       }
+       
        std::list <LADSPA_Class *> :: iterator c;
        
        for (c=subclasses.begin(); c!=subclasses.end(); c++) (*c)->list(buffer);
@@ -289,25 +305,63 @@ static void menu_callback(GtkWidget *wid, LADSPA_Plugin *plugin) {
        }
 }
 
+static void stereo_menu_callback(GtkWidget *wid, LADSPA_Stereo_Plugin *plugin) {
+       vtt_class *vtt=LADSPA_Class::get_current_vtt();
+       
+       if (vtt) {
+               vtt->add_stereo_effect(plugin);
+       } else {
+               tX_error("LADSPA_Class::menu_callback() no vtt");
+       }
+}
 
-GtkWidget * LADSPA_Class :: get_menu() {
+int LADSPA_Class :: plugins_in_class(LADSPA_Plugin_Type type) {
+       std::list <LADSPA_Class *> :: iterator cls;
+       std::list <LADSPA_Plugin *> *list;
+       int counter=0;
+       
+       if (type==MONO) {
+               list=&plugins;
+       } else {
+               list=(std::list <LADSPA_Plugin *> *) &stereo_plugins;
+       }
+       counter=list->size();
+       
+       for (cls=subclasses.begin(); cls!=subclasses.end(); cls++) {
+               counter+=(*cls)->plugins_in_class(type);
+       }
+       
+       return counter;
+}
+
+GtkWidget * LADSPA_Class :: get_menu(LADSPA_Plugin_Type type) {
        std::list <LADSPA_Class *> :: iterator cls;
        GtkWidget *menu=gtk_menu_new();
        GtkWidget *item;
+       bool need_separator=false;
        
        for (cls=subclasses.begin(); cls!=subclasses.end(); cls++) {
                LADSPA_Class *c=(*cls);
                
-               if (c->plugins.size() || c->subclasses.size()) {
+               if (c->plugins_in_class(type)>0) {
                        item=gtk_menu_item_new_with_label(c->label);
-                       GtkWidget *submenu=c->get_menu();
+                       GtkWidget *submenu=c->get_menu(type);
                        gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu);
                        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                        gtk_widget_show(item);
+                       need_separator=true;
                }
        }
        
-       if (subclasses.size() && plugins.size()) {
+       std::list <LADSPA_Plugin *> *list;
+       
+       if (type==MONO) {
+               list=&plugins;
+       } else {
+               list=(std::list <LADSPA_Plugin *> *) &stereo_plugins;
+       }
+
+       if (need_separator && list->size()) {
                item = gtk_menu_item_new();
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
                gtk_widget_set_sensitive (item, FALSE);
@@ -316,14 +370,14 @@ GtkWidget * LADSPA_Class :: get_menu() {
        
        std::list <LADSPA_Plugin *> :: iterator plugin;
        
-       for (plugin=plugins.begin(); plugin != plugins.end(); plugin++) {
+       for (plugin=list->begin(); plugin!=list->end(); plugin++) {
                char buffer[512];
                LADSPA_Plugin *p=(*plugin);
                
                sprintf(buffer, "%s - (%s, %li)", p->getName(), p->getLabel(), p->getUniqueID());
                item=gtk_menu_item_new_with_label(buffer);
                gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
-               g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(menu_callback), p);             
+               g_signal_connect(G_OBJECT(item), "activate", (type == MONO) ? G_CALLBACK(menu_callback) : G_CALLBACK(stereo_menu_callback), p);         
                gtk_widget_show(item);
        }
        
@@ -331,5 +385,9 @@ GtkWidget * LADSPA_Class :: get_menu() {
 }
 
 GtkWidget * LADSPA_Class :: get_ladspa_menu() {
-       return root->get_menu();
+       return root->get_menu(MONO);
+}
+
+GtkWidget * LADSPA_Class :: get_stereo_ladspa_menu() {
+       return root->get_menu(STEREO);
 }
index 256de68658a2471e3f8e7a13f98fa4350e7090c9..6ceba55804a68a0f05757a4e10dc62f5b4a4765e 100644 (file)
 #include <gtk/gtk.h>
 #include "tX_vtt.h"
 
+typedef enum {
+       MONO,
+       STEREO
+} LADSPA_Plugin_Type;
+
 class LADSPA_Class { // Yeah, I know "class" name for C++ class - but it just seems to fit best...
        protected:
        static LADSPA_Class *root;
        static LADSPA_Class *unclassified;
+       
        static std::list <char *> rdf_files;
        static vtt_class *current_vtt;
        static bool liblrdf_error;
@@ -46,22 +52,27 @@ class LADSPA_Class { // Yeah, I know "class" name for C++ class - but it just se
        std::list <LADSPA_Class *> subclasses;
        std::list <long> registered_ids;
        std::list <LADSPA_Plugin *> plugins;
+       std::list <LADSPA_Stereo_Plugin *> stereo_plugins;
        
        static void scandir(char *dir);
-       bool add_plugin_instance(LADSPA_Plugin *);
+       bool add_plugin_instance(LADSPA_Plugin *, LADSPA_Plugin_Type);
        void insert_class(LADSPA_Class *);
-       void insert_plugin(LADSPA_Plugin *);
+       void insert_plugin(LADSPA_Plugin *, LADSPA_Plugin_Type);
+       int plugins_in_class(LADSPA_Plugin_Type type);
        void list(char *);
-       GtkWidget *get_menu();
+       GtkWidget *get_menu(LADSPA_Plugin_Type);
        
        public:
        LADSPA_Class(char *uri);
        LADSPA_Class(); // For the unclassified class;  
        
        static bool add_plugin(LADSPA_Plugin *plugin);
+       static bool add_stereo_plugin(LADSPA_Stereo_Plugin *plugin);
+       
        static void init();
        static void dump();
        static GtkWidget *get_ladspa_menu();
+       static GtkWidget *get_stereo_ladspa_menu();
        static void set_current_vtt(vtt_class *vtt) { current_vtt=vtt; }
        static vtt_class *get_current_vtt() { return current_vtt; }
 };
index 44e1c1113ece9ca90ab005126032b5b7ac209dcb..69ce1333999685f861885ee895772a070c5204df 100644 (file)
@@ -106,6 +106,7 @@ vtt_class :: vtt_class (int do_create_gui)
        ec_length=1;
        ec_output_buffer=NULL;
        output_buffer=NULL;
+       output_buffer2=NULL;
        
        set_volume(1);
        set_pitch(1);
@@ -206,6 +207,8 @@ vtt_class :: ~vtt_class()
        if (audiofile) delete audiofile;
        //if (buffer) free(buffer);
        if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
+       if (output_buffer2) tX_freemem(output_buffer2, "output_buffer2", "vtt Destructor");
+               
        vtt_amount--;
        
        if (mix_solo) solo_ctr--;
@@ -279,6 +282,8 @@ int vtt_class :: set_output_buffer_size(int newsize)
 
        if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
        tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
+       if (output_buffer2) tX_freemem(output_buffer2, "output_buffer2", "vtt set_output_buffer2_size()");
+       tX_malloc(output_buffer2, "output_buffer2", "vtt set_output_buffer2_size()", sizeof(float)*newsize, (float *));
 
        end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
        
@@ -290,8 +295,7 @@ int vtt_class :: set_output_buffer_size(int newsize)
                (*effect)->reconnect_buffer();
        }
        
-       if (output_buffer) return(0);   
-       else return(0);
+       return 0;       
 }
 
 void vtt_class :: set_volume(f_prec newvol)
@@ -519,7 +523,7 @@ void vtt_class :: ec_clear_buffer()
 void vtt_class :: render()
 {
        list <vtt_fx *> :: iterator effect;
-
+       
        if (do_scratch) {
                if (sense_cycles>0) {
                        sense_cycles--;
@@ -531,6 +535,42 @@ void vtt_class :: render()
        for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
                if ((*effect)->isEnabled()) (*effect)->run();
        }
+       
+       if (stereo_fx_list.size()>0) {
+               // fill 2nd channel
+               memcpy((void *) output_buffer2, (void *) output_buffer, sizeof(float)*((int)samples_in_outputbuffer));
+               
+               // apply stereo effects.
+               list <vtt_fx_stereo_ladspa *> :: iterator stereo_effect;
+               
+               for (stereo_effect=stereo_fx_list.begin(); stereo_effect != stereo_fx_list.end(); stereo_effect++) {
+                       if ((*stereo_effect)->isEnabled()) (*stereo_effect)->run();
+               }
+
+               for (int sample=0; sample<samples_in_outputbuffer; sample++) {                          
+                       f_prec temp=output_buffer[sample]*=res_volume_left;
+                       output_buffer2[sample]*=res_volume_right;
+                       
+                       temp=fabs(temp);
+                       if (temp>max_value) max_value=temp;
+               }
+       } else {
+               for (int sample=0; sample<samples_in_outputbuffer; sample++) {                          
+                       output_buffer2[sample]=output_buffer[sample]*res_volume_right;
+                       f_prec temp=output_buffer[sample]*=res_volume_left;
+                       
+                       temp=fabs(temp);
+                       if (temp>max_value) max_value=temp;
+               }
+       }
+       
+       if (ec_enable) {
+               for (int sample=0; sample<samples_in_outputbuffer; sample++) {
+                       f_prec temp=ec_output_buffer[sample];
+                       output_buffer[sample]+=temp*ec_volume_left;
+                       output_buffer2[sample]+=temp*ec_volume_right;
+               }
+       }       
 }
 
 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
@@ -549,6 +589,20 @@ vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
        return new_effect;
 }
 
+vtt_fx_stereo_ladspa * vtt_class :: add_stereo_effect (LADSPA_Stereo_Plugin *plugin)
+{
+       vtt_fx_stereo_ladspa *new_effect;
+       
+       new_effect = new vtt_fx_stereo_ladspa(plugin, this);
+       pthread_mutex_lock(&render_lock);
+       stereo_fx_list.push_back(new_effect);
+       if (is_playing) new_effect->activate();
+       pthread_mutex_unlock(&render_lock);
+       vg_create_fx_gui(this, new_effect, plugin);
+       
+       return new_effect;
+}
+
 void vtt_class :: calc_speed()
 {
        do_mute=0;
@@ -839,34 +893,12 @@ int16_t * vtt_class :: render_all_turntables()
        } else {
                        vtt=render_list.begin();
                        (*vtt)->render();                       
-                       max=(*vtt)->max_value;
-                       min=max;
-
-                       for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {                                
-                               temp=(*vtt)->output_buffer[sample];
-                               mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
-                               mix_sample++;
-                               mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
-                               mix_sample++;
-                               
-                               if (temp>max) max=temp;
-                               else if (temp<min) min=temp;
-                       }
                        
-                       min*=-1.0;
-                       if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
-
-                       if ((*vtt)->ec_enable) {
-                               for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {                                
-                                       temp=(*vtt)->ec_output_buffer[sample];
-                                       
-                                       mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
-                                       mix_sample++;
-                                       mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
-                                       mix_sample++;
-                               }
+                       for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
+                               mix_buffer[mix_sample++]=(*vtt)->output_buffer[sample];
+                               mix_buffer[mix_sample++]=(*vtt)->output_buffer2[sample];
                        }
-                       
+
                        if (master_triggered) {
                                for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
                                        if ((*vtt)->is_sync_client)     {
@@ -881,34 +913,13 @@ int16_t * vtt_class :: render_all_turntables()
                        }
                        
                        vtt=render_list.begin();
+                       
                        for (vtt++; vtt!=render_list.end(); vtt++) {
                                (*vtt)->render();                                       
-                               max=(*vtt)->max_value;
-                               min=max;
 
                                for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
-                                       temp=(*vtt)->output_buffer[sample];
-                                       mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
-                                       mix_sample++;                                   
-                                       mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
-                                       mix_sample++;
-                               
-                                       if (temp>max) max=temp;
-                                       else if (temp<min) min=temp;
-                               }
-                               
-                               min*=-1.0;
-                               if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
-                               
-                               if ((*vtt)->ec_enable) {
-                                       for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
-                                               temp=(*vtt)->ec_output_buffer[sample];
-                                               
-                                               mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
-                                               mix_sample++;
-                                               mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
-                                               mix_sample++;
-                                       }
+                                       mix_buffer[mix_sample++]+=(*vtt)->output_buffer[sample];
+                                       mix_buffer[mix_sample++]+=(*vtt)->output_buffer2[sample];
                                }
                        }
                        
@@ -1042,8 +1053,6 @@ void vtt_class :: retrigger()
 
 int vtt_class :: trigger(bool need_lock)
 {
-       list <vtt_fx *> :: iterator effect;
-
        if (!buffer) return 1;
        
        retrigger();
@@ -1054,7 +1063,11 @@ int vtt_class :: trigger(bool need_lock)
                cleanup_required=false;
                
                /* activating plugins */
-               for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
+               for (list <vtt_fx *> :: iterator effect=fx_list.begin(); effect != fx_list.end(); effect++) {
+                       (*effect)->activate();
+               }
+               
+               for (list <vtt_fx_stereo_ladspa *> :: iterator effect=stereo_fx_list.begin(); effect != stereo_fx_list.end(); effect++) {
                        (*effect)->activate();
                }
                
@@ -1252,7 +1265,6 @@ void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
 
 int  vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
-       list <vtt_fx *> :: iterator effect;
        char tmp_xml_buffer[4096];
        
        int res=0;
@@ -1317,12 +1329,21 @@ int  vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
        tX_store("%s<fx>\n", indent);
        strcat(indent, "\t");
        
-       for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
+       for (list <vtt_fx *> :: iterator effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
                (*effect)->save(rc, rz, indent);
        }
        indent[strlen(indent)-1]=0;
        tX_store("%s</fx>\n", indent);
        
+       tX_store("%s<stereo_fx>\n", indent);
+       strcat(indent, "\t");
+       
+       for (list <vtt_fx_stereo_ladspa *> :: iterator effect=stereo_fx_list.begin(); effect!=stereo_fx_list.end(); effect++) {
+               (*effect)->save(rc, rz, indent);
+       }
+       indent[strlen(indent)-1]=0;
+       tX_store("%s</stereo_fx>\n", indent);
+               
        indent[strlen(indent)-1]=0;
        tX_store("%s</turntable>\n", indent);
        
@@ -1417,7 +1438,9 @@ int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
                        restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
                        vg_adjust_zoom(gui.zoom, this);
                        
-                       if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
+                       if ((xmlStrcmp(cur->name, (xmlChar *) "fx")==0) || 
+                               (xmlStrcmp(cur->name, (xmlChar *) "stereo_fx")==0))  {
+                               bool stereo=(xmlStrcmp(cur->name, (xmlChar *) "stereo_fx")==0);
                                xmlNodePtr fx=cur;
                                elementFound=1;
                                
@@ -1448,8 +1471,25 @@ int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
                                                        
                                                        if (ladspa_id!=-1) {
                                                                LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
+                                                               if (!plugin) plugin=LADSPA_Stereo_Plugin::getPluginByUniqueID(ladspa_id);
+                                                               
                                                                if (plugin) {
-                                                                       vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
+                                                                       vtt_fx_ladspa *ladspa_effect=NULL;
+                                                                       
+                                                                       if (plugin->is_stereo()) {
+                                                                               ladspa_effect=add_stereo_effect((LADSPA_Stereo_Plugin *) plugin);
+                                                                               if (!stereo) {
+                                                                                       sprintf(buffer,"Trying to load mono plugin into stereo queue [%i].", ladspa_id);
+                                                                                       tx_note(buffer, true);                                                  
+                                                                               }
+                                                                       } else {
+                                                                               ladspa_effect=add_effect(plugin);
+                                                                               if (stereo) {
+                                                                                       sprintf(buffer,"Trying to load stereo plugin into mono queue [%i].", ladspa_id);
+                                                                                       tx_note(buffer, true);                                                  
+                                                                               }                                                                               
+                                                                       }
+                                                                       
                                                                        ladspa_effect->load(doc, pluginNode);
                                                                } else {
                                                                        sprintf(buffer,"The terminatorX set file you are loading makes use of a LADSPA plugin that is not installed on this machine. The plugin's ID is [%i].", ladspa_id);
@@ -1621,23 +1661,30 @@ void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
        if (fn) new_tt->load_file(fn);
 }
 
-extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
-extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
+extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt, bool stereo);
+extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt, bool stereo);
 
-//#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
+//#define debug_fx_stack(); for (i=list->begin(); i != list->end(); i++) puts((*i)->get_info_string());
 #define debug_fx_stack();
 
 void vtt_class :: effect_up(vtt_fx *effect)
 {
        list <vtt_fx *> :: iterator i;
        list <vtt_fx *> :: iterator previous;
+       list <vtt_fx *> *list;
        int ok=0;
        
+       if (effect->is_stereo()) {
+               list=(std::list <vtt_fx *> *) &stereo_fx_list;
+       } else {
+               list=&fx_list;
+       }
+       
        debug_fx_stack();
        
-       if ((*fx_list.begin())==effect) return;
+       if ((*list->begin())==effect) return;
        
-       for (previous=i=fx_list.begin(); i != fx_list.end(); i++) {
+       for (previous=i=list->begin(); i != list->end(); i++) {
                if ((*i) == effect) {
                        ok=1;
                        break;
@@ -1647,11 +1694,11 @@ void vtt_class :: effect_up(vtt_fx *effect)
        
        if (ok) {       
                pthread_mutex_lock(&render_lock);
-               fx_list.remove(effect);
-               fx_list.insert(previous, effect);
+               list->remove(effect);
+               list->insert(previous, effect);
                pthread_mutex_unlock(&render_lock);
 
-               vg_move_fx_panel_up(effect->get_panel_widget(), this);
+               vg_move_fx_panel_up(effect->get_panel_widget(), this, effect->is_stereo());
        }
        
        debug_fx_stack();
@@ -1660,27 +1707,34 @@ void vtt_class :: effect_up(vtt_fx *effect)
 void vtt_class :: effect_down(vtt_fx *effect)
 {
        list <vtt_fx *> :: iterator i;
+       list <vtt_fx *> *list;
        int ok=0;
+       
+       if (effect->is_stereo()) {
+               list=(std::list <vtt_fx *> *) &stereo_fx_list;
+       } else {
+               list=&fx_list;
+       }
 
        debug_fx_stack();
                
-       for (i=fx_list.begin(); i != fx_list.end(); i++) {
+       for (i=list->begin(); i != list->end(); i++) {
                if ((*i) == effect) {
                        ok=1;
                        break;
                }
        }
        
-       if ((ok) && (i!=fx_list.end())) {
+       if ((ok) && (i!=list->end())) {
                i++;
-               if (i==fx_list.end()) return;
+               if (i==list->end()) return;
                i++;
 
                pthread_mutex_lock(&render_lock);
-               fx_list.remove(effect);
+               list->remove(effect);
                
-               fx_list.insert(i, effect);
-               vg_move_fx_panel_down(effect->get_panel_widget(), this);
+               list->insert(i, effect);
+               vg_move_fx_panel_down(effect->get_panel_widget(), this, effect->is_stereo());
                pthread_mutex_unlock(&render_lock);
        }
        
@@ -1690,7 +1744,11 @@ void vtt_class :: effect_down(vtt_fx *effect)
 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
 {
        pthread_mutex_lock(&render_lock);
-       fx_list.remove(effect);
+       if (effect->is_stereo()) {
+               stereo_fx_list.remove((vtt_fx_stereo_ladspa *) effect);
+       } else {
+               fx_list.remove(effect);
+       }
        pthread_mutex_unlock(&render_lock);
        
        delete effect;
index 2615cd21e208dd7bd35024e648a3282e095885e2..3fd6b530853b016f1ae149b3665ad948bba56b42 100644 (file)
@@ -110,6 +110,9 @@ class vtt_class
        
        f_prec *output_buffer; 
        f_prec *end_of_outputbuffer;
+       
+       f_prec *output_buffer2; // 2nd audio channel
+       
        f_prec samples_in_outputbuffer;
        f_prec inv_samples_in_outputbuffer;
        
@@ -206,6 +209,7 @@ class vtt_class
        f_prec audiofile_pitch_correction;
 
        list <vtt_fx *> fx_list;
+       list <vtt_fx_stereo_ladspa *> stereo_fx_list;
                
        public:
        /* Methods */           
@@ -256,6 +260,7 @@ class vtt_class
        void xy_input(f_prec, f_prec);
 
        vtt_fx_ladspa * add_effect(LADSPA_Plugin *);
+       vtt_fx_stereo_ladspa * add_stereo_effect (LADSPA_Stereo_Plugin *plugin);
        
        void calc_speed();
        void render();
index 08c1b6be1a8fa8bca30ca224d41e629b1771a76f..e2314f5edc1ffb435ac6d51a58c01a6adfe44b9b 100644 (file)
@@ -38,6 +38,7 @@ void vtt_fx :: reconnect_buffer()
 
 vtt_fx :: ~vtt_fx() {}
 void vtt_fx::toggle_drywet() {}
+bool vtt_fx::is_stereo() { return false; }
 tX_drywet_type vtt_fx::has_drywet_feature() { return NOT_DRYWET_CAPABLE; }
 
 /******************* builtin fx ***/
@@ -202,7 +203,6 @@ vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
                        plugin->getDescriptor()->connect_port(instance, port, &ladspa_dummy_output_port);
                }
        }
-       reconnect_buffer();
 }
 
 void vtt_fx_ladspa :: realloc_drywet() 
@@ -302,15 +302,16 @@ 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) {
+                       bool drywet=false;
                        elementFound=0;
                        
                        restore_int("ladspa_id", dummy);
                        restore_bool("panel_hidden", hidden);
-                       restore_bool_ac("has_drywet", bdummy, add_drywet());
+                       restore_bool("has_drywet", drywet);
+                       if (drywet) add_drywet();
                        
                        if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) {
                                val=0;
@@ -377,3 +378,82 @@ tX_drywet_type vtt_fx_ladspa::has_drywet_feature()
        if (sp_wet) return DRYWET_ACTIVE;
        else return DRYWET_AVAILABLE;
 }
+
+/****** STEREO plugins **********/
+
+vtt_fx_stereo_ladspa::vtt_fx_stereo_ladspa(LADSPA_Stereo_Plugin *p, void *v):vtt_fx_ladspa(p,v)
+{
+       input_port=input2_port=-1; 
+       output_port=output2_port=-1; 
+       wet_buffer2=NULL;
+       
+       for (int port=0; port < plugin->getPortCount(); port++) {
+               if (LADSPA_IS_PORT_AUDIO(cpd)) {
+                       if (LADSPA_IS_PORT_INPUT(cpd)) {
+                               if (input_port<0) { input_port=port; }
+                               else if (input2_port<0) { input2_port=port; }
+                               else { tX_error("Extra input port for plugin %s?", plugin->getName()); }
+                       } else if (LADSPA_IS_PORT_OUTPUT(cpd)) {
+                               if (output_port<0) { output_port=port; }
+                               else if (output2_port<0) { output2_port=port; }
+                               else { tX_error("Extra output port for plugin %s?", plugin->getName()); }
+                       }
+               }
+       }
+};
+
+void vtt_fx_stereo_ladspa :: reconnect_buffer()
+{
+       plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);
+       plugin->getDescriptor()->connect_port(instance, input2_port, myvtt->output_buffer2);
+
+       if (wet_buffer) {
+               plugin->getDescriptor()->connect_port(instance, output_port, wet_buffer);       
+               plugin->getDescriptor()->connect_port(instance, output2_port, wet_buffer2);
+       } else {
+               plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);     
+               plugin->getDescriptor()->connect_port(instance, output2_port, myvtt->output_buffer2);   
+       }
+}
+
+void vtt_fx_stereo_ladspa :: realloc_drywet() 
+{
+       free_drywet();
+       wet_buffer=(f_prec *) malloc(sizeof(float)*vtt_class::samples_in_mix_buffer);
+       wet_buffer2=(f_prec *) malloc(sizeof(float)*vtt_class::samples_in_mix_buffer);
+}
+
+void vtt_fx_stereo_ladspa :: free_drywet()
+{
+       if (wet_buffer) {
+               free(wet_buffer);
+               wet_buffer=NULL;
+       }
+       if (wet_buffer2) {
+               free(wet_buffer2);
+               wet_buffer2=NULL;
+       }
+}
+
+void vtt_fx_stereo_ladspa :: run()
+{
+       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];
+                       myvtt->output_buffer2[sample]=dry*myvtt->output_buffer2[sample]+wet*wet_buffer2[sample];
+               }
+       }
+}
+
+vtt_fx_stereo_ladspa :: ~vtt_fx_stereo_ladspa()
+{
+       // rest should be handeld in parent's destrucutor.
+       if (wet_buffer2) free(wet_buffer2);
+}
+
+bool vtt_fx_stereo_ladspa::is_stereo() { return true; }
index 3db5cdc826e5e36ffbc1f8da59d84271b8e11955..71eab3d5a12b53d206bc23cb2016a9d4a554c2c0 100644 (file)
@@ -68,6 +68,7 @@ class vtt_fx
        virtual int isEnabled()=NULL;
        virtual void reconnect_buffer();
        virtual void toggle_drywet();
+       virtual bool is_stereo();
        virtual tX_drywet_type has_drywet_feature();
        
        virtual const char *get_info_string()=NULL;
@@ -117,7 +118,7 @@ class vtt_fx_ladspa : public vtt_fx
 {
        public:
        list <tX_seqpar_vttfx *> controls;
-       private:
+       protected:
        tX_seqpar_vttfx *sp_enable;
        tX_seqpar_vttfx *sp_wet;
        f_prec *wet_buffer;
@@ -136,8 +137,8 @@ class vtt_fx_ladspa : public vtt_fx
        virtual int isEnabled();
        virtual void reconnect_buffer();
        virtual const char *get_info_string();
-       void realloc_drywet();
-       void free_drywet();
+       virtual void realloc_drywet();
+       virtual void free_drywet();
        virtual void toggle_drywet();
        void add_drywet();
        void remove_drywet();
@@ -150,4 +151,20 @@ class vtt_fx_ladspa : public vtt_fx
        virtual void load(xmlDocPtr, xmlNodePtr);
 };
 
+class vtt_fx_stereo_ladspa : public vtt_fx_ladspa {
+       private:
+       f_prec *wet_buffer2;
+       int input2_port, output2_port;
+       
+       protected:
+       virtual void reconnect_buffer();        
+       virtual void realloc_drywet();
+       virtual void free_drywet();
+
+       public:
+       vtt_fx_stereo_ladspa(LADSPA_Stereo_Plugin *, void *);
+       virtual bool is_stereo();
+       virtual void run();
+       virtual ~vtt_fx_stereo_ladspa();
+};
 #endif
index b0a0eab40986fd482d1836db3a7006f1de9e1c0c..b506115dfcba186dec959b7f4fb26a9ea0b20c7b 100644 (file)
@@ -653,6 +653,20 @@ void fx_button_pressed(GtkWidget *wid, vtt_class *vtt)
        g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
 }
 
+void stereo_fx_button_pressed(GtkWidget *wid, vtt_class *vtt)
+{
+       vtt_gui *g=&vtt->gui;
+
+       LADSPA_Class::set_current_vtt(vtt);
+
+       if (g->ladspa_menu) gtk_object_destroy(GTK_OBJECT(g->ladspa_menu));
+       g->ladspa_menu=LADSPA_Class::get_stereo_ladspa_menu();
+       gtk_menu_popup (GTK_MENU(g->ladspa_menu), NULL, NULL, NULL, NULL, 0, 0);
+
+       /* gtk+ is really waiting for this.. */
+       g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
+}
+
 void gui_set_name(vtt_class *vtt, char *newname)
 {
        char bold_name[128];
@@ -703,6 +717,7 @@ void gui_connect_signals(vtt_class *vtt)
        connect_button(adjust_button, vg_adjust_pitch_vtt);
        connect_adj(cycles, client_setup_number);
        connect_press_button(fx_button, fx_button_pressed);
+       connect_press_button(stereo_fx_button, stereo_fx_button_pressed);
        
        connect_button(lp_enable, lp_enabled);
        connect_adj(lp_gain, lp_gain_changed);
@@ -926,18 +941,22 @@ void build_vtt_gui(vtt_class *vtt)
        g_signal_connect(G_OBJECT(dummy), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_sync_cycles);      
 
        gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
-
+       
+       g->fx_box=gtk_vbox_new(FALSE,0);
+       gtk_box_pack_start(GTK_BOX(g->control_subbox), g->fx_box, WID_FIX);
+       gtk_widget_show(g->fx_box);
+       
        dummy=gtk_button_new_with_label("FX");
        gtk_container_foreach(GTK_CONTAINER(dummy), (GtkCallback) tX_panel_make_label_bold, NULL);
        gtk_widget_show(dummy);
        g->fx_button=dummy;
        gui_set_tooltip(g->fx_button, "Click here to load a LADSPA plugin. You will get a menu from which you can choose which plugin to load.");
-       gtk_box_pack_start(GTK_BOX(g->control_subbox), dummy, WID_FIX);
+       gtk_box_pack_start(GTK_BOX(g->fx_box), dummy, WID_FIX);
        
        /* 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);
+       p=new tX_panel("Lowpass", g->fx_box);
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "pressed", G_CALLBACK(vg_show_fx_menu), vtt->lp_fx);
        g->lp_panel=p;
                
        g->lp_enable=gtk_check_button_new_with_label("Enable");
@@ -964,12 +983,12 @@ void build_vtt_gui(vtt_class *vtt)
        p->add_client_widget(g->lp_resod->get_widget());
        gui_set_tooltip(g->lp_resod->get_entry(), "Adjust the resonance of the lowpass filter. This value determines how much the signal at the cutoff frequency will be amplified.");
 
-       gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
+       gtk_box_pack_start(GTK_BOX(g->fx_box), p->get_widget(), WID_FIX);
 
        /* 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);
+       p=new tX_panel("Echo", g->fx_box);
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "pressed",  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));
@@ -1001,8 +1020,19 @@ void build_vtt_gui(vtt_class *vtt)
        p->add_client_widget(g->ec_pand->get_widget());
        gui_set_tooltip(g->ec_pand->get_entry(), "Adjust the panning of the echo effect.");
 
-       gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
+       gtk_box_pack_start(GTK_BOX(g->fx_box), p->get_widget(), WID_FIX);
        
+       g->stereo_fx_box=gtk_vbox_new(FALSE, 0);
+       gtk_box_pack_start(GTK_BOX(g->control_subbox), g->stereo_fx_box, WID_FIX);
+       gtk_widget_show(g->stereo_fx_box);
+       
+       dummy=gtk_button_new_with_label("Stereo FX");
+       gtk_container_foreach(GTK_CONTAINER(dummy), (GtkCallback) tX_panel_make_label_bold, NULL);
+       gtk_widget_show(dummy);
+       g->stereo_fx_button=dummy;
+       gui_set_tooltip(g->stereo_fx_button, "Click here to load a stereo LADSPA plugin. You will get a menu from which you can choose which plugin to load.");
+       gtk_box_pack_start(GTK_BOX(g->stereo_fx_box), dummy, WID_FIX);
+
        /* Output */
        
        tempbox=gtk_hbox_new(FALSE,2);
@@ -1139,7 +1169,6 @@ GtkWidget *vg_create_fx_bar(vtt_class *vtt, vtt_fx *effect, int showdel)
        return box;
 }
 
-
 int gtk_box_get_widget_pos(GtkBox *box, GtkWidget *child)
 {
        int i=0;
@@ -1157,16 +1186,18 @@ int gtk_box_get_widget_pos(GtkBox *box, GtkWidget *child)
        return i;
 }
 
-void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt)
+void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt, bool stereo)
 {
-       int pos=gtk_box_get_widget_pos(GTK_BOX(vtt->gui.control_subbox), wid);
-       gtk_box_reorder_child(GTK_BOX(vtt->gui.control_subbox), wid, pos-1);
+       GtkWidget *box=(stereo ? vtt->gui.stereo_fx_box : vtt->gui.fx_box);
+       int pos=gtk_box_get_widget_pos(GTK_BOX(box), wid);
+       gtk_box_reorder_child(GTK_BOX(box), wid, pos-1);
 }
 
-void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt)
+void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt, bool stereo)
 {
-       int pos=gtk_box_get_widget_pos(GTK_BOX(vtt->gui.control_subbox), wid);
-       gtk_box_reorder_child(GTK_BOX(vtt->gui.control_subbox), wid, pos+1);
+       GtkWidget *box=(stereo ? vtt->gui.stereo_fx_box : vtt->gui.fx_box);
+       int pos=gtk_box_get_widget_pos(GTK_BOX(box), wid);
+       gtk_box_reorder_child(GTK_BOX(box), wid, pos+1);
 }
 
 void vg_show_fx_info(GtkWidget *wid, vtt_fx *effect)
@@ -1182,7 +1213,7 @@ void vg_toggle_drywet(GtkWidget *wid, vtt_fx *effect)
 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");
+       GtkWidget *item=gtk_menu_item_new_with_label("View Plugin Details");
        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);
@@ -1201,10 +1232,30 @@ void vg_show_fx_menu(GtkWidget *wid, vtt_fx *effect)
                        break;
        }
        
-       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_toggle_drywet), effect);
+       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);
        
+       item = gtk_menu_item_new();
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+       gtk_widget_set_sensitive(item, FALSE);
+       gtk_widget_show(item);
+
+       item=gtk_menu_item_new_with_label("Up");
+       gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+       gtk_widget_show(item);
+       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(fx_up), effect);
+
+       item=gtk_menu_item_new_with_label("Down");
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        gtk_widget_show(item);
+       g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(fx_down), effect);
+
+       item=gtk_menu_item_new_with_label("Delete");
+       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(fx_kill), effect);
 
        gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
 
@@ -1222,8 +1273,7 @@ void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plug
        list <tX_seqpar_vttfx *> :: iterator sp;
        
        strcpy(buffer, plugin->getLabel());
-       if (strlen(buffer) > 6)
-       {
+       if (strlen(buffer) > 6) {
                buffer[5]='.';
                buffer[6]='.';
                buffer[7]='.';
@@ -1234,17 +1284,16 @@ void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plug
        
        p->add_client_widget(vg_create_fx_bar(vtt, effect, 1));
        
-       for (sp = effect->controls.begin(); sp != effect->controls.end(); sp++)
-       {
+       for (sp = effect->controls.begin(); sp != effect->controls.end(); sp++) {
                        p->add_client_widget((*sp)->get_widget());
        }
 
-       g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_menu, (void *) effect);
+       g_signal_connect(G_OBJECT(p->get_labelbutton()), "pressed", (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);
 
-       gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
+       gtk_box_pack_start(GTK_BOX((effect->is_stereo() ? g->stereo_fx_box : g->fx_box)), p->get_widget(), WID_FIX);
 }
 
 void gui_set_filename (vtt_class *vtt, char *newname)
index ad1dc1735729f24b18788ff4a56680ec4ad4f769..41112f7fe939efded353a941b57e79043b5a4653 100644 (file)
@@ -43,6 +43,8 @@ typedef struct vtt_gui
        GtkWidget *control_minimize;
        GtkWidget *scrolled_win;
        GtkWidget *control_subbox;
+       GtkWidget *fx_box;
+       GtkWidget *stereo_fx_box;
        GtkWidget *ladspa_menu;
        GtkWidget *par_menu;
 
@@ -53,6 +55,7 @@ typedef struct vtt_gui
        GtkWidget *del;
        GtkWidget *adjust_button;
        GtkWidget *fx_button;
+       GtkWidget *stereo_fx_button;
        
        /* Trigger */
        tX_panel  *trigger_panel;