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.

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