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.

1744 lines
44KB

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