Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
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.

1681 lines
42KB

  1. # data file for the Fltk User Interface Designer (fluid)
  2. version 1.0107
  3. header_name {.H}
  4. code_name {.C}
  5. comment {//
  6. // Copyright (C) 2008 Jonathan Moore Liles
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with this program; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. //
  22. } {in_source in_header
  23. }
  24. decl {\#include <Fl/Fl_Dial.H>} {public
  25. }
  26. decl {\#include <Fl/Fl_Help_Dialog.H>} {}
  27. decl {\#include "widgets.H"} {}
  28. decl {\#include "event_edit.H"} {}
  29. decl {\#include "../jack.H"} {}
  30. decl {\#include "../lash.H"} {}
  31. decl {extern UI *ui;} {}
  32. decl {class O_Canvas;} {}
  33. decl {class Triggers;} {public
  34. }
  35. decl {Fl_Color canvas_background_color;} {public
  36. }
  37. decl {extern Fl_Color velocity_colors[];} {}
  38. Function {update_transport( void * )} {open return_type void
  39. } {
  40. code {// transport_poll();
  41. handle_midi_input();
  42. lash.process();
  43. ui->progress_group->do_callback();
  44. ui->vmetro_widget->update();
  45. if ( transport.rolling )
  46. ui->triggers_widget->update();
  47. Fl::repeat_timeout( TRANSPORT_POLL_INTERVAL, update_transport );
  48. static int oldstate = -1;
  49. if ( transport.rolling != oldstate )
  50. {
  51. ui->play_button->label( transport.rolling ? "@square" : "@>" );
  52. oldstate = transport.rolling;
  53. }
  54. // JUST A TEST
  55. if ( transport.rolling )
  56. {
  57. if ( ui->tabs->value() == ui->pattern_tab )
  58. ui->pattern_canvas_widget->draw_playhead();
  59. else
  60. if ( ui->tabs->value() == ui->phrase_tab )
  61. ui->phrase_canvas_widget->draw_playhead();
  62. }} {}
  63. }
  64. class UI {open
  65. } {
  66. decl {Fl_Text_Buffer *sequence_notes_buffer;} {}
  67. decl {Fl_Text_Buffer *pattern_notes_buffer;} {}
  68. decl {Fl_Text_Buffer *phrase_notes_buffer} {}
  69. Function {UI()} {open
  70. } {
  71. code {// Make her pretty
  72. Fl::background( 32, 32, 32 );
  73. Fl::background2( 36, 36, 36 );
  74. Fl::foreground( 255, 255, 255 );
  75. Fl::scheme( "plastic" );
  76. canvas_background_color = FL_GREEN;
  77. main_window = make_main_window();
  78. seq_window = make_seq_window();
  79. make_randomization_dialog();
  80. Fl::add_handler( shortcut_handler );
  81. // use old focus behavior
  82. Fl::visible_focus( 0 );
  83. main_window->show();
  84. Fl::add_timeout( TRANSPORT_POLL_INTERVAL, update_transport );
  85. playlist->signal_new_song.connect( sigc::mem_fun( this, &UI::update_sequence_widgets ) );} {}
  86. }
  87. Function {~UI()} {open
  88. } {
  89. code {delete seq_window;
  90. delete main_window;} {}
  91. }
  92. Function {run()} {open
  93. } {
  94. code {Fl::run();} {}
  95. }
  96. Function {make_main_window()} {open
  97. } {
  98. Fl_Window main_window {
  99. label {Non Sequencer}
  100. callback {// Ignore escape
  101. if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape )
  102. return;
  103. if ( maybe_save_song() )
  104. quit();} open
  105. xywh {790 38 869 801} type Single box PLASTIC_UP_BOX color 37 resizable xclass non size_range {869 801 0 0} visible
  106. } {
  107. Fl_Menu_Bar {} {open
  108. xywh {0 0 869 30} color 37
  109. } {
  110. Submenu {} {
  111. label {&File} open
  112. xywh {0 0 100 20} color 37
  113. } {
  114. MenuItem {} {
  115. label {&New}
  116. callback {if ( transport.rolling )
  117. {
  118. fl_alert( "Can't make new file while the transport is running." );
  119. return;
  120. }
  121. // FIXME: check for dirtiness and ask to save.
  122. if ( maybe_save_song() )
  123. {
  124. init_song();
  125. // Sync the GUI.
  126. update_pattern_widgets();
  127. update_sequence_widgets();
  128. update_phrase_widgets();
  129. }}
  130. xywh {0 0 40 25}
  131. }
  132. MenuItem {} {
  133. label {&Open}
  134. callback {if ( transport.rolling )
  135. {
  136. fl_alert( "Can't open file while transport is rolling." );
  137. return;
  138. }
  139. char *name = fl_file_chooser( "Open File", "Non Files (*.non)", NULL, 0 );
  140. if ( name )
  141. {
  142. if ( ! load_song( name ) )
  143. fl_alert( "Could not load song!" );
  144. update_sequence_widgets();
  145. update_pattern_widgets();
  146. update_phrase_widgets();
  147. playback_mode_menu->value( song.play_mode );
  148. playback_mode_menu->redraw();
  149. }}
  150. xywh {0 0 40 25} shortcut 0x4006f color 37
  151. }
  152. MenuItem {} {
  153. label {&Save}
  154. callback {save_dialog( song.filename );}
  155. xywh {0 0 40 25} shortcut 0x40073 color 37
  156. }
  157. MenuItem {} {
  158. label {Save &As}
  159. callback {save_dialog( NULL );}
  160. xywh {0 0 40 25}
  161. }
  162. MenuItem {} {
  163. label {&Import}
  164. callback {char *name = fl_file_chooser( "MIDI Import", "MIDI Files (*.mid)", NULL, 0 );
  165. if ( ! name )
  166. return;
  167. smf f;
  168. if ( ! f.open( name, smf::READ ) )
  169. {
  170. fl_message( "could not open file" );
  171. return;
  172. }
  173. f.read_header();
  174. switch ( f.format() )
  175. {
  176. case 0:
  177. if ( ! pattern::import( &f, 0 ) )
  178. fl_message( "Error importing MIDI" );
  179. break;
  180. case 1: case 2:
  181. {
  182. char **sa = f.track_listing();
  183. if ( sa && *sa )
  184. {
  185. List_Chooser tc( "Select tracks to import:", "Import" );
  186. char *s;
  187. for ( int i = 0; (s = sa[i]); ++i )
  188. {
  189. tc.add( s );
  190. free( s );
  191. }
  192. free( sa );
  193. tc.show();
  194. while( tc.shown() )
  195. Fl::wait();
  196. int n = 0;
  197. for ( int i = 1; i <= tc.browser->size(); ++i )
  198. {
  199. if ( tc.browser->selected( i ) )
  200. {
  201. if ( pattern::import( &f , i - 1 ) )
  202. ++n;
  203. else
  204. WARNING( "error importing track %d", i - 1 );
  205. }
  206. }
  207. // fl_message( "%d patterns imported.", n );
  208. gui_status( "Imported %d tracks as patterns", n );
  209. }
  210. break;
  211. }
  212. }}
  213. xywh {0 0 40 25}
  214. code0 {\#include "../smf.H"}
  215. }
  216. MenuItem {} {
  217. label {&Export}
  218. callback {// Fl_File_Chooser::custom_filter_label = "*.mid";
  219. Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "MIDI Files (*.mid)", Fl_File_Chooser::CREATE, "MIDI Export" );
  220. fc->show();
  221. // wait for user to make a choice
  222. while( fc->shown() )
  223. Fl::wait();
  224. if ( ! fc->value() )
  225. return;
  226. if ( tabs->value() == pattern_tab )
  227. ((pattern*)pattern_c->grid())->save( fc->value() );}
  228. xywh {0 0 40 25}
  229. code0 {\#include <Fl/Fl_File_Chooser.H>}
  230. }
  231. MenuItem {} {
  232. label {&Quit}
  233. callback {main_window->do_callback();}
  234. xywh {0 0 40 25} shortcut 0x40071 color 37
  235. }
  236. }
  237. Submenu {} {
  238. label {&Edit} open
  239. xywh {0 0 74 25} color 37
  240. } {
  241. MenuItem {} {
  242. label {&Mapping}
  243. xywh {5 5 40 25} color 37
  244. }
  245. MenuItem {} {
  246. label {&Events}
  247. callback {if ( tabs->value() != pattern_tab )
  248. return;
  249. event_editor( pattern_c->grid() );}
  250. xywh {0 0 40 25}
  251. }
  252. MenuItem {} {
  253. label {&Randomization Settings}
  254. callback {randomization_dialog->show();}
  255. xywh {0 0 40 25}
  256. }
  257. }
  258. Submenu {} {
  259. label {&View} open
  260. xywh {10 10 74 25} color 37
  261. } {
  262. MenuItem {} {
  263. label {&Metronome}
  264. callback {int val = o->menu()[ o->value() ].value();
  265. if ( val )
  266. vmetro_widget->show();
  267. else
  268. vmetro_widget->hide();}
  269. xywh {0 0 40 25} type Toggle value 1
  270. }
  271. MenuItem {} {
  272. label {&Compacted}
  273. callback {int val = o->menu()[ o->value() ].value();
  274. pattern_c->row_compact( val ? Canvas::ON : Canvas::OFF );}
  275. xywh {10 10 40 25} type Toggle value 1
  276. }
  277. MenuItem {} {
  278. label {&Follow Playhead}
  279. callback {int val = o->menu()[ o->value() ].value();
  280. config.follow_playhead = val ? true : false;}
  281. xywh {10 10 40 25} type Toggle value 1
  282. }
  283. }
  284. Submenu {} {
  285. label {&Help} open
  286. xywh {100 0 74 25} color 37
  287. } {
  288. MenuItem {} {
  289. label {&Keys}
  290. callback {show_help_dialog( "KEYS" );}
  291. xywh {0 0 40 25}
  292. }
  293. MenuItem {} {
  294. label {&Manual}
  295. callback {show_help_dialog( "MANUAL" );}
  296. xywh {10 10 40 25} divider
  297. }
  298. MenuItem {} {
  299. label {&About}
  300. callback {make_about_popup();
  301. about_popup->show();}
  302. xywh {0 0 40 25} color 37
  303. code0 {\#include "../non.H"}
  304. }
  305. }
  306. }
  307. Fl_Tabs tabs {
  308. callback {// give this tab's canvas the focus
  309. //if ( o->value() == sequence_tab )
  310. // sequence_canvas_widget->take_focus();
  311. //else
  312. if ( o->value() == phrase_tab )
  313. phrase_canvas_widget->take_focus();
  314. else
  315. if ( o->value() == pattern_tab )
  316. pattern_canvas_widget->take_focus();} open
  317. xywh {0 76 868 701} color 37 labeltype SHADOW_LABEL labelsize 19 when 1
  318. code0 {canvas_background_color = fl_rgb_color( 18, 18, 18 );}
  319. } {
  320. Fl_Group sequence_tab {
  321. label Sequence open
  322. xywh {0 98 868 674} color 37 resizable
  323. code0 {update_sequence_widgets();}
  324. } {
  325. Fl_Group {} {open
  326. xywh {10 125 233 502} labelsize 12
  327. } {
  328. Fl_Browser playlist_browser {
  329. label Playlist
  330. xywh {10 125 233 435} type Hold box EMBOSSED_BOX color 39 selection_color 30 labelcolor 55 align 1 when 4 textsize 18 textcolor 95 resizable
  331. code0 {static int widths[] = { 40, 30, 0 };}
  332. code1 {o->column_widths( widths ); o->column_char( '\\t' );}
  333. code2 {o->value( 1 );}
  334. }
  335. Fl_Button sequence_phrase_delete_button {
  336. label Delete
  337. callback {int val = playlist_browser->value();
  338. if ( val > 1 )
  339. {
  340. // playlist_browser->value( playlist_browser->value() + 1 );
  341. playlist->remove( val - 2 );
  342. update_sequence_widgets();
  343. if ( ! playlist_browser->value() )
  344. playlist_browser->value( playlist_browser->size() );
  345. }}
  346. xywh {14 566 73 25} shortcut 0xffff color 88 labelcolor 23
  347. }
  348. Fl_Button sequence_phrase_up_button {
  349. label Up
  350. callback {if ( playlist_browser->value() > 2 )
  351. {
  352. playlist->move( playlist_browser->value() - 2, UP );
  353. playlist_browser->value( playlist_browser->value() - 1 );
  354. update_sequence_widgets();
  355. }}
  356. xywh {97 566 65 25} shortcut 0xffbf
  357. }
  358. Fl_Button sequence_phrase_down_button {
  359. label Down
  360. callback {if ( playlist_browser->value() > 1 )
  361. {
  362. playlist->move( playlist_browser->value() - 2, DOWN );
  363. playlist_browser->value( playlist_browser->value() + 1 );
  364. update_sequence_widgets();
  365. }}
  366. xywh {169 566 74 25} shortcut 0xffc0
  367. }
  368. Fl_Menu_Button sequence_phrase_choice {
  369. label {Insert Phrase}
  370. callback {playlist->insert( playlist_browser->value() - 1, o->value() + 1 );
  371. update_sequence_widgets();
  372. int val = playlist_browser->value();
  373. if ( val )
  374. playlist_browser->value( playlist_browser->value() + 1 );
  375. else
  376. playlist_browser->value( playlist_browser->size() );} open
  377. xywh {11 597 232 30} color 63
  378. } {}
  379. }
  380. Fl_Input sequence_name_field {
  381. label {name:}
  382. callback {playlist->name( o->value() );}
  383. xywh {91 740 158 26} color 36 align 20 when 1 textcolor 32
  384. }
  385. Fl_Light_Button detach_button {
  386. label Detach
  387. callback {if ( o->value() )
  388. {
  389. Fl_Group *g = seq_detached_group;
  390. g->add( sequence_tab );
  391. sequence_tab->resize( g->x(), g->y(), g->w(), g->h() );
  392. seq_window->show();
  393. }
  394. else
  395. {
  396. seq_window->hide();
  397. tabs->insert( (Fl_Widget&)*sequence_tab, 0 );
  398. sequence_tab->resize( pattern_tab->x(), pattern_tab->y(), pattern_tab->w(), pattern_tab->h() );
  399. }}
  400. xywh {7 740 78 26}
  401. }
  402. Fl_Text_Editor sequence_notes_edit {
  403. label {Notes:}
  404. callback {playlist->notes( o->buffer()->text() );}
  405. xywh {254 691 606 73} selection_color 48 labelsize 12 align 5 textcolor 94
  406. code0 {o->buffer( sequence_notes_buffer = new Fl_Text_Buffer );}
  407. }
  408. Fl_Box triggers_widget {
  409. label Patterns
  410. xywh {253 125 607 549} box UP_BOX color 72 align 1 resizable
  411. code0 {o->box( FL_NO_BOX );}
  412. class Triggers
  413. }
  414. Fl_Group progress_group {
  415. callback {if ( ! o->visible_r() )
  416. return;
  417. phrase *p = phrase::phrase_by_number( playlist->playing() );
  418. if ( p )
  419. phrase_progress->value( p->index() / (double)p->length() );
  420. if ( playlist->length() )
  421. sequence_progress->value( playlist->index() / (double)playlist->length() );} open
  422. xywh {10 656 233 66}
  423. } {
  424. Fl_Slider phrase_progress {
  425. label Phrase
  426. xywh {10 656 233 24} type Horizontal labelsize 12 align 1
  427. }
  428. Fl_Slider sequence_progress {
  429. label Sequence
  430. callback {transport.locate( (tick_t)((double)playlist->length() * o->value()) );} selected
  431. xywh {10 698 233 24} type Horizontal labelsize 12 align 1
  432. }
  433. }
  434. }
  435. Fl_Group phrase_tab {
  436. label Phrase open
  437. xywh {0 98 868 674} color 37 hide
  438. code0 {update_phrase_widgets();}
  439. } {
  440. Fl_Box phrase_canvas_widget {
  441. label Phrase
  442. xywh {4 102 860 590} box FLAT_BOX color 37 labelsize 100 align 16 resizable
  443. code0 {o->set_canvas( phrase_c );}
  444. code1 {o->box( FL_NO_BOX );}
  445. class O_Canvas
  446. }
  447. Fl_Group {} {open
  448. xywh {10 703 854 60}
  449. } {
  450. Fl_Input phrase_name_field {
  451. label {name:}
  452. callback {phrase_c->grid()->name( strdup( o->value() ) );
  453. // if the name changed..
  454. update_sequence_widgets();}
  455. xywh {10 703 144 25} color 36 align 20 textcolor 32
  456. }
  457. Fl_Spinner phrase_number_spinner {
  458. callback {phrase *p = ((phrase *)phrase_c->grid())->by_number( o->value() );
  459. if ( p )
  460. phrase_c->grid( p );
  461. o->maximum( phrase::phrases() );}
  462. xywh {164 703 40 25} color 36 labeltype NO_LABEL when 1
  463. }
  464. Fl_Light_Button phrase_mute_button {
  465. label Mute
  466. xywh {10 740 88 23} color 37 hide
  467. }
  468. Fl_Light_Button phrase_solo_button {
  469. label Solo
  470. xywh {111 740 87 23} color 37 hide
  471. }
  472. Fl_Text_Editor phrase_notes_edit {
  473. label {Notes:}
  474. callback {phrase_c->grid()->notes( o->buffer()->text() );}
  475. xywh {211 713 653 46} selection_color 48 labelsize 12 textcolor 94 resizable
  476. code0 {o->buffer( phrase_notes_buffer = new Fl_Text_Buffer );}
  477. }
  478. }
  479. }
  480. Fl_Group pattern_tab {
  481. label Pattern open
  482. xywh {0 98 868 674} color 37 hide
  483. code0 {update_pattern_widgets();}
  484. } {
  485. Fl_Box pattern_canvas_widget {
  486. label Pattern
  487. xywh {4 102 860 590} box FLAT_BOX color 37 labelsize 100 align 16 resizable
  488. code0 {\#include "draw.H"}
  489. code1 {o->set_canvas( pattern_c );}
  490. code2 {\#include "input.H"}
  491. code3 {o->box( FL_NO_BOX );}
  492. class O_Canvas
  493. }
  494. Fl_Group {} {open
  495. xywh {4 694 858 77}
  496. } {
  497. Fl_Input pattern_name_field {
  498. label {name:}
  499. callback {pattern_c->grid()->name( strdup( o->value() ) );}
  500. xywh {10 703 144 25} color 36 align 20 when 1 textcolor 32
  501. }
  502. Fl_Spinner pattern_number_spinner {
  503. callback {pattern *p = ((pattern *)pattern_c->grid())->by_number( o->value() );
  504. if ( p )
  505. pattern_c->grid( p );
  506. o->maximum( pattern::patterns() );}
  507. xywh {164 703 40 25} color 36 labeltype NO_LABEL when 1
  508. code0 {o->maximum( 1 );}
  509. code1 {// pattern::signal_create_destroy.connect( sigc::mem_fun( o, static_cast<void (Fl_Spinner::*)(double)>(&Fl_Spinner::maximum) ) );}
  510. }
  511. Fl_Light_Button pattern_mute_button {
  512. label Mute
  513. callback {Grid *g = pattern_c->grid();
  514. g->mode( g->mode() == MUTE ? PLAY : MUTE );
  515. o->value( g->mode() == MUTE );
  516. pattern_solo_button->value( 0 );}
  517. xywh {10 738 90 23} type Normal color 37
  518. code0 {// o->type(FL_RADIO_BUTTON);}
  519. }
  520. Fl_Light_Button pattern_solo_button {
  521. label Solo
  522. callback {Grid *g = pattern_c->grid();
  523. g->mode( g->mode() == SOLO ? PLAY : SOLO );
  524. o->value( g->mode() == SOLO );
  525. pattern_mute_button->value( 0 );}
  526. xywh {110 738 91 23} type Normal color 37
  527. code0 {// o->type( FL_RADIO_BUTTON );}
  528. }
  529. Fl_Text_Editor pattern_notes_edit {
  530. label {Notes:}
  531. callback {pattern_c->grid()->notes( o->buffer()->text() );}
  532. xywh {214 713 243 48} selection_color 48 labelsize 12 textcolor 94 resizable
  533. code0 {o->buffer( pattern_notes_buffer = new Fl_Text_Buffer );}
  534. }
  535. Fl_Group pattern_settings_group {open
  536. xywh {458 694 400 77}
  537. } {
  538. Fl_Spinner pattern_channel_spinner {
  539. label Channel
  540. callback {((pattern *)pattern_c->grid())->channel( o->value() - 1 );}
  541. xywh {815 700 40 24} color 36 when 1
  542. code0 {\#include "../pattern.H"}
  543. code1 {o->maximum( 16 );}
  544. }
  545. Fl_Spinner pattern_port_spinner {
  546. label Port
  547. callback {((pattern *)pattern_c->grid())->port( o->value() - 1 );}
  548. xywh {815 734 40 24} color 36 when 1
  549. code0 {o->maximum( 16 );}
  550. }
  551. Fl_Output mapping_text {
  552. label Mapping
  553. xywh {464 734 145 24} align 20
  554. }
  555. Fl_Menu_Button mapping_menu {
  556. label {@>}
  557. callback {mapping_text->value( o->text() );
  558. char picked[80];
  559. mapping_menu->item_pathname(picked, sizeof(picked)-1 );
  560. if ( 0 == strncmp( picked, "Instrument", strlen( "Instrument" ) ) )
  561. {
  562. ((pattern*)pattern_c->grid())->mapping.open( Mapping::INSTRUMENT, o->text() );
  563. pattern_c->changed_mapping();
  564. pattern_key_combo->deactivate();
  565. }
  566. else
  567. if ( 0 == strncmp( picked, "Scale", strlen( "Scale" ) ) )
  568. {
  569. ((pattern*)pattern_c->grid())->mapping.open( Mapping::SCALE, o->text() );
  570. pattern_c->changed_mapping();
  571. pattern_key_combo->activate();
  572. }} open
  573. xywh {609 734 30 24} labeltype NO_LABEL
  574. code0 {update_mapping_menu();}
  575. } {
  576. Submenu mapping_scale_menu {
  577. label Scale open
  578. xywh {25 25 74 25}
  579. } {}
  580. Submenu mapping_instrument_menu {
  581. label Instrument open
  582. xywh {10 10 74 25}
  583. } {}
  584. }
  585. Fl_Choice pattern_key_combo {
  586. label {&Key}
  587. callback {((pattern*)pattern_c->grid())->mapping.key( o->value() );
  588. pattern_c->changed_mapping();}
  589. xywh {674 734 75 24} down_box BORDER_BOX when 1
  590. } {
  591. MenuItem {} {
  592. label C
  593. xywh {30 30 40 25}
  594. }
  595. MenuItem {} {
  596. label {C\#/Db}
  597. xywh {40 40 40 25}
  598. }
  599. MenuItem {} {
  600. label D
  601. xywh {50 50 40 25}
  602. }
  603. MenuItem {} {
  604. label {D\#/Eb}
  605. xywh {60 60 40 25}
  606. }
  607. MenuItem {} {
  608. label E
  609. xywh {70 70 40 25}
  610. }
  611. MenuItem {} {
  612. label F
  613. xywh {80 80 40 25}
  614. }
  615. MenuItem {} {
  616. label {F\#/Gb}
  617. xywh {90 90 40 25}
  618. }
  619. MenuItem {} {
  620. label G
  621. xywh {100 100 40 25}
  622. }
  623. MenuItem {} {
  624. label {G\#}
  625. xywh {110 110 40 25}
  626. }
  627. MenuItem {} {
  628. label A
  629. xywh {0 0 40 25}
  630. }
  631. MenuItem {} {
  632. label {A\#/Bb}
  633. xywh {10 10 40 25}
  634. }
  635. MenuItem {} {
  636. label B
  637. xywh {20 20 40 25}
  638. }
  639. }
  640. Fl_Choice pattern_note_combo {
  641. label {&Note 1/}
  642. callback {((pattern*)pattern_c->grid())->note( atoi( o->menu()[ o->value() ].text ));}
  643. xywh {704 700 45 24} down_box BORDER_BOX when 1
  644. } {
  645. MenuItem {} {
  646. label 1
  647. xywh {0 0 40 25}
  648. }
  649. MenuItem {} {
  650. label 2
  651. xywh {10 10 40 25}
  652. }
  653. MenuItem {} {
  654. label 4
  655. xywh {20 20 40 25}
  656. }
  657. MenuItem {} {
  658. label 8
  659. xywh {30 30 40 25}
  660. }
  661. MenuItem {} {
  662. label 16
  663. xywh {40 40 40 25}
  664. }
  665. MenuItem {} {
  666. label 32
  667. xywh {50 50 40 25}
  668. }
  669. MenuItem {} {
  670. label 64
  671. xywh {60 60 40 25} divider
  672. }
  673. MenuItem {} {
  674. label 3
  675. xywh {60 60 40 25}
  676. }
  677. MenuItem {} {
  678. label 6
  679. xywh {70 70 40 25}
  680. }
  681. MenuItem {} {
  682. label 12
  683. xywh {80 80 40 25}
  684. }
  685. MenuItem {} {
  686. label 24
  687. xywh {90 90 40 25}
  688. }
  689. }
  690. Fl_Choice pattern_res_combo {
  691. label {&Resolution 1/}
  692. callback {pattern_c->grid()->resolution( atoi( o->menu()[ o->value() ].text ));}
  693. xywh {584 700 55 24} down_box BORDER_BOX when 1
  694. } {
  695. MenuItem {} {
  696. label 4
  697. xywh {30 30 40 25}
  698. }
  699. MenuItem {} {
  700. label 8
  701. xywh {40 40 40 25}
  702. }
  703. MenuItem {} {
  704. label 16
  705. xywh {50 50 40 25}
  706. }
  707. MenuItem {} {
  708. label 32
  709. xywh {60 60 40 25}
  710. }
  711. MenuItem {} {
  712. label 64
  713. xywh {80 80 40 25}
  714. }
  715. MenuItem {} {
  716. label 128
  717. xywh {90 90 40 25} divider
  718. }
  719. MenuItem {} {
  720. label 3
  721. xywh {70 70 40 25}
  722. }
  723. MenuItem {} {
  724. label 6
  725. xywh {80 80 40 25}
  726. }
  727. MenuItem {} {
  728. label 12
  729. xywh {90 90 40 25}
  730. }
  731. MenuItem {} {
  732. label 24
  733. xywh {100 100 40 25}
  734. }
  735. }
  736. }
  737. }
  738. }
  739. }
  740. Fl_Group {} {open
  741. xywh {5 33 853 52}
  742. } {
  743. Fl_Choice playback_mode_menu {
  744. label {Playback &Mode} open
  745. xywh {751 54 107 30} box PLASTIC_DOWN_BOX down_box BORDER_BOX color 37 align 1
  746. } {
  747. MenuItem {} {
  748. label Pattern
  749. callback {song.play_mode = PATTERN;}
  750. xywh {0 0 40 25}
  751. }
  752. MenuItem {} {
  753. label Sequence
  754. callback {song.play_mode = SEQUENCE;}
  755. xywh {10 10 40 25}
  756. }
  757. MenuItem {} {
  758. label Trigger
  759. callback {song.play_mode = TRIGGER;}
  760. xywh {20 20 40 25}
  761. }
  762. }
  763. Fl_Choice record_mode_menu {
  764. label {&Record Mode}
  765. callback {if ( ! transport.recording )
  766. config.record_mode = (record_mode_e)o->value();
  767. else
  768. o->value( config.record_mode );} open
  769. xywh {634 54 107 30} box PLASTIC_DOWN_BOX down_box BORDER_BOX color 37 align 1
  770. } {
  771. MenuItem {} {
  772. label Merge
  773. xywh {10 10 40 25}
  774. }
  775. MenuItem {} {
  776. label Overwrite
  777. xywh {20 20 40 25}
  778. }
  779. MenuItem {} {
  780. label Layer
  781. xywh {30 30 40 25}
  782. }
  783. MenuItem {} {
  784. label New
  785. xywh {40 40 40 25}
  786. }
  787. }
  788. Fl_Pack vmetro_widget {
  789. label Metronome open
  790. xywh {226 37 245 48} type HORIZONTAL box UP_BOX color 40 selection_color 48 labelsize 33 align 0 resizable
  791. code0 {\#include "widgets.H"}
  792. code1 {o->box( FL_NO_BOX );}
  793. class Visual_Metronome
  794. } {}
  795. Fl_Group transport_controls_group {
  796. xywh {481 37 143 48}
  797. } {
  798. Fl_Button play_button {
  799. label {@>}
  800. callback {transport.toggle();}
  801. xywh {531 43 34 35} shortcut 0x20 labeltype ENGRAVED_LABEL
  802. }
  803. Fl_Button rec_button {
  804. label {@circle}
  805. callback {transport.recording = o->value();
  806. if ( o->value() )
  807. {
  808. if ( config.record_mode == NEW )
  809. {
  810. pattern *p = new pattern;
  811. p->length( -1 );
  812. pattern_c->grid( p );
  813. }
  814. ((pattern*)pattern_c->grid())->record( 0 );
  815. o->labelcolor( FL_RED );
  816. }
  817. else
  818. {
  819. pattern::recording()->record_stop();
  820. o->labelcolor( FL_WHITE );
  821. }}
  822. xywh {575 43 49 35} type Toggle shortcut 0x80072 selection_color 47 labeltype ENGRAVED_LABEL when 1
  823. }
  824. Fl_Button home_button {
  825. label {@|<}
  826. callback {transport.locate( 0 );}
  827. xywh {481 43 40 35} shortcut 0xff50 labeltype ENGRAVED_LABEL
  828. }
  829. }
  830. Fl_Group {} {open
  831. xywh {5 33 208 38}
  832. } {
  833. Fl_Box {} {
  834. label {BPM:}
  835. xywh {5 37 35 34}
  836. }
  837. Fl_Counter {} {
  838. callback {transport.set_beats_per_minute( o->value() );}
  839. xywh {43 41 97 24} labeltype NO_LABEL align 4
  840. code1 {transport.signal_tempo_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Counter::*)(double)>(&Fl_Counter::value) ) );}
  841. code2 {o->value( transport.beats_per_minute );}
  842. }
  843. Fl_Value_Input {} {
  844. callback {transport.set_beats_per_bar( o->value() );}
  845. xywh {149 41 26 24}
  846. code0 {transport.signal_bpb_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value) ) );}
  847. code1 {o->value( transport.beats_per_bar );}
  848. }
  849. Fl_Value_Input {} {
  850. callback {transport.set_beat_type( o->value() );}
  851. xywh {189 41 24 24}
  852. code0 {transport.signal_beat_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value) ) );}
  853. code1 {o->value( transport.beat_type );}
  854. }
  855. Fl_Box {} {
  856. label {/}
  857. xywh {170 41 19 24}
  858. }
  859. }
  860. }
  861. Fl_Output status {
  862. xywh {3 776 861 21} box NO_BOX color 32 labeltype NO_LABEL textcolor 55
  863. }
  864. }
  865. }
  866. Function {make_seq_window()} {} {
  867. Fl_Window seq_window {
  868. callback {sequence_tab->activate();
  869. o->hide();
  870. detach_button->value( 0 );}
  871. xywh {189 27 1278 1003} type Single hide resizable
  872. } {
  873. Fl_Group seq_detached_group {open
  874. xywh {0 0 1277 1003} resizable
  875. } {}
  876. }
  877. }
  878. Function {make_about_popup()} {} {
  879. Fl_Window about_popup {
  880. label About open
  881. xywh {944 405 539 608} type Single non_modal size_range {539 608 539 608} visible
  882. } {
  883. Fl_Box {} {
  884. label VERSION
  885. image {../logo.xpm} xywh {10 29 525 209}
  886. code0 {o->label( VERSION );}
  887. }
  888. Fl_Group {} {open
  889. xywh {26 272 488 272} box ROUNDED_BOX color 51
  890. } {
  891. Fl_Box {} {
  892. label {Copyright (C) 2007-2008 Jonathan Moore Liles}
  893. xywh {26 272 488 32} labeltype SHADOW_LABEL labelfont 1 labelsize 18
  894. }
  895. Fl_Box {} {
  896. label {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.
  897. 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.
  898. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.}
  899. xywh {41 311 463 233} labelfont 1 labelsize 12 align 144
  900. }
  901. }
  902. Fl_Button {} {
  903. label {http://non.tuxfamily.org}
  904. callback {system( "x-www-browser http://non.tuxfamily.org &" );}
  905. xywh {178 554 188 30} color 14 labeltype SHADOW_LABEL labelcolor 6
  906. }
  907. Fl_Return_Button {} {
  908. label rock
  909. callback {about_popup->hide();}
  910. xywh {453 570 78 31}
  911. }
  912. }
  913. }
  914. Function {make_randomization_dialog()} {open
  915. } {
  916. Fl_Window randomization_dialog {
  917. label {Randomization Settings} open
  918. xywh {841 360 342 98} type Double
  919. code0 {// feel->value( )}
  920. code1 {probability->value( song.random.probability );} non_modal visible
  921. } {
  922. Fl_Choice feel {
  923. label {Feel: 1/}
  924. callback {song.random.feel = atoi( o->menu()[ find_numeric_menu_item( o->menu(), o->value() ) ].text );} open
  925. xywh {67 55 50 24} down_box BORDER_BOX
  926. } {
  927. MenuItem {} {
  928. label 4
  929. xywh {10 10 40 25}
  930. }
  931. MenuItem {} {
  932. label 8
  933. xywh {0 0 40 25}
  934. }
  935. MenuItem {} {
  936. label 16
  937. xywh {10 10 40 25}
  938. }
  939. }
  940. Fl_Box {} {
  941. label {Randomization Settings}
  942. xywh {10 15 321 28} box ROUNDED_BOX color 94 labelsize 22 labelcolor 39
  943. }
  944. Fl_Counter probability {
  945. label Probability
  946. callback {song.random.probability = o->value();}
  947. xywh {216 53 112 26} type Simple align 4 when 4 minimum 0 maximum 1 step 0.01
  948. }
  949. }
  950. }
  951. Function {update_pattern_widgets()} {} {
  952. code {if ( ! pattern_settings_group )
  953. return;
  954. pattern *g = (pattern *)pattern_c->grid();
  955. pattern_number_spinner->value( g->number() );
  956. pattern_name_field->value( g->name() );
  957. pattern_channel_spinner->value( 1 + g->channel() );
  958. pattern_port_spinner->value( 1 + g->port() );
  959. pattern_solo_button->value( g->mode() == SOLO );
  960. pattern_mute_button->value( g->mode() == MUTE );
  961. if ( g->mapping.key() == -1 )
  962. pattern_key_combo->deactivate();
  963. else
  964. {
  965. pattern_key_combo->activate();
  966. pattern_key_combo->value( g->mapping.key() );
  967. }
  968. mapping_text->value( g->mapping.name() );
  969. pattern_note_combo->value( find_numeric_menu_item( menu_pattern_note_combo, g->note() ));
  970. pattern_res_combo->value( find_numeric_menu_item( menu_pattern_res_combo, g->resolution() ));
  971. if ( g->notes() )
  972. pattern_notes_buffer->text( g->notes() );
  973. else
  974. pattern_notes_buffer->text( strdup( "" ) );} {}
  975. }
  976. Function {update_phrase_widgets()} {} {
  977. code {phrase *g = (phrase *)phrase_c->grid();
  978. if ( ! g )
  979. return;
  980. phrase_number_spinner->value( g->number() );
  981. phrase_name_field->value( g->name() );
  982. phrase_solo_button->value( g->mode() == SOLO );
  983. phrase_mute_button->value( g->mode() == MUTE );
  984. if ( g->notes() )
  985. phrase_notes_buffer->text( g->notes() );
  986. else
  987. phrase_notes_buffer->text( strdup( "" ) );} {}
  988. }
  989. Function {update_sequence_widgets()} {open
  990. } {
  991. code {if ( playlist->notes() )
  992. sequence_notes_buffer->text( playlist->notes() );
  993. else
  994. sequence_notes_buffer->text( strdup( "" ) );
  995. sequence_name_field->value( playlist->name() );
  996. sequence_phrase_choice->clear();
  997. for ( int i = 1; i <= phrase::phrases(); i++ )
  998. {
  999. phrase *p = phrase::phrase_by_number( i );
  1000. if ( p )
  1001. sequence_phrase_choice->add( p->name() );
  1002. }
  1003. Fl_Browser *o = playlist_browser;
  1004. int val = o->value();
  1005. o->clear();
  1006. char *s = playlist->dump();
  1007. char *l = strtok( s, "\\n" );
  1008. o->add( "@b@C2Bar\\t@b@C2\#\\t@b@C2Name" );
  1009. if ( ! l )
  1010. return;
  1011. o->add( l );
  1012. while ( ( l = strtok( NULL, "\\n" ) ) )
  1013. {
  1014. o->add( l );
  1015. }
  1016. o->value( val );
  1017. free( s );} {}
  1018. }
  1019. Function {update_mapping_menu()} {open
  1020. } {
  1021. code {char **sa = Instrument::listing();
  1022. if ( sa )
  1023. {
  1024. for ( int i = 0; sa[i]; i++ )
  1025. {
  1026. char pat[512];
  1027. snprintf( pat, 512, "Instrument/%s", sa[i] );
  1028. mapping_menu->add( pat, 0, 0, 0, 0 );
  1029. free( sa[i] );
  1030. }
  1031. free( sa );
  1032. }
  1033. sa = Scale::listing();
  1034. for ( int i = 0; sa[i]; i++ )
  1035. {
  1036. char pat[512];
  1037. snprintf( pat, 512, "Scale/%s", sa[i] );
  1038. mapping_menu->add( pat, 0, 0, 0, 0 );
  1039. free( sa[i] );
  1040. }
  1041. free( sa );} {}
  1042. }
  1043. Function {update_canvas_widgets()} {return_type {static void}
  1044. } {
  1045. code {if ( pattern_c->grid() )
  1046. ui->update_pattern_widgets();
  1047. if ( phrase_c->grid() )
  1048. ui->update_phrase_widgets();} {}
  1049. }
  1050. Function {find_numeric_menu_item( const Fl_Menu_Item *menu, int n )} {return_type {static int}
  1051. } {
  1052. code {for ( unsigned int i = 0; menu[i].text; i++ )
  1053. {
  1054. if ( atoi( menu[i].text ) == n )
  1055. return i;
  1056. }
  1057. return 0;} {}
  1058. }
  1059. Function {save_dialog( const char *name )} {return_type void
  1060. } {
  1061. code {if ( ! name )
  1062. {
  1063. Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "Non Sequences (*.non)", Fl_File_Chooser::CREATE, "Save sequence" );
  1064. fc->show();
  1065. // wait for user to make a choice
  1066. while( fc->shown() )
  1067. Fl::wait();
  1068. if ( ! fc->value() )
  1069. return;
  1070. name = fc->value();
  1071. }
  1072. if ( ! save_song( name ) )
  1073. fl_alert( "Could not save song" );} {}
  1074. }
  1075. Function {show_help_dialog( const char *file )} {return_type void
  1076. } {
  1077. code {char pat[256];
  1078. snprintf( pat, 256, "%s%s.html", DOCUMENT_PATH, file );
  1079. Fl_Help_Dialog *help; // Help dialog
  1080. help = new Fl_Help_Dialog;
  1081. help->load( pat );
  1082. help->show();
  1083. // FIXME: need to delete it somehow.
  1084. // help->show(1, argv);} {}
  1085. }
  1086. Function {maybe_save_song()} {return_type bool
  1087. } {
  1088. code {if ( song.dirty )
  1089. {
  1090. int c = fl_choice( "Song has been modified since last save. What shall I do?", "Cancel", "Save", "Discard" );
  1091. switch ( c )
  1092. {
  1093. case 0:
  1094. return false;
  1095. case 1:
  1096. /* SAVE */
  1097. save_dialog( song.filename );
  1098. break;
  1099. case 2:
  1100. break;
  1101. }
  1102. }
  1103. return true;} {}
  1104. }
  1105. Function {switch_to_pattern( int n )} {return_type void
  1106. } {
  1107. code {pattern *p = pattern::pattern_by_number( n );
  1108. if ( p )
  1109. {
  1110. tabs->value( pattern_tab );
  1111. pattern_canvas_widget->take_focus();
  1112. pattern_c->grid( p );
  1113. // update_pattern_widgets();
  1114. }} {}
  1115. }
  1116. }
  1117. decl {\#include <Fl/Fl_Single_Window.H>} {public
  1118. }
  1119. class O_Canvas {open : {public Fl_Widget}
  1120. } {
  1121. decl {Canvas *_c;} {}
  1122. decl {bool _border_drawn;} {}
  1123. decl {uint _flags;} {}
  1124. Function {O_Canvas( int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L)} {open
  1125. } {
  1126. code {_c = NULL;
  1127. _border_drawn = false;
  1128. _flags = 0;} {}
  1129. }
  1130. Function {handle( int m )} {open return_type int
  1131. } {
  1132. code {// Accept focus if offered.
  1133. if ( m == FL_FOCUS || m == FL_UNFOCUS )
  1134. {
  1135. _border_drawn = false;
  1136. draw_playhead();
  1137. return 1;
  1138. }
  1139. // Hack in click-to-focus
  1140. if ( m == FL_PUSH )
  1141. if ( Fl::event_inside( this ) )
  1142. take_focus();
  1143. // Ignore events unless we have the focus.
  1144. if ( this != Fl::focus() )
  1145. return 0;
  1146. // MESSAGE( "got event %i for canvas %p", m, _c );
  1147. int p = 0;
  1148. if ( _c )
  1149. {
  1150. p = canvas_input_callback( this, _c, m );
  1151. }
  1152. return p;} {}
  1153. }
  1154. Function {resize( int x, int y, int w, int h )} {open
  1155. } {
  1156. code {if ( _c )
  1157. {
  1158. DEBUG( "Resizing canvas." );
  1159. _c->resize( x + 1, y + 1, w - 1, h - 1 );
  1160. }
  1161. Fl_Widget::resize( x, y, w, h );
  1162. // Fl_Window::resize( x, y, w, h );} {}
  1163. }
  1164. Function {draw()} {open return_type void
  1165. } {
  1166. code {draw_border();
  1167. if ( ! takesevents() )
  1168. return;
  1169. if ( _c )
  1170. {
  1171. damage( _flags );
  1172. _flags = 0;
  1173. /*
  1174. if ( damage() & FL_DAMAGE_ALL ) printf( " damage_all" );
  1175. if ( damage() & FL_DAMAGE_SCROLL ) printf( " damage_scroll" );
  1176. if ( damage() & FL_DAMAGE_USER1 ) printf( " damage_user1" );
  1177. if ( damage() & FL_DAMAGE_USER2 ) printf( " damage_user2" );
  1178. if ( damage() & FL_DAMAGE_EXPOSE ) printf( " damage_expose" );
  1179. printf("\\n");
  1180. */
  1181. if ( damage() & (FL_DAMAGE_ALL | FL_DAMAGE_USER2) )
  1182. {
  1183. _c->redraw();
  1184. }
  1185. if ( damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL) )
  1186. {
  1187. // optimized draw
  1188. _c->draw();
  1189. }
  1190. else
  1191. if ( damage() & (FL_DAMAGE_ALL | FL_DAMAGE_USER1) )
  1192. {
  1193. // playhead
  1194. _c->draw_playhead();
  1195. }
  1196. else
  1197. if ( damage() & FL_DAMAGE_ALL )
  1198. {
  1199. _border_drawn = false;
  1200. draw_border();
  1201. _c->redraw();
  1202. }
  1203. }
  1204. else
  1205. {
  1206. WARNING( "No canvas set for widget." );
  1207. }} {}
  1208. }
  1209. Function {set_canvas( Canvas *c )} {open
  1210. } {
  1211. code {_c = c;
  1212. _c->resize( x(), y(), w(), h() );
  1213. _c->signal_draw.connect( sigc::mem_fun( this, &O_Canvas::draw_notes ) );
  1214. _c->signal_resize.connect( sigc::mem_fun( this, &O_Canvas::clear ) );
  1215. _c->signal_settings_change.connect( sigc::ptr_fun( &UI::update_canvas_widgets ) );} {}
  1216. }
  1217. Function {click_to_focus()} {open return_type bool
  1218. } {
  1219. code {return true;} {}
  1220. }
  1221. Function {clear( void )} {open return_type void
  1222. } {
  1223. code {parent()->parent()->damage( FL_DAMAGE_ALL, x(), y(), w(), h() );
  1224. damage( FL_DAMAGE_USER2 );
  1225. _flags |= FL_DAMAGE_USER2;} {}
  1226. }
  1227. Function {draw_notes( void )} {open return_type void
  1228. } {
  1229. code {damage( FL_DAMAGE_SCROLL );
  1230. // this might be called from within draw(), in which case the above does nothing.
  1231. _flags |= FL_DAMAGE_SCROLL;} {}
  1232. }
  1233. Function {draw_playhead( void )} {open return_type void
  1234. } {
  1235. code {damage( FL_DAMAGE_USER1 );} {}
  1236. }
  1237. Function {draw_border()} {open return_type void
  1238. } {
  1239. code {if ( _border_drawn )
  1240. return;
  1241. if ( this != Fl::focus() )
  1242. fl_color( FL_RED );
  1243. else
  1244. fl_color( FL_BLACK );
  1245. fl_line_style( FL_DASH );
  1246. fl_rect( x(), y(), w(), h() );
  1247. fl_line_style( FL_SOLID );
  1248. _border_drawn = true;} {}
  1249. }
  1250. }
  1251. Function {shortcut_handler( int e )} {open return_type int
  1252. } {
  1253. code {if ( e != FL_SHORTCUT )
  1254. return 0;
  1255. // this is for mainwindow shortcuts only, ignore all other windows.
  1256. if ( Fl::first_window() != ui->main_window )
  1257. return 0;
  1258. int processed = 0;
  1259. // shortcuts that don't fit anywhere else (widgets that don't take shortcuts, etc.)
  1260. \#define KEY(key) ((Fl::test_shortcut( (key) )))
  1261. processed = 1;
  1262. if KEY( FL_ALT + 's' )
  1263. {
  1264. ui->tabs->value( ui->sequence_tab );
  1265. }
  1266. else
  1267. if KEY( FL_ALT + 'a' )
  1268. {
  1269. ui->tabs->value( ui->phrase_tab );
  1270. ((Fl_Group*)ui->tabs->value())->child( 0 )->take_focus();
  1271. }
  1272. else
  1273. if KEY( FL_ALT + 'p' )
  1274. {
  1275. ui->tabs->value( ui->pattern_tab );
  1276. ((Fl_Group*)ui->tabs->value())->child( 0 )->take_focus();
  1277. }
  1278. else
  1279. if KEY( FL_ALT + 'c' )
  1280. ui->pattern_channel_spinner->take_focus();
  1281. else
  1282. if KEY( FL_ALT + 'o' )
  1283. ui->pattern_port_spinner->take_focus();
  1284. else
  1285. if KEY( FL_ALT + 'i' )
  1286. ui->mapping_menu->take_focus();
  1287. else
  1288. processed = 0;
  1289. return processed;} {}
  1290. }
  1291. class Trigger {open : {public Fl_Dial}
  1292. } {
  1293. Function {Trigger( int X, int Y, int W, int H, const char *L = 0 ) : Fl_Dial( X, Y, W, H, L )} {open
  1294. } {}
  1295. Function {handle( int m )} {open return_type int
  1296. } {
  1297. code {int r = 0;
  1298. switch ( m )
  1299. {
  1300. case FL_PUSH:
  1301. {
  1302. switch ( Fl::event_button() )
  1303. {
  1304. case 1:
  1305. {
  1306. pattern *p = pattern::pattern_by_number( atoi( label() ) );
  1307. if ( p )
  1308. {
  1309. if ( p->mode() == MUTE )
  1310. p->mode( PLAY );
  1311. else
  1312. p->mode( MUTE );
  1313. }
  1314. break;
  1315. }
  1316. case 2:
  1317. {
  1318. pattern *p = pattern::pattern_by_number( atoi( label() ) );
  1319. if ( p )
  1320. {
  1321. if ( p->mode() != SOLO )
  1322. p->mode( SOLO );
  1323. else
  1324. p->mode( PLAY );
  1325. }
  1326. break;
  1327. }
  1328. case 3:
  1329. {
  1330. ui->switch_to_pattern( atoi( label() ) );
  1331. }
  1332. break;
  1333. }
  1334. r = 1;
  1335. break;
  1336. }
  1337. case FL_RELEASE:
  1338. MESSAGE("doing callback");
  1339. do_callback();
  1340. r = 1;
  1341. break;
  1342. case FL_DRAG:
  1343. r = 1;
  1344. break;
  1345. default:
  1346. r = Fl_Widget::handle( m );
  1347. break;
  1348. }
  1349. return r;} {}
  1350. }
  1351. }
  1352. widget_class Triggers {open
  1353. xywh {121 31 1278 1003} type Double hide resizable
  1354. code0 {populate();}
  1355. code1 {\#include <Fl/Fl_Dial.H>}
  1356. class Fl_Group
  1357. } {
  1358. Fl_Pack rows {open
  1359. xywh {25 25 15 15}
  1360. code0 {// o->position( x(), y() );}
  1361. } {}
  1362. Function {populate( void )} {open private return_type void
  1363. } {
  1364. code {int bw = (w() / 16);
  1365. int bh = h() / (128/ 16);
  1366. begin();
  1367. for ( int n = 0; n < 128 ; n += 16 )
  1368. {
  1369. Fl_Pack *p = new Fl_Pack( 0, 0, 25, 25 );
  1370. p->type( Fl_Pack::HORIZONTAL );
  1371. for ( int i = 0; i < 16; i++ )
  1372. {
  1373. Trigger *b = new Trigger( 0, 0, bw, 50, "Num" );
  1374. char pat[4];
  1375. sprintf( pat, "%d", n + i + 1 );
  1376. b->label( strdup( pat ) );
  1377. b->minimum( 0 );
  1378. b->maximum( 1 );
  1379. b->angles( 0, 360 );
  1380. b->type( FL_FILL_DIAL );
  1381. // b->box( FL_ROUNDED_BOX );
  1382. // b->down_box( FL_ROUNDED_BOX );
  1383. b->selection_color( FL_GREEN );
  1384. b->color( FL_BLACK );
  1385. b->align( FL_ALIGN_CENTER );
  1386. p->add( b );
  1387. }
  1388. p->end();
  1389. p->resize( 0, 0, w(), bh );
  1390. rows->add( p );
  1391. }
  1392. end();
  1393. rows->resize( x(), y(), w(), h() );
  1394. redraw();} {}
  1395. }
  1396. Function {update( void )} {open return_type void
  1397. } {
  1398. code {if ( ! takesevents() )
  1399. return;
  1400. int i;
  1401. for ( i = 0; i < MAX_PATTERN; i++ )
  1402. {
  1403. Trigger *b = (Trigger*)(((Fl_Pack*)rows->child( i / 16 ))->child( i % 16 ));
  1404. if ( i >= pattern::patterns() )
  1405. {
  1406. b->color( FL_BLACK );
  1407. b->value( 0 );
  1408. continue;
  1409. }
  1410. pattern *p = pattern::pattern_by_number( i + 1 );
  1411. if ( p->playing() )
  1412. {
  1413. b->color( fl_lighter( FL_GRAY ) );
  1414. Fl_Color c;
  1415. switch ( p->mode() )
  1416. {
  1417. case MUTE:
  1418. c = FL_GRAY;
  1419. break;
  1420. case SOLO:
  1421. c = FL_RED;
  1422. break;
  1423. case PLAY:
  1424. c = FL_GREEN;
  1425. break;
  1426. }
  1427. b->selection_color( c );
  1428. b->value( (double)p->index() / p->length() );
  1429. }
  1430. else
  1431. {
  1432. b->value( 0 );
  1433. }
  1434. }} {}
  1435. }
  1436. Function {resize( int X, int Y, int W, int H )} {open return_type void
  1437. } {
  1438. code {for ( int i = rows->children(); i--; )
  1439. {
  1440. Fl_Pack *p = (Fl_Pack*) rows->child( i );
  1441. for ( int j = p->children(); j--; )
  1442. {
  1443. int bw = W / p->children();
  1444. p->child( j )->resize( 0, 0, bw, 25 );;
  1445. }
  1446. p->resize( 0, 0, W, H / rows->children() );
  1447. p->redraw();
  1448. }
  1449. Fl_Group::resize( X, Y, W, H );} {}
  1450. }
  1451. }