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.

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