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.

1801 lines
45KB

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