| @@ -292,6 +292,12 @@ LADSPAInfo::GetMenuList(void) | |||
| return m_SSMMenuList; | |||
| } | |||
| const vector<LADSPAInfo::PluginInfo> | |||
| 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; | |||
| @@ -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<PluginEntry> GetMenuList(void); | |||
| const std::vector<PluginInfo> 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 | |||
| { | |||
| @@ -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 ( mod ) | |||
| { | |||
| if ( !strcmp( mod->name(), "JACK" ) ) | |||
| { | |||
| 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; | |||
| } | |||
| DMESSAGE( "Special casing JACK module" ); | |||
| JACK_Module *jm = (JACK_Module*)mod; | |||
| jm->chain( chain() ); | |||
| jm->configure_inputs( ninputs() ); | |||
| jm->configure_outputs( ninputs() ); | |||
| } | |||
| redraw(); | |||
| if ( ! chain()->insert( this, mod ) ) | |||
| { | |||
| 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 ); | |||
| @@ -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 <FL/Fl.H> | |||
| #include <FL/Fl_Browser.H> | |||
| #include <FL/Fl_Input.H> | |||
| #include <FL/Fl_Scalepack.H> | |||
| #include "Plugin_Chooser_UI.H" | |||
| #include "Plugin_Module.H" | |||
| #include "Plugin_Chooser.H" | |||
| #include "stdio.h" | |||
| #include <FL/Fl_Box.H> | |||
| #include <FL/fl_draw.H> | |||
| #include <algorithm> | |||
| static std::vector <Plugin_Module::Plugin_Info*> _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<Plugin_Module::Plugin_Info>::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<Plugin_Module::Plugin_Info>::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<Plugin_Module::Plugin_Info>::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(); | |||
| } | |||
| @@ -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 <FL/Fl_Double_Window.H> | |||
| #include "Plugin_Module.H" | |||
| #include <vector> | |||
| class Plugin_Chooser_UI; | |||
| class Plugin_Chooser : public Fl_Double_Window | |||
| { | |||
| Plugin_Chooser_UI *ui; | |||
| std::list <Plugin_Module::Plugin_Info> _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 ); | |||
| }; | |||
| @@ -0,0 +1,64 @@ | |||
| # data file for the Fltk User Interface Designer (fluid) | |||
| version 1.0300 | |||
| header_name {.h} | |||
| code_name {.cxx} | |||
| decl {\#include <FL/Fl_Scalepack.H>} {public global | |||
| } | |||
| decl {\#include <FL/Fl_Table_Row.H>} {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} | |||
| } | |||
| } | |||
| } | |||
| @@ -45,6 +45,8 @@ | |||
| #include <dsp.h> | |||
| #include <algorithm> | |||
| 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::Plugin_Info> | |||
| Plugin_Module::get_all_plugins ( void ) | |||
| { | |||
| if ( !ladspainfo ) | |||
| @@ -330,19 +274,30 @@ Plugin_Module::get_all_plugins ( void ) | |||
| plugin_discover_thread->join(); | |||
| } | |||
| std::vector<LADSPAInfo::PluginEntry> plugins = ladspainfo->GetMenuList(); | |||
| std::vector<LADSPAInfo::PluginInfo> plugins = ladspainfo->GetPluginInfo(); | |||
| Plugin_Info* pi = new Plugin_Info[plugins.size() + 1]; | |||
| std::list<Plugin_Module::Plugin_Info> pr; | |||
| int j = 0; | |||
| for (std::vector<LADSPAInfo::PluginEntry>::iterator i=plugins.begin(); | |||
| for (std::vector<LADSPAInfo::PluginInfo>::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 | |||
| @@ -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<Plugin_Info> 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; } | |||
| @@ -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 | |||