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.

1775 lines
44KB

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