Non reinvents the DAW. Powerful enough to form a complete studio, fast and light enough to run on low-end hardware like the eeePC or Raspberry Pi, and so reliable that it can be used live https://non.tuxfamily.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

443 lines
12KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2013 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. #include <FL/Fl.H>
  19. #include <FL/Fl_Browser.H>
  20. #include <FL/Fl_Input.H>
  21. #include <FL/Fl_Scalepack.H>
  22. #include "Plugin_Chooser_UI.H"
  23. #include "Plugin_Module.H"
  24. #include "Plugin_Chooser.H"
  25. #include "stdio.h"
  26. #include <FL/Fl_Box.H>
  27. #include <FL/fl_draw.H>
  28. #include <algorithm>
  29. static std::vector <Plugin_Module::Plugin_Info*> _plugin_rows;
  30. unsigned long
  31. Plugin_Chooser::plugin_chooser ( int ninputs )
  32. {
  33. Plugin_Chooser *o = new Plugin_Chooser( 0,0,735,500,"Plugin Chooser");
  34. o->ui->inputs_input->value( ninputs );
  35. o->search( "", "", "Any", ninputs, 0, o->ui->favorites_button->value() );
  36. o->show();
  37. while ( o->shown() )
  38. Fl::wait();
  39. unsigned long picked = o->value();
  40. delete o;
  41. return picked;
  42. }
  43. void
  44. Plugin_Chooser::search ( const char *name, const char *author, const char *category, int ninputs, int noutputs, bool favorites )
  45. {
  46. _plugin_rows.clear();
  47. for ( std::list<Plugin_Module::Plugin_Info>::iterator i = _plugins.begin(); i != _plugins.end(); i++ )
  48. {
  49. Plugin_Module::Plugin_Info *p = &(*i);
  50. if ( strcasestr( p->name.c_str(), name ) &&
  51. strcasestr( p->author.c_str(), author ) )
  52. {
  53. if ( !
  54. ((( ( ninputs == 0 || ninputs == p->audio_inputs || ( ninputs == 1 && p->audio_inputs == 2 ) ) ) &&
  55. ( noutputs == 0 || noutputs == p->audio_outputs )) ||
  56. ( p->audio_inputs == 1 && p->audio_outputs == 1 ) ) )
  57. continue;
  58. if ( p->audio_outputs == 0 || p->audio_inputs == 0 )
  59. /* we don't support these */
  60. continue;
  61. if ( favorites > 0 && ! p->favorite )
  62. continue;
  63. if ( strcmp( category, "Any" ) )
  64. {
  65. if ( !p->category.c_str() && strcmp( category, "Unclassified" ))
  66. continue;
  67. if (strncmp( p->category.c_str(), category, strlen( category )))
  68. continue;
  69. }
  70. _plugin_rows.push_back( p );
  71. }
  72. }
  73. ui->table->rows( _plugin_rows.size() );
  74. }
  75. void
  76. Plugin_Chooser::cb_handle ( Fl_Widget *w, void *v )
  77. {
  78. ((Plugin_Chooser*)v)->cb_handle( w );
  79. }
  80. void
  81. Plugin_Chooser::cb_handle ( Fl_Widget *w )
  82. {
  83. if ( w == ui->all_button )
  84. {
  85. ui->favorites_button->value( !ui->all_button->value() );
  86. }
  87. {
  88. char picked[512];
  89. ui->category_choice->item_pathname( picked, sizeof( picked ) );
  90. search( ui->name_input->value(),
  91. ui->author_input->value(),
  92. picked[0] == '/' ? &picked[1] : picked,
  93. ui->inputs_input->value(),
  94. ui->outputs_input->value(),
  95. ui->favorites_button->value() );
  96. }
  97. }
  98. class Plugin_Table : public Fl_Table_Row
  99. {
  100. protected:
  101. void draw_cell(TableContext context, // table cell drawing
  102. int R=0, int C=0, int X=0, int Y=0, int W=0, int H=0);
  103. public:
  104. Plugin_Table(int x, int y, int w, int h, const char *l=0) : Fl_Table_Row(x,y,w,h,l)
  105. {
  106. end();
  107. }
  108. ~Plugin_Table() { }
  109. };
  110. void Plugin_Table::draw_cell(TableContext context,
  111. int R, int C, int X, int Y, int W, int H)
  112. {
  113. const char *headings[] = { "Fav.", "Name", "Author", "Type", "In", "Out" };
  114. static char s[40];
  115. switch ( context )
  116. {
  117. case CONTEXT_STARTPAGE:
  118. fl_font(FL_HELVETICA, 12);
  119. return;
  120. case CONTEXT_COL_HEADER:
  121. fl_push_clip(X, Y, W, H);
  122. {
  123. fl_draw_box(FL_THIN_UP_BOX, X, Y, W, H, col_header_color());
  124. fl_color(FL_FOREGROUND_COLOR);
  125. fl_draw(headings[C], X, Y, W, H, FL_ALIGN_CENTER);
  126. }
  127. fl_pop_clip();
  128. return;
  129. case CONTEXT_ROW_HEADER:
  130. return;
  131. case CONTEXT_CELL:
  132. {
  133. fl_font(FL_HELVETICA, 12);
  134. const char *s2 = (char*)s;
  135. Fl_Align a = FL_ALIGN_CENTER;
  136. int symbol = 0;
  137. Fl_Color c = FL_FOREGROUND_COLOR;
  138. switch ( C )
  139. {
  140. case 0:
  141. sprintf( s, "%s", "@circle" );
  142. c = _plugin_rows[R]->favorite ? FL_LIGHT2 : FL_BLACK;
  143. symbol = 1;
  144. fl_font(FL_HELVETICA, 9 );
  145. break;
  146. case 1:
  147. a = FL_ALIGN_LEFT;
  148. s2 = _plugin_rows[R]->name.c_str();
  149. break;
  150. case 2:
  151. a = FL_ALIGN_LEFT;
  152. s2 = _plugin_rows[R]->author.c_str();
  153. break;
  154. case 3:
  155. s2 = _plugin_rows[R]->type;
  156. break;
  157. case 4:
  158. sprintf( s, "%i", _plugin_rows[R]->audio_inputs );
  159. break;
  160. case 5:
  161. sprintf( s, "%i", _plugin_rows[R]->audio_outputs );
  162. break;
  163. }
  164. fl_color( row_selected(R) ? selection_color() : FL_DARK1);
  165. fl_rectf(X, Y, W, H);
  166. fl_color(color());
  167. fl_rect(X, Y, W, H);
  168. X+=4;
  169. W-=8;
  170. Y+=4;
  171. H-=8;
  172. fl_push_clip(X, Y, W, H);
  173. fl_color(c);
  174. fl_draw(s2, X, Y, W, H, a, 0, symbol );
  175. fl_pop_clip();
  176. return;
  177. }
  178. case CONTEXT_TABLE:
  179. fprintf(stderr, "TABLE CONTEXT CALLED\n");
  180. return;
  181. case CONTEXT_ENDPAGE:
  182. case CONTEXT_RC_RESIZE:
  183. case CONTEXT_NONE:
  184. return;
  185. }
  186. }
  187. void
  188. Plugin_Chooser::cb_table ( Fl_Widget *w, void *v )
  189. {
  190. ((Plugin_Chooser*)v)->cb_table(w);
  191. }
  192. void
  193. Plugin_Chooser::cb_table ( Fl_Widget *w )
  194. {
  195. Fl_Table_Row *o = (Fl_Table_Row*)w;
  196. int R = o->callback_row();
  197. int C = o->callback_col();
  198. Fl_Table::TableContext context = o->callback_context();
  199. if ( context == Fl_Table::CONTEXT_CELL )
  200. {
  201. if ( C == 0 )
  202. {
  203. _plugin_rows[R]->favorite = ! _plugin_rows[R]->favorite;
  204. o->redraw();
  205. }
  206. else
  207. {
  208. _value = _plugin_rows[R]->id;
  209. hide();
  210. }
  211. }
  212. }
  213. extern char *user_config_dir;
  214. static FILE *open_favorites( const char *mode )
  215. {
  216. char *path;
  217. asprintf( &path, "%s/%s", user_config_dir, "favorite_plugins" );
  218. FILE *fp = fopen( path, mode );
  219. free( path );
  220. return fp;
  221. }
  222. int
  223. Plugin_Chooser::load_favorites ( void )
  224. {
  225. FILE *fp = open_favorites( "r" );
  226. if ( !fp )
  227. {
  228. return 0;
  229. }
  230. unsigned long id;
  231. char *type;
  232. int favorites = 0;
  233. while ( 2 == fscanf( fp, "%m[^:]:%lu\n", &type, &id ) )
  234. {
  235. for ( std::list<Plugin_Module::Plugin_Info>::iterator i = _plugins.begin();
  236. i != _plugins.end();
  237. i++ )
  238. {
  239. if ( !strcmp( (*i).type, type ) &&
  240. (*i).id == id )
  241. {
  242. (*i).favorite = 1;
  243. favorites++;
  244. }
  245. }
  246. free(type);
  247. }
  248. fclose(fp);
  249. return favorites;
  250. }
  251. void
  252. Plugin_Chooser::save_favorites ( void )
  253. {
  254. FILE *fp = open_favorites( "w" );
  255. if ( !fp )
  256. return;
  257. for ( std::list<Plugin_Module::Plugin_Info>::iterator i = _plugins.begin();
  258. i != _plugins.end();
  259. i++ )
  260. {
  261. if ( (*i).favorite )
  262. {
  263. fprintf( fp, "%s:%lu\n", i->type, i->id );
  264. }
  265. }
  266. fclose( fp );
  267. }
  268. void
  269. Plugin_Chooser::load_categories ( void )
  270. {
  271. ui->category_choice->add( "Any" );
  272. std::list<std::string> categories;
  273. for ( std::list<Plugin_Module::Plugin_Info>::iterator i = _plugins.begin();
  274. i != _plugins.end();
  275. i++ )
  276. {
  277. if ( i->category.c_str() )
  278. {
  279. categories.push_back(i->category);
  280. }
  281. }
  282. categories.sort();
  283. for ( std::list<std::string>::const_iterator i = categories.begin();
  284. i != categories.end();
  285. i++ )
  286. {
  287. ui->category_choice->add( i->c_str() );
  288. }
  289. ui->category_choice->value( 0 );
  290. }
  291. Plugin_Chooser::Plugin_Chooser ( int X,int Y,int W,int H, const char *L )
  292. : Fl_Double_Window ( X,Y,W,H,L )
  293. {
  294. set_modal();
  295. _value = 0;
  296. _plugins = Plugin_Module::get_all_plugins();
  297. {
  298. Plugin_Chooser_UI *o = ui = new Plugin_Chooser_UI(X,Y,W,H);
  299. o->name_input->callback( &Plugin_Chooser::cb_handle, this );
  300. o->name_input->when( FL_WHEN_CHANGED );
  301. o->author_input->callback( &Plugin_Chooser::cb_handle, this );
  302. o->author_input->when( FL_WHEN_CHANGED );
  303. o->inputs_input->callback( &Plugin_Chooser::cb_handle, this );
  304. o->inputs_input->when( FL_WHEN_CHANGED );
  305. o->outputs_input->callback( &Plugin_Chooser::cb_handle, this );
  306. o->outputs_input->when( FL_WHEN_CHANGED );
  307. o->favorites_button->callback( &Plugin_Chooser::cb_handle, this );
  308. o->favorites_button->when( FL_WHEN_CHANGED );
  309. o->all_button->callback( &Plugin_Chooser::cb_handle, this );
  310. o->all_button->when( FL_WHEN_CHANGED );
  311. o->category_choice->callback( &Plugin_Chooser::cb_handle, this );
  312. o->category_choice->when( FL_WHEN_CHANGED );
  313. {
  314. Plugin_Table *o = new Plugin_Table(ui->table->x(),ui->table->y(),ui->table->w(),ui->table->h() );
  315. ui->table_group->add(o);
  316. ui->table_group->resizable(o);
  317. delete ui->table;
  318. ui->table = o;
  319. /* ui->scalepack->add( o ); */
  320. /* ui->scalepack->resizable( o ); */
  321. o->col_header(1);
  322. o->col_resize(1);
  323. o->row_resize(1);
  324. o->cols(6);
  325. o->col_resize_min(4);
  326. o->col_width(0,30);
  327. o->col_width(1,350 - 7);
  328. o->col_width(2,200);
  329. o->col_width(3,75);
  330. o->col_width(4,30);
  331. o->col_width(5,30);
  332. o->color(FL_BLACK);
  333. o->box(FL_NO_BOX);
  334. o->when(FL_WHEN_CHANGED);
  335. o->callback( &Plugin_Chooser::cb_table, this );
  336. }
  337. resizable(o);
  338. }
  339. size_range( 735, 300, 735, 0 );
  340. end();
  341. load_categories();
  342. if ( load_favorites() )
  343. {
  344. ui->all_button->value(0);
  345. ui->favorites_button->value(1);
  346. }
  347. }
  348. Plugin_Chooser::~Plugin_Chooser( )
  349. {
  350. save_favorites();
  351. }