From dd9eb35ab22adb39592fd698d7356d0b370895fd Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Sat, 13 Apr 2013 13:18:03 -0700 Subject: [PATCH] Implement plugin browser, with search and favorites. --- mixer/src/LADSPAInfo.C | 42 +++- mixer/src/LADSPAInfo.h | 30 ++- mixer/src/Module.C | 94 ++++---- mixer/src/Plugin_Chooser.C | 384 +++++++++++++++++++++++++++++++++ mixer/src/Plugin_Chooser.H | 57 +++++ mixer/src/Plugin_Chooser_UI.fl | 64 ++++++ mixer/src/Plugin_Module.C | 85 ++------ mixer/src/Plugin_Module.H | 26 ++- mixer/wscript | 2 + 9 files changed, 648 insertions(+), 136 deletions(-) create mode 100644 mixer/src/Plugin_Chooser.C create mode 100644 mixer/src/Plugin_Chooser.H create mode 100644 mixer/src/Plugin_Chooser_UI.fl diff --git a/mixer/src/LADSPAInfo.C b/mixer/src/LADSPAInfo.C index 4214c97..c74611d 100644 --- a/mixer/src/LADSPAInfo.C +++ b/mixer/src/LADSPAInfo.C @@ -292,6 +292,12 @@ LADSPAInfo::GetMenuList(void) return m_SSMMenuList; } +const vector +LADSPAInfo::GetPluginInfo(void) +{ + return m_Plugins; +} + unsigned long LADSPAInfo::GetPluginListEntryByID(unsigned long unique_id) { @@ -378,7 +384,7 @@ LADSPAInfo::DescendGroup(string prefix, pe.Depth = depth; pe.UniqueID = pi->UniqueID; pe.Name = prefix + name; - + plugins.push_back(pe); } plugins.sort(); @@ -599,6 +605,13 @@ LADSPAInfo::ExaminePluginLibrary(const string path, library_added = true; } + if ( ! desc->Name ) + { + printf( "WARNING: LADSPA Plugin with id %lu has no name!\n", desc->UniqueID ); + + continue; + } + // Add plugin info PluginInfo pi; pi.LibraryIndex = m_Libraries.size() - 1; @@ -607,19 +620,34 @@ LADSPAInfo::ExaminePluginLibrary(const string path, pi.Label = desc->Label; pi.Name = desc->Name; pi.Descriptor = NULL; - m_Plugins.push_back(pi); - + pi.Maker = desc->Maker; + pi.AudioInputs = 0; + pi.AudioOutputs = 0; + // Find number of input ports unsigned long in_port_count = 0; for (unsigned long p = 0; p < desc->PortCount; p++) { - if (LADSPA_IS_PORT_INPUT(desc->PortDescriptors[p])) { - in_port_count++; - } + if (LADSPA_IS_PORT_INPUT(desc->PortDescriptors[p])) { + in_port_count++; + if ( LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[p] ) ) + pi.AudioInputs++; + } } + for (unsigned long p = 0; p < desc->PortCount; p++) { + if (LADSPA_IS_PORT_OUTPUT(desc->PortDescriptors[p])) { + + if ( LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[p] ) ) + pi.AudioOutputs++; + } + } + if (in_port_count > m_MaxInputPortCount) { - m_MaxInputPortCount = in_port_count; + m_MaxInputPortCount = in_port_count; + } + m_Plugins.push_back(pi); + // Add to index m_IDLookup[desc->UniqueID] = m_Plugins.size() - 1; diff --git a/mixer/src/LADSPAInfo.h b/mixer/src/LADSPAInfo.h index e41911f..d936086 100644 --- a/mixer/src/LADSPAInfo.h +++ b/mixer/src/LADSPAInfo.h @@ -97,8 +97,27 @@ public: } }; + +// For cached plugin information + struct PluginInfo + { + unsigned long LibraryIndex; // Index of library in m_Libraries + unsigned long Index; // Plugin index in library + unsigned long UniqueID; // Unique ID + std::string Label; // Plugin label + std::string Name; // Plugin Name + std::string Maker; + unsigned int AudioInputs; + unsigned int AudioOutputs; + const LADSPA_Descriptor *Descriptor; // Descriptor, NULL + + + }; + // Get ordered list of plugin names and IDs for plugin menu const std::vector GetMenuList(void); + + const std::vector GetPluginInfo(void); // Get the index in the above list for given Unique ID // If not found, this returns the size of the above list @@ -140,17 +159,6 @@ private: void *Handle; // DLL Handle, NULL }; -// For cached plugin information - struct PluginInfo - { - unsigned long LibraryIndex; // Index of library in m_Libraries - unsigned long Index; // Plugin index in library - unsigned long UniqueID; // Unique ID - std::string Label; // Plugin label - std::string Name; // Plugin Name - const LADSPA_Descriptor *Descriptor; // Descriptor, NULL - }; - // For cached RDF uri information struct RDFURIInfo { diff --git a/mixer/src/Module.C b/mixer/src/Module.C index 1ae4b0b..8fa273d 100644 --- a/mixer/src/Module.C +++ b/mixer/src/Module.C @@ -39,6 +39,7 @@ #include "FL/menu_popup.H" #include "Mixer.H" +#include "Plugin_Chooser.H" #include "OSC/Endpoint.H" #include "string_util.h" @@ -602,61 +603,55 @@ Module::draw_label ( void ) void Module::insert_menu_cb ( const Fl_Menu_ *m ) { - if ( ! m->mvalue() || m->mvalue()->flags & FL_SUBMENU_POINTER || m->mvalue()->flags & FL_SUBMENU ) - return; - - void * v = m->mvalue()->user_data(); - - if ( v ) + unsigned long id = Plugin_Chooser::plugin_chooser( this->ninputs() ); + + Module *mod = NULL; + + switch ( id ) { - unsigned long id = *((unsigned long *)v); - - Module *mod = NULL; - - switch ( id ) + case 0: + return; + case 1: + mod = new JACK_Module(); + break; + case 2: + mod = new Gain_Module(); + break; + case 3: + mod = new Meter_Module(); + break; + case 4: + mod = new Mono_Pan_Module(); + break; + default: { - case 1: - mod = new JACK_Module(); - break; - case 2: - mod = new Gain_Module(); - break; - case 3: - mod = new Meter_Module(); - break; - case 4: - mod = new Mono_Pan_Module(); - break; - default: - { - Plugin_Module *m = new Plugin_Module(); + Plugin_Module *m = new Plugin_Module(); - m->load( id ); + m->load( id ); - mod = m; - } + mod = m; + } + } + + if ( mod ) + { + if ( !strcmp( mod->name(), "JACK" ) ) + { + DMESSAGE( "Special casing JACK module" ); + JACK_Module *jm = (JACK_Module*)mod; + jm->chain( chain() ); + jm->configure_inputs( ninputs() ); + jm->configure_outputs( ninputs() ); } - if ( mod ) + if ( ! chain()->insert( this, mod ) ) { - if ( !strcmp( mod->name(), "JACK" ) ) - { - DMESSAGE( "Special casing JACK module" ); - JACK_Module *jm = (JACK_Module*)mod; - jm->chain( chain() ); - jm->configure_inputs( ninputs() ); - jm->configure_outputs( ninputs() ); - } - - if ( ! chain()->insert( this, mod ) ) - { - fl_alert( "Cannot insert this module at this point in the chain" ); - delete mod; - return; - } - - redraw(); + fl_alert( "Cannot insert this module at this point in the chain" ); + delete mod; + return; } + + redraw(); } } @@ -733,7 +728,10 @@ Module::menu ( void ) const insert_menu->add( "Meter", 0, 0, new unsigned long(3) ); insert_menu->add( "Mono Pan", 0, 0, new unsigned long(4) ); - Plugin_Module::add_plugins_to_menu( insert_menu ); + insert_menu->add( "Plugin", 0, 0, new unsigned long(4) ); + + + /* Plugin_Module::add_plugins_to_menu( insert_menu ); */ // menu_set_callback( insert_menu, &Module::insert_menu_cb, (void*)this ); insert_menu->callback( &Module::insert_menu_cb, (void*)this ); diff --git a/mixer/src/Plugin_Chooser.C b/mixer/src/Plugin_Chooser.C new file mode 100644 index 0000000..ddecb4a --- /dev/null +++ b/mixer/src/Plugin_Chooser.C @@ -0,0 +1,384 @@ + +/*******************************************************************************/ +/* Copyright (C) 2013 Jonathan Moore Liles */ +/* */ +/* This program 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. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include +#include +#include +#include +#include "Plugin_Chooser_UI.H" +#include "Plugin_Module.H" +#include "Plugin_Chooser.H" +#include "stdio.h" +#include +#include + +#include + +static std::vector _plugin_rows; + +unsigned long +Plugin_Chooser::plugin_chooser ( int ninputs ) +{ + Plugin_Chooser *o = new Plugin_Chooser( 0,0,735,500,"Plugin Chooser"); + + o->ui->inputs_input->value( ninputs ); + + o->search( "", "", ninputs, 0, o->ui->favorites_button->value() ); + + o->show(); + + while ( o->shown() ) + Fl::wait(); + + unsigned long picked = o->value(); + + delete o; + + return picked; +} + +void +Plugin_Chooser::search ( const char *name, const char *author, int ninputs, int noutputs, bool favorites ) +{ + _plugin_rows.clear(); + + for ( std::list::iterator i = _plugins.begin(); i != _plugins.end(); i++ ) + { + Plugin_Module::Plugin_Info *p = &(*i); + + if ( strcasestr( p->name, name ) && + strcasestr( p->author, author ) ) + { + if ( ! + ((( ( ninputs == 0 || ninputs == p->audio_inputs ) ) && + ( noutputs == 0 || noutputs == p->audio_outputs )) || + ( p->audio_inputs == 1 && p->audio_outputs == 1 ) ) ) + continue; + + if ( p->audio_outputs == 0 || p->audio_inputs == 0 ) + /* we don't support these */ + continue; + + if ( favorites > 0 && ! p->favorite ) + continue; + + _plugin_rows.push_back( p ); + } + } + + ui->table->rows( _plugin_rows.size() ); +} + +void +Plugin_Chooser::cb_handle ( Fl_Widget *w, void *v ) +{ + ((Plugin_Chooser*)v)->cb_handle( w ); +} + +void +Plugin_Chooser::cb_handle ( Fl_Widget *w ) +{ + if ( w == ui->all_button ) + { + ui->favorites_button->value( !ui->all_button->value() ); + } + + { + search( ui->name_input->value(), ui->author_input->value(), ui->inputs_input->value(), ui->outputs_input->value(), ui->favorites_button->value() ); + } +} + +class Plugin_Table : public Fl_Table_Row +{ +protected: + void draw_cell(TableContext context, // table cell drawing + int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0); +public: + Plugin_Table(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l) + { + end(); + } + ~Plugin_Table() { } +}; + +void Plugin_Table::draw_cell(TableContext context, + int R, int C, int X, int Y, int W, int H) +{ + const char *headings[] = { "Fav.", "Name", "Author", "Type", "In", "Out" }; + + static char s[40]; + + switch ( context ) + { + case CONTEXT_STARTPAGE: + fl_font(FL_HELVETICA, 12); + return; + + case CONTEXT_COL_HEADER: + fl_push_clip(X, Y, W, H); + { + fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color()); + fl_color(FL_FOREGROUND_COLOR); + fl_draw(headings[C], X, Y, W, H, FL_ALIGN_CENTER); + } + fl_pop_clip(); + return; + + case CONTEXT_ROW_HEADER: + return; + + case CONTEXT_CELL: + { + const char *s2 = (char*)s; + Fl_Align a = FL_ALIGN_CENTER; + int symbol = 0; + + switch ( C ) + { + case 0: + sprintf( s, "%s", _plugin_rows[R]->favorite ? "@circle" : "" ); + symbol = 1; + break; + case 1: + a = FL_ALIGN_LEFT; + s2 = _plugin_rows[R]->name; + break; + case 2: + a = FL_ALIGN_LEFT; + s2 = _plugin_rows[R]->author; + break; + case 3: + s2 = _plugin_rows[R]->type; + break; + case 4: + sprintf( s, "%i", _plugin_rows[R]->audio_inputs ); + break; + case 5: + sprintf( s, "%i", _plugin_rows[R]->audio_outputs ); + break; + } + + fl_push_clip(X, Y, W, H); + { + // BG COLOR + fl_color( row_selected(R) ? selection_color() : FL_DARK1); + fl_rectf(X, Y, W, H); + + // TEXT + fl_color(FL_FOREGROUND_COLOR); + fl_draw(s2, X, Y, W, H, a, 0, symbol ); + + // BORDER + fl_color(color()); + fl_rect(X, Y, W, H); + } + fl_pop_clip(); + return; + } + + case CONTEXT_TABLE: + fprintf(stderr, "TABLE CONTEXT CALLED\n"); + return; + + case CONTEXT_ENDPAGE: + case CONTEXT_RC_RESIZE: + case CONTEXT_NONE: + return; + } +} + +void +Plugin_Chooser::cb_table ( Fl_Widget *w, void *v ) +{ + ((Plugin_Chooser*)v)->cb_table(w); +} + +void +Plugin_Chooser::cb_table ( Fl_Widget *w ) +{ + Fl_Table_Row *o = (Fl_Table_Row*)w; + + int R = o->callback_row(); + int C = o->callback_col(); + + Fl_Table::TableContext context = o->callback_context(); + + if ( context == Fl_Table::CONTEXT_CELL ) + { + if ( C == 0 ) + { + _plugin_rows[R]->favorite = ! _plugin_rows[R]->favorite; + o->redraw(); + } + else + { + _value = _plugin_rows[R]->id; + hide(); + } + } +} + +extern char *user_config_dir; + +static FILE *open_favorites( const char *mode ) +{ + char *path; + + asprintf( &path, "%s/%s", user_config_dir, "favorite_plugins" ); + + FILE *fp = fopen( path, mode ); + + free( path ); + + return fp; +} + +int +Plugin_Chooser::load_favorites ( void ) +{ + FILE *fp = open_favorites( "r" ); + + if ( !fp ) + { + return 0; + } + + unsigned long id; + char *type; + int favorites = 0; + + while ( 2 == fscanf( fp, "%a[^:]:%lu\n", &type, &id ) ) + { + for ( std::list::iterator i = _plugins.begin(); + i != _plugins.end(); + i++ ) + { + if ( !strcmp( (*i).type, type ) && + (*i).id == id ) + { + (*i).favorite = 1; + + favorites++; + } + } + + free(type); + } + + fclose(fp); + + return favorites; +} + +void +Plugin_Chooser::save_favorites ( void ) +{ + FILE *fp = open_favorites( "w" ); + + if ( !fp ) + return; + + for ( std::list::iterator i = _plugins.begin(); + i != _plugins.end(); + i++ ) + { + if ( (*i).favorite ) + { + fprintf( fp, "%s:%lu\n", i->type, i->id ); + } + } + + fclose( fp ); +} + +Plugin_Chooser::Plugin_Chooser ( int X,int Y,int W,int H, const char *L ) + : Fl_Double_Window ( X,Y,W,H,L ) +{ + set_modal(); + _value = 0; + + _plugins = Plugin_Module::get_all_plugins(); + + + { + Plugin_Chooser_UI *o = ui = new Plugin_Chooser_UI(X,Y,W,H); + + o->name_input->callback( &Plugin_Chooser::cb_handle, this ); + o->name_input->when( FL_WHEN_CHANGED ); + + + o->author_input->callback( &Plugin_Chooser::cb_handle, this ); + o->author_input->when( FL_WHEN_CHANGED ); + + + o->inputs_input->callback( &Plugin_Chooser::cb_handle, this ); + o->inputs_input->when( FL_WHEN_CHANGED ); + + o->outputs_input->callback( &Plugin_Chooser::cb_handle, this ); + o->outputs_input->when( FL_WHEN_CHANGED ); + + o->favorites_button->callback( &Plugin_Chooser::cb_handle, this ); + o->favorites_button->when( FL_WHEN_CHANGED ); + + o->all_button->callback( &Plugin_Chooser::cb_handle, this ); + o->all_button->when( FL_WHEN_CHANGED ); + + { + Plugin_Table *o = new Plugin_Table(ui->table->x(),ui->table->y(),ui->table->w(),ui->table->h() ); + ui->table_group->add(o); + ui->table_group->resizable(o); + delete ui->table; + ui->table = o; + /* ui->scalepack->add( o ); */ + /* ui->scalepack->resizable( o ); */ + o->col_header(1); + o->col_resize(1); + o->row_resize(1); + o->cols(6); + o->col_resize_min(4); + o->col_width(0,30); + o->col_width(1,350 - 7); + o->col_width(2,200); + o->col_width(3,75); + o->col_width(4,30); + o->col_width(5,30); + o->color(FL_BLACK); + o->box(FL_NO_BOX); + o->when(FL_WHEN_CHANGED); + o->callback( &Plugin_Chooser::cb_table, this ); + + } + + resizable(o); + } + size_range( 735, 300, 735, 0 ); + + end(); + + if ( load_favorites() ) + { + ui->all_button->value(0); + ui->favorites_button->value(1); + } +} + +Plugin_Chooser::~Plugin_Chooser( ) +{ + save_favorites(); +} diff --git a/mixer/src/Plugin_Chooser.H b/mixer/src/Plugin_Chooser.H new file mode 100644 index 0000000..86249ff --- /dev/null +++ b/mixer/src/Plugin_Chooser.H @@ -0,0 +1,57 @@ + +/*******************************************************************************/ +/* Copyright (C) 2013 Jonathan Moore Liles */ +/* */ +/* This program 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. */ +/* */ +/* This program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#pragma once + +#include +#include "Plugin_Module.H" +#include + +class Plugin_Chooser_UI; +class Plugin_Chooser : public Fl_Double_Window +{ + Plugin_Chooser_UI *ui; + + std::list _plugins; + + static void cb_handle ( Fl_Widget *w, void *v ); + void cb_handle ( Fl_Widget *w ); + static void cb_table ( Fl_Widget *w, void *v ); + void cb_table ( Fl_Widget *w ); + + void search ( const char *name, const char *author, int ninputs, int noutputs, bool favorites ); + + unsigned long _value; + + int load_favorites ( void ); + + void save_favorites ( void ); + +public: + + unsigned long value ( void ) const { return _value; } + + Plugin_Chooser ( int X,int Y,int W,int H, const char *L=0 ); + + virtual ~Plugin_Chooser( ); + + static unsigned long plugin_chooser ( int ninputs ); +}; + + diff --git a/mixer/src/Plugin_Chooser_UI.fl b/mixer/src/Plugin_Chooser_UI.fl new file mode 100644 index 0000000..a17323a --- /dev/null +++ b/mixer/src/Plugin_Chooser_UI.fl @@ -0,0 +1,64 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0300 +header_name {.h} +code_name {.cxx} +decl {\#include } {public global +} + +decl {\#include } {public global +} + +widget_class Plugin_Chooser_UI { + label {Plugin Selector} open selected + xywh {821 343 735 500} type Double resizable size_range {740 0 740 0} visible +} { + Fl_Group {} {open + xywh {10 5 155 20} + } { + Fl_Round_Button all_button { + label All + xywh {10 5 50 20} type Radio down_box ROUND_DOWN_BOX value 1 + } + Fl_Round_Button favorites_button { + label Favorites + xywh {65 5 100 20} type Radio down_box ROUND_DOWN_BOX + } + } + Fl_Group {} {open + xywh {5 29 725 77} box UP_FRAME + code0 {o->resizable(0);} + } { + Fl_Input name_input { + label {Name:} + xywh {65 38 555 24} labelsize 12 textsize 13 + } + Fl_Input author_input { + label {Author:} + xywh {65 72 415 24} labelsize 12 textsize 13 + } + Fl_Value_Input outputs_input { + label {Outputs:} + xywh {693 70 30 26} labelsize 12 + } + Fl_Value_Input inputs_input { + label {Inputs:} + xywh {693 39 30 24} labelsize 12 + } + } + Fl_Group table_group {open + xywh {5 115 725 380} resizable + } { + Fl_Table table {open + xywh {5 115 725 380} resizable + } {} + } + Fl_Choice type_choice { + label {Type:} open + xywh {520 135 100 28} down_box BORDER_BOX labelsize 12 hide + } { + MenuItem {} { + label LADSPA + xywh {0 -68 34 18} + } + } +} diff --git a/mixer/src/Plugin_Module.C b/mixer/src/Plugin_Module.C index 950bd0d..ae49c32 100644 --- a/mixer/src/Plugin_Module.C +++ b/mixer/src/Plugin_Module.C @@ -45,6 +45,8 @@ #include +#include + static LADSPAInfo *ladspainfo; @@ -119,64 +121,6 @@ Plugin_Module::set ( Log_Entry &e ) -void -Plugin_Module::add_plugins_to_menu ( Fl_Menu_Button *menu ) -{ - Plugin_Module::Plugin_Info *pia = Plugin_Module::get_all_plugins(); - - char path[1024]; - for ( Plugin_Module::Plugin_Info *pi = pia; pi->path; ++pi ) - { - snprintf( path, sizeof( path ), "Plugin/%s", pi->path ); - - menu->add(path, 0, NULL, new unsigned long( pi->id ), 0 ); - } - - delete[] pia; -} - -/* allow the user to pick a plugin */ -Plugin_Module * -Plugin_Module::pick_plugin ( void ) -{ - /**************/ - /* build menu */ - /**************/ - - Fl_Menu_Button *menu = new Fl_Menu_Button( 0, 0, 400, 400 ); - menu->type( Fl_Menu_Button::POPUP3 ); - - Plugin_Module::Plugin_Info *pia = Plugin_Module::get_all_plugins(); - - for ( Plugin_Module::Plugin_Info *pi = pia; pi->path; ++pi ) - { - menu->add(pi->path, 0, NULL, pi, 0 ); - } - - menu->popup(); - - if ( menu->value() <= 0 ) - return NULL; - - /************************/ - /* load selected plugin */ - /************************/ - - Plugin_Module::Plugin_Info *pi = (Plugin_Module::Plugin_Info*)menu->menu()[ menu->value() ].user_data(); - - if ( ! pi ) - return NULL; - - Plugin_Module *m = new Plugin_Module(); - - m->load( pi->id ); - - delete[] pia; - - return m; -} - - void Plugin_Module::init ( void ) { @@ -319,7 +263,7 @@ Plugin_Module::join_discover_thread ( void ) } /* return a list of available plugins */ -Plugin_Module::Plugin_Info * +std::list Plugin_Module::get_all_plugins ( void ) { if ( !ladspainfo ) @@ -330,19 +274,30 @@ Plugin_Module::get_all_plugins ( void ) plugin_discover_thread->join(); } - std::vector plugins = ladspainfo->GetMenuList(); + std::vector plugins = ladspainfo->GetPluginInfo(); - Plugin_Info* pi = new Plugin_Info[plugins.size() + 1]; + std::list pr; int j = 0; - for (std::vector::iterator i=plugins.begin(); + for (std::vector::iterator i=plugins.begin(); i!=plugins.end(); i++, j++) { - pi[j].path = i->Name.c_str(); - pi[j].id = i->UniqueID; + Plugin_Info pi; + + // pi[j].path = i->Name.c_str(); + pi.path = NULL; + pi.id = i->UniqueID; + pi.author = i->Maker.c_str(); + pi.name = i->Name.c_str(); + pi.audio_inputs = i->AudioInputs; + pi.audio_outputs = i->AudioOutputs; + + pr.push_back( pi ); } - return pi; + pr.sort(); + + return pr; } bool diff --git a/mixer/src/Plugin_Module.H b/mixer/src/Plugin_Module.H index 1835dc9..f709207 100644 --- a/mixer/src/Plugin_Module.H +++ b/mixer/src/Plugin_Module.H @@ -35,12 +35,30 @@ public: { const char *path; unsigned long id; + const char *name; + const char *author; + const char *category; + int audio_inputs; + int audio_outputs; + const char *type; + bool favorite; Plugin_Info ( ) { path = 0; id = 0; + name = 0; + author = 0; + category = 0; + audio_inputs = 0; + audio_outputs = 0; + type = "LADSPA"; + favorite = 0; } + + bool operator< ( const Plugin_Info &rhs ) { + return strcmp( name, rhs.name ) < 1; + } }; bool load ( unsigned long id ); @@ -71,8 +89,7 @@ private: bool _crosswire; static void *discover_thread ( void * ); - static Plugin_Info* get_all_plugins ( void ); - + void set_input_buffer ( int n, void *buf ); void set_output_buffer ( int n, void *buf ); @@ -89,15 +106,14 @@ private: public: + static std::list get_all_plugins ( void ); + static void spawn_discover_thread ( void ); static void join_discover_thread ( void ); Plugin_Module ( ); virtual ~Plugin_Module(); - static Plugin_Module * pick_plugin ( void ); - static void add_plugins_to_menu ( Fl_Menu_Button *menu ); - int plugin_ins ( void ) const { return _plugin_ins; } int plugin_outs ( void ) const { return _plugin_outs; } diff --git a/mixer/wscript b/mixer/wscript index 3e78418..5e6a3b6 100644 --- a/mixer/wscript +++ b/mixer/wscript @@ -57,6 +57,8 @@ src/Mixer_Strip.C src/Module.C src/Module_Parameter_Editor.C src/Mono_Pan_Module.C +src/Plugin_Chooser_UI.fl +src/Plugin_Chooser.C src/NSM.C src/Panner.C src/Plugin_Module.C