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.

1969 lines
50KB

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