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.

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