1934 lines
49 KiB
Plaintext
1934 lines
49 KiB
Plaintext
# data file for the Fltk User Interface Designer (fluid)
|
|
version 1.0300
|
|
header_name {.H}
|
|
code_name {.C}
|
|
comment {//
|
|
// Copyright (C) 2008 Jonathan Moore Liles
|
|
//
|
|
// 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.
|
|
//
|
|
// 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.
|
|
//
|
|
// 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.
|
|
//
|
|
} {in_source in_header
|
|
}
|
|
|
|
decl {\#include <FL/Fl_Dial.H>} {public local
|
|
}
|
|
|
|
decl {\#include <About_Dialog.H>} {private local
|
|
}
|
|
|
|
decl {class Fl_Scalepack;} {public local
|
|
}
|
|
|
|
decl {class Fl_Sometimes_Input;} {public local
|
|
}
|
|
|
|
decl {\#include <FL/Fl_Theme_Chooser.H>} {private local
|
|
}
|
|
|
|
decl {\#include <Fl_Scalepack.H>} {private local
|
|
}
|
|
|
|
decl {\#include <Fl_Sometimes_Input.H>} {private local
|
|
}
|
|
|
|
decl {\#include <Fl_Menu_Settings.H>} {private local
|
|
}
|
|
|
|
decl {\#include <FL/Fl_Shared_Image.H>} {private local
|
|
}
|
|
|
|
decl {\#include "widgets.H"} {private local
|
|
}
|
|
|
|
decl {\#include "event_edit.H"} {private local
|
|
}
|
|
|
|
decl {\#include "../jack.H"} {private local
|
|
}
|
|
|
|
decl {\#include "../NSM.H"} {private local
|
|
}
|
|
|
|
decl {extern NSM_Client *nsm;} {private local
|
|
}
|
|
|
|
decl {extern UI *ui;} {private local
|
|
}
|
|
|
|
decl {class O_Canvas;} {private local
|
|
}
|
|
|
|
decl {class Triggers;} {public local
|
|
}
|
|
|
|
decl {class Instrument_Editor;} {private local
|
|
}
|
|
|
|
decl {Fl_Color canvas_background_color;} {public local
|
|
}
|
|
|
|
decl {extern Fl_Color velocity_colors[];} {private local
|
|
}
|
|
|
|
Function {update_transport( void * )} {open return_type void
|
|
} {
|
|
code {// transport_poll();
|
|
|
|
handle_midi_input();
|
|
|
|
ui->progress_group->do_callback();
|
|
|
|
ui->vmetro_widget->update();
|
|
|
|
ui->triggers_widget->update();
|
|
|
|
Fl::repeat_timeout( TRANSPORT_POLL_INTERVAL, update_transport );
|
|
|
|
static int oldstate = -1;
|
|
|
|
if ( transport.rolling != oldstate )
|
|
{
|
|
|
|
ui->play_button->label( transport.rolling ? "@square" : "@>" );
|
|
oldstate = transport.rolling;
|
|
|
|
if ( transport.rolling )
|
|
{
|
|
ui->menu_new->deactivate();
|
|
ui->menu_open->deactivate();
|
|
}
|
|
else
|
|
{
|
|
ui->menu_new->activate();
|
|
ui->menu_open->activate();
|
|
}
|
|
|
|
}
|
|
|
|
if ( nsm && nsm->is_active() )
|
|
{
|
|
if ( ui->menu_new->active() )
|
|
{
|
|
ui->menu_new->deactivate();
|
|
ui->menu_open->deactivate();
|
|
ui->menu_save_as->deactivate();
|
|
}
|
|
}
|
|
|
|
// JUST A TEST
|
|
if ( transport.rolling )
|
|
{
|
|
if ( ui->tabs->value() == ui->pattern_tab )
|
|
ui->pattern_canvas_widget->redraw_playhead();
|
|
else
|
|
if ( ui->tabs->value() == ui->phrase_tab )
|
|
ui->phrase_canvas_widget->redraw_playhead();
|
|
|
|
}
|
|
|
|
ui->transport_state->do_callback();} {}
|
|
}
|
|
|
|
class UI {open
|
|
} {
|
|
decl {Fl_Text_Buffer *sequence_notes_buffer;} {private local
|
|
}
|
|
decl {Fl_Text_Buffer *pattern_notes_buffer;} {private local
|
|
}
|
|
decl {Fl_Text_Buffer *phrase_notes_buffer} {private local
|
|
}
|
|
Function {UI()} {open
|
|
} {
|
|
code {fl_register_images();
|
|
|
|
canvas_background_color = FL_GREEN;
|
|
|
|
playback_mode_menu = NULL;
|
|
|
|
main_window = make_main_window();
|
|
seq_window = make_seq_window();
|
|
|
|
make_randomization_dialog();
|
|
|
|
// make_instrument_edit_dialog();
|
|
|
|
Fl::add_handler( shortcut_handler );
|
|
|
|
// use old focus behavior
|
|
Fl::visible_focus( 0 );
|
|
|
|
// try to fill the screen, but only when the screen is tiny and our window is huge.
|
|
{
|
|
int sx, sy, sw, sh;
|
|
|
|
Fl::screen_xywh( sx, sy, sw, sh );
|
|
|
|
if ( sw < main_window->w() || sh < main_window->h() )
|
|
main_window->resize( sx, sy, sw, sh );
|
|
}
|
|
|
|
Fl::add_timeout( TRANSPORT_POLL_INTERVAL, update_transport );
|
|
|
|
|
|
playlist->signal_new_song.connect( sigc::mem_fun( this, &UI::update_sequence_widgets ) );} {}
|
|
}
|
|
Function {~UI()} {open
|
|
} {
|
|
code {delete seq_window;
|
|
delete main_window;} {}
|
|
}
|
|
Function {run()} {open
|
|
} {
|
|
code {Fl::run();} {}
|
|
}
|
|
Function {load_settings()} {open return_type void
|
|
} {
|
|
code {char *path;
|
|
|
|
asprintf( &path, "%s/%s", config.user_config_dir, "view" );
|
|
|
|
((Fl_Menu_Settings*)menu_bar)->load( menu_bar->find_item( "&View" ), path );
|
|
|
|
free( path );} {}
|
|
}
|
|
Function {save_settings()} {open return_type void
|
|
} {
|
|
code {char *path;
|
|
|
|
asprintf( &path, "%s/%s", config.user_config_dir, "view" );
|
|
|
|
((Fl_Menu_Settings*)menu_bar)->dump( menu_bar->find_item( "&View" ), path );
|
|
|
|
free( path );} {}
|
|
}
|
|
Function {make_main_window()} {open
|
|
} {
|
|
Fl_Window main_window {
|
|
label {Non Sequencer}
|
|
callback {// Ignore escape
|
|
if ( Fl::event() == FL_SHORTCUT && Fl::event_key() == FL_Escape )
|
|
return;
|
|
|
|
if ( maybe_save_song() )
|
|
quit();} open
|
|
xywh {798 131 865 805} type Double color 47 resizable
|
|
code0 {o->color( FL_BACKGROUND_COLOR );} xclass non size_range {700 509 0 0} visible
|
|
} {
|
|
Fl_Group {} {open
|
|
xywh {0 30 865 70} box FLAT_BOX
|
|
} {
|
|
Fl_Value_Input {} {
|
|
label BPM
|
|
callback {transport.set_beats_per_minute( o->value() );}
|
|
xywh {389 47 45 25} labelsize 9 align 1 when 8
|
|
code1 {transport.signal_tempo_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value) ) );}
|
|
code2 {o->value( transport.beats_per_minute );}
|
|
}
|
|
Fl_Value_Input {} {
|
|
callback {transport.set_beats_per_bar( o->value() );}
|
|
xywh {444 47 26 25}
|
|
code0 {transport.signal_bpb_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value) ) );}
|
|
code1 {o->value( transport.beats_per_bar );}
|
|
}
|
|
Fl_Box {} {
|
|
label {/}
|
|
xywh {469 47 19 25}
|
|
}
|
|
Fl_Value_Input {} {
|
|
callback {transport.set_beat_type( o->value() );}
|
|
xywh {489 47 24 25}
|
|
code0 {transport.signal_beat_change.connect( sigc::mem_fun( o, static_cast<int (Fl_Valuator::*)(double)>(&Fl_Valuator::value) ) );}
|
|
code1 {o->value( transport.beat_type );}
|
|
}
|
|
Fl_Pack vmetro_widget {
|
|
label Metronome
|
|
xywh {520 35 336 59} type HORIZONTAL box UP_BOX color 40 selection_color 48 labelsize 33 align 0 resizable
|
|
code0 {\#include "widgets.H"}
|
|
code1 {o->box( FL_FLAT_BOX );}
|
|
class Visual_Metronome
|
|
} {}
|
|
Fl_Pack transport_controls_group {open
|
|
xywh {4 32 156 42} type HORIZONTAL
|
|
code0 {o->spacing( 2 );}
|
|
class Fl_Scalepack
|
|
} {
|
|
Fl_Button play_button {
|
|
label {@>}
|
|
callback {transport.toggle();}
|
|
xywh {10 34 43 38} shortcut 0x20 labeltype ENGRAVED_LABEL
|
|
}
|
|
Fl_Button rec_button {
|
|
label {@circle}
|
|
callback {transport.recording = o->value();
|
|
|
|
|
|
if ( o->value() )
|
|
{
|
|
if ( config.record_mode == NEW )
|
|
{
|
|
pattern *p = new pattern;
|
|
p->length( -1 );
|
|
|
|
pattern_c->grid( p );
|
|
}
|
|
|
|
((pattern*)pattern_c->grid())->record( 0 );
|
|
|
|
o->labelcolor( FL_RED );
|
|
}
|
|
else
|
|
{
|
|
pattern::recording()->record_stop();
|
|
|
|
o->labelcolor( FL_WHITE );
|
|
}}
|
|
xywh {60 34 43 38} type Toggle shortcut 0x80072 selection_color 47 labeltype ENGRAVED_LABEL when 1
|
|
}
|
|
Fl_Button home_button {
|
|
label {@|<}
|
|
callback {transport.locate( 0 );}
|
|
xywh {110 34 43 38} shortcut 0xff50 labeltype ENGRAVED_LABEL
|
|
}
|
|
}
|
|
Fl_Choice record_mode_menu {
|
|
label {&Record Mode}
|
|
callback {if ( ! transport.recording )
|
|
config.record_mode = (record_mode_e)o->value();
|
|
else
|
|
o->value( config.record_mode );} open
|
|
xywh {170 47 100 25} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1
|
|
} {
|
|
MenuItem {} {
|
|
label Merge
|
|
xywh {15 15 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label Overwrite
|
|
xywh {25 25 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label Layer
|
|
xywh {35 35 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label New
|
|
xywh {45 45 40 25}
|
|
}
|
|
}
|
|
Fl_Choice playback_mode_menu {
|
|
label {Playback &Mode} open
|
|
xywh {279 47 100 25} box DOWN_BOX down_box BORDER_BOX color 37 labelsize 9 align 1
|
|
} {
|
|
MenuItem {} {
|
|
label Pattern
|
|
callback {song.play_mode = PATTERN;}
|
|
xywh {5 5 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label Sequence
|
|
callback {song.play_mode = SEQUENCE;}
|
|
xywh {15 15 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label Trigger
|
|
callback {song.play_mode = TRIGGER;}
|
|
xywh {25 25 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label Queue
|
|
callback {song.play_mode = QUEUE;}
|
|
xywh {0 0 40 24}
|
|
}
|
|
}
|
|
}
|
|
Fl_Tabs tabs {
|
|
callback {((Fl_Group*)o->value())->child( 0 )->take_focus();
|
|
|
|
ui->pan_indicators->show();
|
|
|
|
if ( o->value() == pattern_tab )
|
|
pattern_canvas_widget->handle_pan();
|
|
else if ( o->value() == phrase_tab )
|
|
phrase_canvas_widget->handle_pan();
|
|
|
|
if ( o->value() != pattern_tab )
|
|
{
|
|
if ( o->value() != phrase_tab )
|
|
ui->pan_indicators->hide();
|
|
edit_menu->deactivate();
|
|
}
|
|
else
|
|
{
|
|
edit_menu->activate();
|
|
}
|
|
|
|
menu_bar->redraw();} open
|
|
xywh {0 79 865 698} box BORDER_BOX color 47 labeltype SHADOW_LABEL labelsize 19 when 1 resizable
|
|
code0 {canvas_background_color = fl_rgb_color( 18, 18, 18 );}
|
|
} {
|
|
Fl_Group sequence_tab {
|
|
label Sequence open
|
|
xywh {0 102 865 674} box FLAT_BOX color 37 hide resizable
|
|
code0 {update_sequence_widgets();}
|
|
} {
|
|
Fl_Group {} {open
|
|
xywh {10 125 233 502} labelsize 12
|
|
} {
|
|
Fl_Browser playlist_browser {
|
|
label Playlist
|
|
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
|
|
code0 {static int widths[] = { 40, 30, 0 };}
|
|
code1 {o->column_widths( widths ); o->column_char( '\\t' );}
|
|
code2 {o->value( 1 );}
|
|
}
|
|
Fl_Button sequence_phrase_delete_button {
|
|
label Delete
|
|
callback {int val = playlist_browser->value();
|
|
|
|
if ( val > 1 )
|
|
{
|
|
// playlist_browser->value( playlist_browser->value() + 1 );
|
|
|
|
playlist->remove( val - 2 );
|
|
|
|
update_sequence_widgets();
|
|
|
|
if ( ! playlist_browser->value() )
|
|
playlist_browser->value( playlist_browser->size() );
|
|
}}
|
|
xywh {14 566 73 25} shortcut 0xffff color 88 labelcolor 23
|
|
}
|
|
Fl_Button sequence_phrase_up_button {
|
|
label Up
|
|
callback {if ( playlist_browser->value() > 2 )
|
|
{
|
|
playlist->move( playlist_browser->value() - 2, UP );
|
|
playlist_browser->value( playlist_browser->value() - 1 );
|
|
update_sequence_widgets();
|
|
}}
|
|
xywh {97 566 65 25} shortcut 0xffbf
|
|
}
|
|
Fl_Button sequence_phrase_down_button {
|
|
label Down
|
|
callback {if ( playlist_browser->value() > 1 )
|
|
{
|
|
playlist->move( playlist_browser->value() - 2, DOWN );
|
|
playlist_browser->value( playlist_browser->value() + 1 );
|
|
update_sequence_widgets();
|
|
}}
|
|
xywh {169 566 74 25} shortcut 0xffc0
|
|
}
|
|
Fl_Menu_Button sequence_phrase_choice {
|
|
label {Insert Phrase}
|
|
callback {playlist->insert( playlist_browser->value() - 1, o->value() + 1 );
|
|
|
|
update_sequence_widgets();
|
|
|
|
int val = playlist_browser->value();
|
|
|
|
if ( val )
|
|
playlist_browser->value( playlist_browser->value() + 1 );
|
|
else
|
|
playlist_browser->value( playlist_browser->size() );} open
|
|
xywh {11 597 232 30} color 63
|
|
} {}
|
|
}
|
|
Fl_Input sequence_name_field {
|
|
label {name:}
|
|
callback {playlist->name( o->value() );}
|
|
xywh {91 740 158 26} color 36 align 20 when 1 textcolor 32
|
|
}
|
|
Fl_Light_Button detach_button {
|
|
label Detach
|
|
callback {if ( o->value() )
|
|
{
|
|
Fl_Group *g = seq_detached_group;
|
|
seq_window->show();
|
|
g->add( sequence_tab );
|
|
sequence_tab->resize( g->x(), g->y(), g->w(), g->h() );
|
|
tabs->do_callback();
|
|
main_window->redraw();
|
|
}
|
|
else
|
|
{
|
|
seq_window->hide();
|
|
tabs->insert( (Fl_Widget&)*sequence_tab, 0 );
|
|
sequence_tab->resize( pattern_tab->x(), pattern_tab->y(), pattern_tab->w(), pattern_tab->h() );
|
|
tabs->do_callback();
|
|
}}
|
|
xywh {7 740 78 26}
|
|
}
|
|
Fl_Text_Editor sequence_notes_edit {
|
|
label {Notes:}
|
|
callback {playlist->notes( o->buffer()->text() );}
|
|
xywh {254 691 606 73} selection_color 48 labelsize 12 align 5 textcolor 94
|
|
code0 {o->buffer( sequence_notes_buffer = new Fl_Text_Buffer );}
|
|
}
|
|
Fl_Box triggers_widget {
|
|
label Patterns
|
|
xywh {253 125 607 549} color 48 align 1 resizable
|
|
code0 {o->color( FL_BACKGROUND_COLOR );}
|
|
class Triggers
|
|
}
|
|
Fl_Group progress_group {
|
|
callback {if ( ! o->visible_r() )
|
|
return;
|
|
|
|
phrase *p = phrase::phrase_by_number( playlist->playing() );
|
|
|
|
if ( p )
|
|
phrase_progress->value( p->index() / (double)p->length() );
|
|
|
|
if ( playlist->length() )
|
|
sequence_progress->value( playlist->index() / (double)playlist->length() );} open
|
|
xywh {10 656 233 66}
|
|
} {
|
|
Fl_Slider phrase_progress {
|
|
label Phrase
|
|
xywh {10 656 233 24} type Horizontal labelsize 12 align 1
|
|
}
|
|
Fl_Slider sequence_progress {
|
|
label Sequence
|
|
callback {transport.locate( (tick_t)((double)playlist->length() * o->value()) );}
|
|
xywh {10 698 233 24} type Horizontal labelsize 12 align 1
|
|
}
|
|
}
|
|
}
|
|
Fl_Group phrase_tab {
|
|
label Phrase open
|
|
xywh {0 102 865 674} box FLAT_BOX color 47 hide
|
|
code0 {update_phrase_widgets();}
|
|
} {
|
|
Fl_Box phrase_canvas_widget {
|
|
label Phrase
|
|
xywh {1 103 863 587} box FLAT_BOX color 37 labelsize 100 align 16 resizable
|
|
code0 {o->set_canvas( phrase_c );}
|
|
code1 {phrase_c->signal_pan.connect( sigc::mem_fun( phrase_canvas_widget, &O_Canvas::handle_pan ) );}
|
|
class O_Canvas
|
|
}
|
|
Fl_Group {} {open
|
|
xywh {5 697 856 77} box FLAT_BOX color 47
|
|
} {
|
|
Fl_Input phrase_name_field {
|
|
label {name:}
|
|
callback {phrase_c->grid()->name( strdup( o->value() ) );
|
|
|
|
// if the name changed..
|
|
update_sequence_widgets();}
|
|
xywh {5 704 155 24} box ROUNDED_BOX color 49 labelfont 2 labelcolor 55 align 20 textcolor 32
|
|
code0 {o->up_box( FL_ROUNDED_BOX );}
|
|
class Fl_Sometimes_Input
|
|
}
|
|
Fl_Spinner phrase_number_spinner {
|
|
label {Phrase:}
|
|
callback {phrase *p = ((phrase *)phrase_c->grid())->by_number( o->value() );
|
|
|
|
if ( p )
|
|
phrase_c->grid( p );
|
|
|
|
o->maximum( phrase::phrases() );}
|
|
xywh {165 704 55 24} color 36 labelsize 9 align 1 when 1
|
|
}
|
|
Fl_Light_Button phrase_mute_button {
|
|
label Mute
|
|
xywh {5 740 93 23} color 37 hide
|
|
}
|
|
Fl_Light_Button phrase_solo_button {
|
|
label Solo
|
|
xywh {111 740 87 23} color 37 hide
|
|
}
|
|
Fl_Text_Editor phrase_notes_edit {
|
|
label {Notes:}
|
|
callback {phrase_c->grid()->notes( o->buffer()->text() );}
|
|
xywh {235 709 620 58} selection_color 48 labelsize 12 textcolor 94 resizable
|
|
code0 {o->buffer( phrase_notes_buffer = new Fl_Text_Buffer );}
|
|
}
|
|
}
|
|
}
|
|
Fl_Group pattern_tab {
|
|
label Pattern open
|
|
xywh {0 102 865 674} box FLAT_BOX color 47
|
|
code0 {update_pattern_widgets();}
|
|
} {
|
|
Fl_Box pattern_canvas_widget {
|
|
label Pattern selected
|
|
xywh {1 103 863 587} box FLAT_BOX color 37 labelsize 100 align 16 resizable
|
|
code0 {\#include "draw.H"}
|
|
code1 {o->set_canvas( pattern_c );}
|
|
code2 {\#include "input.H"}
|
|
code3 {pattern_c->signal_pan.connect( sigc::mem_fun( pattern_canvas_widget, &O_Canvas::handle_pan ) );}
|
|
class O_Canvas
|
|
}
|
|
Fl_Group {} {open
|
|
xywh {0 694 862 78} box FLAT_BOX color 47
|
|
} {
|
|
Fl_Input pattern_name_field {
|
|
label {name:}
|
|
callback {pattern_c->grid()->name( strdup( o->value() ) );}
|
|
xywh {5 704 155 24} box ROUNDED_BOX color 49 align 20 when 1 textfont 2 textcolor 55
|
|
code0 {o->up_box( FL_ROUNDED_BOX );}
|
|
class Fl_Sometimes_Input
|
|
}
|
|
Fl_Spinner pattern_number_spinner {
|
|
label {Pattern:}
|
|
callback {pattern *p = ((pattern *)pattern_c->grid())->by_number( o->value() );
|
|
|
|
if ( p )
|
|
pattern_c->grid( p );
|
|
|
|
o->maximum( pattern::patterns() );}
|
|
xywh {165 704 55 24} color 36 labelsize 9 align 1 when 1
|
|
code0 {o->maximum( 1 );}
|
|
code1 {// pattern::signal_create_destroy.connect( sigc::mem_fun( o, static_cast<void (Fl_Spinner::*)(double)>(&Fl_Spinner::maximum) ) );}
|
|
}
|
|
Fl_Light_Button pattern_mute_button {
|
|
label Mute
|
|
callback {Grid *g = pattern_c->grid();
|
|
|
|
g->mode( g->mode() == MUTE ? PLAY : MUTE );
|
|
|
|
o->value( g->mode() == MUTE );
|
|
|
|
pattern_solo_button->value( 0 );}
|
|
xywh {10 738 65 25} type Normal color 37
|
|
}
|
|
Fl_Light_Button pattern_solo_button {
|
|
label Solo
|
|
callback {Grid *g = pattern_c->grid();
|
|
|
|
g->mode( g->mode() == SOLO ? PLAY : SOLO );
|
|
|
|
o->value( g->mode() == SOLO );
|
|
|
|
pattern_mute_button->value( 0 );}
|
|
xywh {80 738 65 25} type Normal color 37
|
|
}
|
|
Fl_Text_Editor pattern_notes_edit {
|
|
label {Notes:}
|
|
callback {pattern_c->grid()->notes( o->buffer()->text() );}
|
|
xywh {230 713 227 48} selection_color 48 labelsize 12 textcolor 94 resizable
|
|
code0 {o->buffer( pattern_notes_buffer = new Fl_Text_Buffer );}
|
|
}
|
|
Fl_Group pattern_settings_group {open
|
|
xywh {458 694 400 78}
|
|
} {
|
|
Fl_Spinner pattern_channel_spinner {
|
|
label Channel
|
|
callback {((pattern *)pattern_c->grid())->channel( o->value() - 1 );}
|
|
xywh {815 700 40 24} color 36 when 1
|
|
code0 {\#include "../pattern.H"}
|
|
code1 {o->maximum( 16 );}
|
|
}
|
|
Fl_Spinner pattern_port_spinner {
|
|
label Port
|
|
callback {((pattern *)pattern_c->grid())->port( o->value() - 1 );}
|
|
xywh {815 734 40 24} color 36 when 1
|
|
code0 {o->maximum( 16 );}
|
|
}
|
|
Fl_Output mapping_text {
|
|
label Mapping
|
|
xywh {464 734 145 24} align 20
|
|
}
|
|
Fl_Menu_Button mapping_menu {
|
|
label {@>}
|
|
callback {mapping_text->value( o->text() );
|
|
|
|
|
|
char picked[80];
|
|
mapping_menu->item_pathname(picked, sizeof(picked)-1 );
|
|
|
|
if ( 0 == strncmp( picked, "Instrument", strlen( "Instrument" ) ) )
|
|
{
|
|
((pattern*)pattern_c->grid())->mapping.open( Mapping::INSTRUMENT, o->text() );
|
|
|
|
pattern_c->changed_mapping();
|
|
|
|
pattern_key_combo->deactivate();
|
|
}
|
|
else
|
|
if ( 0 == strncmp( picked, "Scale", strlen( "Scale" ) ) )
|
|
{
|
|
((pattern*)pattern_c->grid())->mapping.open( Mapping::SCALE, o->text() );
|
|
|
|
pattern_c->changed_mapping();
|
|
|
|
pattern_key_combo->activate();
|
|
}} open
|
|
xywh {609 734 30 24} labeltype NO_LABEL
|
|
code0 {update_mapping_menu();}
|
|
} {
|
|
Submenu mapping_scale_menu {
|
|
label Scale open
|
|
xywh {25 25 74 25}
|
|
} {}
|
|
Submenu mapping_instrument_menu {
|
|
label Instrument open
|
|
xywh {10 10 74 25}
|
|
} {}
|
|
}
|
|
Fl_Choice pattern_key_combo {
|
|
label {&Key}
|
|
callback {((pattern*)pattern_c->grid())->mapping.key( o->value() );
|
|
|
|
pattern_c->changed_mapping();}
|
|
xywh {674 734 75 24} down_box BORDER_BOX when 1
|
|
} {
|
|
MenuItem {} {
|
|
label C
|
|
xywh {30 30 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {C\#/Db}
|
|
xywh {40 40 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label D
|
|
xywh {50 50 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {D\#/Eb}
|
|
xywh {60 60 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label E
|
|
xywh {70 70 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label F
|
|
xywh {80 80 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {F\#/Gb}
|
|
xywh {90 90 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label G
|
|
xywh {100 100 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {G\#}
|
|
xywh {110 110 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label A
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {A\#/Bb}
|
|
xywh {10 10 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label B
|
|
xywh {20 20 40 25}
|
|
}
|
|
}
|
|
Fl_Choice pattern_note_combo {
|
|
label {&Note 1/}
|
|
callback {((pattern*)pattern_c->grid())->note( atoi( o->menu()[ o->value() ].text ));}
|
|
xywh {704 700 45 24} down_box BORDER_BOX when 1
|
|
} {
|
|
MenuItem {} {
|
|
label 1
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 2
|
|
xywh {10 10 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 4
|
|
xywh {20 20 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 8
|
|
xywh {30 30 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 16
|
|
xywh {40 40 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 32
|
|
xywh {50 50 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 64
|
|
xywh {60 60 40 25} divider
|
|
}
|
|
MenuItem {} {
|
|
label 3
|
|
xywh {60 60 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 6
|
|
xywh {70 70 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 12
|
|
xywh {80 80 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 24
|
|
xywh {90 90 40 25}
|
|
}
|
|
}
|
|
Fl_Choice pattern_res_combo {
|
|
label {&Resolution 1/}
|
|
callback {pattern_c->grid()->resolution( atoi( o->menu()[ o->value() ].text ));}
|
|
xywh {584 700 55 24} down_box BORDER_BOX when 1
|
|
} {
|
|
MenuItem {} {
|
|
label 4
|
|
xywh {30 30 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 8
|
|
xywh {40 40 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 16
|
|
xywh {50 50 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 32
|
|
xywh {60 60 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 64
|
|
xywh {80 80 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 128
|
|
xywh {90 90 40 25} divider
|
|
}
|
|
MenuItem {} {
|
|
label 3
|
|
xywh {70 70 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 6
|
|
xywh {80 80 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 12
|
|
xywh {90 90 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 24
|
|
xywh {100 100 40 25}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Fl_Group {} {open
|
|
xywh {0 776 865 31}
|
|
} {
|
|
Fl_Box status {
|
|
label status
|
|
xywh {1 776 782 31} box UP_BOX align 84
|
|
code0 {o->label( NULL );}
|
|
}
|
|
Fl_Box transport_state {
|
|
label state
|
|
callback {const char *s = "INVALID";
|
|
|
|
if ( transport.master )
|
|
s = "Master";
|
|
else if ( transport.valid )
|
|
s = "Slave";
|
|
|
|
if ( s != o->label() )
|
|
{
|
|
o->label( s );
|
|
if ( ! strcmp( s, "INVALID" ) )
|
|
o->color( fl_darker( FL_RED ) );
|
|
else
|
|
o->color( fl_darker( FL_GREEN ) );
|
|
}}
|
|
xywh {783 776 82 31} box THIN_UP_BOX align 64
|
|
}
|
|
}
|
|
Fl_Group pan_indicators {open
|
|
xywh {370 692 120 20}
|
|
} {
|
|
Fl_Box scroll_up_box {
|
|
label {@2<}
|
|
xywh {400 694 30 18}
|
|
}
|
|
Fl_Box scroll_down_box {
|
|
label {@2>}
|
|
xywh {430 694 30 18}
|
|
}
|
|
Fl_Box scroll_left_box {
|
|
label {@<}
|
|
xywh {370 692 30 18} hide
|
|
}
|
|
Fl_Box scroll_right_box {
|
|
label {@>}
|
|
xywh {460 692 30 18} hide
|
|
}
|
|
}
|
|
Fl_Group {} {open
|
|
xywh {0 0 865 31}
|
|
} {
|
|
Fl_Menu_Bar menu_bar {open
|
|
xywh {0 0 865 30} color 47
|
|
} {
|
|
Submenu {} {
|
|
label {&File} open
|
|
xywh {0 0 100 20} color 37
|
|
} {
|
|
MenuItem menu_new {
|
|
label {&New}
|
|
callback {if ( maybe_save_song() )
|
|
{
|
|
init_song();
|
|
|
|
// Sync the GUI.
|
|
update_pattern_widgets();
|
|
update_sequence_widgets();
|
|
update_phrase_widgets();
|
|
|
|
|
|
gui_status( "New song." );
|
|
}}
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem menu_open {
|
|
label {&Open}
|
|
callback {char *name = fl_file_chooser( "Open File", "Non Files (*.non)", NULL, 0 );
|
|
|
|
if ( name )
|
|
{
|
|
if ( ! load_song( name ) )
|
|
fl_alert( "Could not load song!" );
|
|
else
|
|
gui_status( "Song opened." );
|
|
|
|
update_sequence_widgets();
|
|
update_pattern_widgets();
|
|
update_phrase_widgets();
|
|
|
|
playback_mode_menu->value( song.play_mode );
|
|
playback_mode_menu->redraw();
|
|
}}
|
|
xywh {0 0 40 25} shortcut 0x4006f color 37
|
|
}
|
|
MenuItem menu_save {
|
|
label {&Save}
|
|
callback {save_dialog( song.filename );}
|
|
xywh {0 0 40 25} shortcut 0x40073 color 37 deactivate
|
|
code0 {song.signal_dirty.connect( sigc::mem_fun( o, &Fl_Menu_Item::activate ) );}
|
|
code1 {song.signal_clean.connect( sigc::mem_fun( o, &Fl_Menu_Item::deactivate ) );}
|
|
}
|
|
MenuItem menu_save_as {
|
|
label {Save &As}
|
|
callback {save_dialog( NULL );}
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {&Import}
|
|
callback {char *name = fl_file_chooser( "MIDI Import", "MIDI Files (*.mid)", NULL, 0 );
|
|
|
|
if ( ! name )
|
|
return;
|
|
|
|
smf f;
|
|
|
|
if ( ! f.open( name, smf::READ ) )
|
|
{
|
|
fl_message( "could not open file" );
|
|
return;
|
|
}
|
|
|
|
f.read_header();
|
|
|
|
switch ( f.format() )
|
|
{
|
|
case 0:
|
|
if ( ! pattern::import( &f, 0 ) )
|
|
fl_message( "Error importing MIDI" );
|
|
break;
|
|
case 1: case 2:
|
|
{
|
|
char **sa = f.track_listing();
|
|
|
|
if ( sa && *sa )
|
|
{
|
|
List_Chooser tc( "Select tracks to import:", "Import" );
|
|
|
|
char *s;
|
|
for ( int i = 0; (s = sa[i]); ++i )
|
|
{
|
|
tc.add( s );
|
|
free( s );
|
|
}
|
|
|
|
free( sa );
|
|
|
|
tc.show();
|
|
|
|
while( tc.shown() )
|
|
Fl::wait();
|
|
|
|
int n = 0;
|
|
for ( int i = 1; i <= tc.browser->size(); ++i )
|
|
{
|
|
if ( tc.browser->selected( i ) )
|
|
{
|
|
if ( pattern::import( &f , i - 1 ) )
|
|
++n;
|
|
else
|
|
WARNING( "error importing track %d", i - 1 );
|
|
}
|
|
|
|
}
|
|
// fl_message( "%d patterns imported.", n );
|
|
gui_status( "Imported %d tracks as patterns", n );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}}
|
|
xywh {0 0 40 25}
|
|
code0 {\#include "../smf.H"}
|
|
}
|
|
MenuItem {} {
|
|
label {&Export}
|
|
callback {// Fl_File_Chooser::custom_filter_label = "*.mid";
|
|
|
|
Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "MIDI Files (*.mid)", Fl_File_Chooser::CREATE, "MIDI Export" );
|
|
|
|
fc->show();
|
|
|
|
// wait for user to make a choice
|
|
while( fc->shown() )
|
|
Fl::wait();
|
|
|
|
if ( ! fc->value() )
|
|
return;
|
|
|
|
if ( tabs->value() == pattern_tab )
|
|
((pattern*)pattern_c->grid())->save( fc->value() );}
|
|
xywh {0 0 40 25}
|
|
code0 {\#include <FL/Fl_File_Chooser.H>}
|
|
}
|
|
MenuItem {} {
|
|
label {&Quit}
|
|
callback {main_window->do_callback();}
|
|
xywh {0 0 40 25} shortcut 0x40071 color 37
|
|
}
|
|
}
|
|
Submenu edit_menu {
|
|
label {&Edit} open
|
|
xywh {0 0 74 25} color 37
|
|
} {
|
|
MenuItem {} {
|
|
label {&Events}
|
|
callback {event_editor( pattern_c->grid() );}
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {&Randomization Settings}
|
|
callback {randomization_dialog->show();}
|
|
xywh {0 0 40 25}
|
|
}
|
|
}
|
|
Submenu {} {
|
|
label {&View} open
|
|
xywh {10 10 74 25} color 37
|
|
} {
|
|
MenuItem {} {
|
|
label {&Metronome}
|
|
callback {int val = o->menu()[ o->value() ].value();
|
|
|
|
if ( val )
|
|
vmetro_widget->show();
|
|
else
|
|
vmetro_widget->hide();}
|
|
xywh {0 0 40 25} type Toggle value 1
|
|
}
|
|
MenuItem {} {
|
|
label {&Compacted}
|
|
callback {int val = o->menu()[ o->value() ].value();
|
|
|
|
pattern_c->row_compact( val ? Canvas::ON : Canvas::OFF );
|
|
|
|
pattern_canvas_widget->redraw();}
|
|
xywh {10 10 40 25} type Toggle value 1
|
|
}
|
|
MenuItem {} {
|
|
label {&Follow Playhead}
|
|
callback {int val = o->menu()[ o->value() ].value();
|
|
|
|
config.follow_playhead = val ? true : false;}
|
|
xywh {10 10 40 25} type Toggle value 1
|
|
}
|
|
Submenu {} {
|
|
label {Note Shape} open
|
|
xywh {0 0 74 24}
|
|
} {
|
|
MenuItem {} {
|
|
label Box
|
|
callback {pattern::note_shape = BOX;
|
|
pattern_canvas_widget->redraw();}
|
|
xywh {0 0 40 24} type Radio
|
|
}
|
|
MenuItem {} {
|
|
label Square
|
|
callback {pattern::note_shape = SQUARE;
|
|
pattern_canvas_widget->redraw();}
|
|
xywh {0 0 40 24} type Radio value 1
|
|
}
|
|
}
|
|
MenuItem {} {
|
|
label {&Theme}
|
|
callback {fl_theme_chooser();}
|
|
xywh {0 0 40 24}
|
|
}
|
|
}
|
|
Submenu {} {
|
|
label {&Help} open
|
|
xywh {100 0 74 25} color 37
|
|
} {
|
|
MenuItem {} {
|
|
label {&Keys}
|
|
callback {show_help_dialog( "KEYS" );}
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label {&Manual}
|
|
callback {show_help_dialog( "MANUAL" );}
|
|
xywh {10 10 40 25} divider
|
|
}
|
|
MenuItem {} {
|
|
label {&About}
|
|
callback {About_Dialog ab( PIXMAP_PATH "/non-sequencer/icon-256x256.png" );
|
|
|
|
ab.logo_box->label( VERSION );
|
|
|
|
ab.title->label( "The Non Sequencer" );
|
|
|
|
ab.copyright->label( "Copyright (C) 2007-2012 Jonathan Moore Liles" );
|
|
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" );
|
|
|
|
ab.website_url->label( "http://non-sequencer.tuxfamily.org" );
|
|
|
|
ab.run();}
|
|
xywh {0 0 40 25} color 37
|
|
code0 {\#include "../non.H"}
|
|
}
|
|
}
|
|
}
|
|
Fl_Button sm_indicator {
|
|
label SM
|
|
xywh {825 8 35 15} box ROUNDED_BOX down_box ROUNDED_BOX color 46 selection_color 93 labelfont 3 labelcolor 39 deactivate
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Function {make_seq_window()} {open
|
|
} {
|
|
Fl_Window seq_window {
|
|
label {Non Sequencer - Sequence}
|
|
callback {sequence_tab->activate();
|
|
o->hide();
|
|
detach_button->value( 0 );} open
|
|
xywh {681 189 876 675} type Double hide resizable
|
|
} {
|
|
Fl_Group seq_detached_group {open
|
|
xywh {0 0 876 675} resizable
|
|
} {}
|
|
}
|
|
}
|
|
Function {make_randomization_dialog()} {} {
|
|
Fl_Window randomization_dialog {
|
|
label {Randomization Settings} open
|
|
xywh {656 39 340 95} type Double hide
|
|
code0 {// feel->value( )}
|
|
code1 {probability->value( song.random.probability );} non_modal
|
|
} {
|
|
Fl_Choice feel {
|
|
label {Feel: 1/}
|
|
callback {song.random.feel = atoi( o->menu()[ find_numeric_menu_item( o->menu(), o->value() ) ].text );} open
|
|
xywh {67 55 50 24} down_box BORDER_BOX
|
|
} {
|
|
MenuItem {} {
|
|
label 4
|
|
xywh {10 10 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 8
|
|
xywh {0 0 40 25}
|
|
}
|
|
MenuItem {} {
|
|
label 16
|
|
xywh {10 10 40 25}
|
|
}
|
|
}
|
|
Fl_Box {} {
|
|
label {Randomization Settings}
|
|
xywh {10 15 321 28} box ROUNDED_BOX color 94 labelsize 22 labelcolor 39
|
|
}
|
|
Fl_Counter probability {
|
|
label Probability
|
|
callback {song.random.probability = o->value();}
|
|
xywh {216 53 112 26} type Simple align 4 when 4 minimum 0 maximum 1 step 0.01
|
|
}
|
|
}
|
|
}
|
|
Function {update_pattern_widgets()} {open
|
|
} {
|
|
code {if ( ! pattern_settings_group )
|
|
return;
|
|
|
|
pattern *g = (pattern *)pattern_c->grid();
|
|
|
|
pattern_number_spinner->value( g->number() );
|
|
pattern_name_field->value( g->name() );
|
|
pattern_channel_spinner->value( 1 + g->channel() );
|
|
pattern_port_spinner->value( 1 + g->port() );
|
|
pattern_solo_button->value( g->mode() == SOLO );
|
|
pattern_mute_button->value( g->mode() == MUTE );
|
|
|
|
if ( g->mapping.key() == -1 )
|
|
pattern_key_combo->deactivate();
|
|
else
|
|
{
|
|
pattern_key_combo->activate();
|
|
pattern_key_combo->value( g->mapping.key() );
|
|
}
|
|
|
|
mapping_text->value( g->mapping.name() );
|
|
|
|
|
|
|
|
pattern_note_combo->value( find_numeric_menu_item( menu_pattern_note_combo, g->note() ));
|
|
pattern_res_combo->value( find_numeric_menu_item( menu_pattern_res_combo, g->resolution() ));
|
|
|
|
if ( g->notes() )
|
|
pattern_notes_buffer->text( g->notes() );
|
|
else
|
|
pattern_notes_buffer->text( strdup( "" ) );} {}
|
|
}
|
|
Function {update_phrase_widgets()} {} {
|
|
code {phrase *g = (phrase *)phrase_c->grid();
|
|
|
|
if ( ! g )
|
|
return;
|
|
|
|
g->viewport.y = 0;
|
|
g->viewport.h = pattern::patterns();
|
|
phrase_c->resize_grid();
|
|
phrase_c->changed_mapping();
|
|
phrase_number_spinner->value( g->number() );
|
|
phrase_name_field->value( g->name() );
|
|
phrase_solo_button->value( g->mode() == SOLO );
|
|
phrase_mute_button->value( g->mode() == MUTE );
|
|
|
|
if ( g->notes() )
|
|
phrase_notes_buffer->text( g->notes() );
|
|
else
|
|
phrase_notes_buffer->text( strdup( "" ) );} {}
|
|
}
|
|
Function {update_sequence_widgets()} {open
|
|
} {
|
|
code {if ( playlist->notes() )
|
|
sequence_notes_buffer->text( playlist->notes() );
|
|
else
|
|
sequence_notes_buffer->text( strdup( "" ) );
|
|
|
|
sequence_name_field->value( playlist->name() );
|
|
|
|
sequence_phrase_choice->clear();
|
|
|
|
for ( int i = 1; i <= phrase::phrases(); i++ )
|
|
{
|
|
phrase *p = phrase::phrase_by_number( i );
|
|
|
|
if ( p )
|
|
sequence_phrase_choice->add( p->name() );
|
|
}
|
|
|
|
|
|
Fl_Browser *o = playlist_browser;
|
|
|
|
int val = o->value();
|
|
|
|
o->clear();
|
|
|
|
char *s = playlist->dump();
|
|
|
|
char *l = strtok( s, "\\n" );
|
|
|
|
o->add( "@b@C2Bar\\t@b@C2\#\\t@b@C2Name" );
|
|
|
|
if ( ! l )
|
|
return;
|
|
|
|
o->add( l );
|
|
|
|
while ( ( l = strtok( NULL, "\\n" ) ) )
|
|
{
|
|
o->add( l );
|
|
}
|
|
|
|
o->value( val );
|
|
|
|
free( s );
|
|
|
|
|
|
if ( playback_mode_menu )
|
|
playback_mode_menu->value( song.play_mode );} {}
|
|
}
|
|
Function {update_mapping_menu()} {open
|
|
} {
|
|
code {char **sa = Instrument::listing();
|
|
|
|
if ( sa )
|
|
{
|
|
|
|
for ( int i = 0; sa[i]; i++ )
|
|
{
|
|
char pat[512];
|
|
snprintf( pat, 512, "Instrument/%s", sa[i] );
|
|
mapping_menu->add( pat, 0, 0, 0, 0 );
|
|
free( sa[i] );
|
|
}
|
|
free( sa );
|
|
}
|
|
|
|
sa = Scale::listing();
|
|
for ( int i = 0; sa[i]; i++ )
|
|
{
|
|
char pat[512];
|
|
snprintf( pat, 512, "Scale/%s", sa[i] );
|
|
mapping_menu->add( pat, 0, 0, 0, 0 );
|
|
free( sa[i] );
|
|
}
|
|
free( sa );} {}
|
|
}
|
|
Function {update_canvas_widgets()} {return_type {static void}
|
|
} {
|
|
code {if ( pattern_c->grid() )
|
|
ui->update_pattern_widgets();
|
|
|
|
if ( phrase_c->grid() )
|
|
ui->update_phrase_widgets();} {}
|
|
}
|
|
Function {find_numeric_menu_item( const Fl_Menu_Item *menu, int n )} {return_type {static int}
|
|
} {
|
|
code {for ( unsigned int i = 0; menu[i].text; i++ )
|
|
{
|
|
if ( atoi( menu[i].text ) == n )
|
|
return i;
|
|
}
|
|
|
|
return 0;} {}
|
|
}
|
|
Function {save_dialog( const char *name )} {open return_type void
|
|
} {
|
|
code {if ( ! name )
|
|
{
|
|
|
|
Fl_File_Chooser *fc = new Fl_File_Chooser( ".", "Non Sequences (*.non)", Fl_File_Chooser::CREATE, "Save sequence" );
|
|
|
|
fc->show();
|
|
|
|
// wait for user to make a choice
|
|
while( fc->shown() )
|
|
Fl::wait();
|
|
|
|
if ( ! fc->value() )
|
|
return;
|
|
|
|
name = fc->value();
|
|
}
|
|
|
|
if ( ! save_song( name ) )
|
|
fl_alert( "Could not save song" );
|
|
else
|
|
gui_status( "Saved." );} {}
|
|
}
|
|
Function {show_help_dialog( const char *file )} {return_type void
|
|
} {
|
|
code {char pat[256];
|
|
|
|
snprintf( pat, 256, "file://%s/non-sequencer/%s.html", DOCUMENT_PATH, file );
|
|
|
|
open_url( pat );} {}
|
|
}
|
|
Function {maybe_save_song()} {open return_type bool
|
|
} {
|
|
code {if ( song.dirty() )
|
|
{
|
|
int c = fl_choice( "Song has been modified since last save. What shall I do?", "&Cancel", "&Save", "&Discard" );
|
|
|
|
switch ( c )
|
|
{
|
|
case 0:
|
|
return false;
|
|
case 1:
|
|
/* SAVE */
|
|
save_dialog( song.filename );
|
|
break;
|
|
case 2:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return true;} {}
|
|
}
|
|
Function {switch_to_pattern( int n )} {return_type void
|
|
} {
|
|
code {pattern *p = pattern::pattern_by_number( n );
|
|
|
|
if ( p )
|
|
{
|
|
|
|
|
|
|
|
tabs->value( pattern_tab );
|
|
|
|
pattern_canvas_widget->take_focus();
|
|
|
|
pattern_c->grid( p );
|
|
|
|
// update_pattern_widgets();
|
|
}} {}
|
|
}
|
|
Function {edit_instrument_row( Instrument *i, int n )} {open return_type void
|
|
} {
|
|
code {Instrument_Editor ie;
|
|
|
|
ie.set( i, n );
|
|
|
|
ie.run();} {}
|
|
}
|
|
}
|
|
|
|
Function {shortcut_handler( int e )} {return_type int
|
|
} {
|
|
code {if ( e != FL_SHORTCUT )
|
|
return 0;
|
|
|
|
|
|
// this is for mainwindow shortcuts only, ignore all other windows.
|
|
if ( Fl::first_window() != ui->main_window )
|
|
return 0;
|
|
|
|
int processed = 0;
|
|
|
|
// shortcuts that don't fit anywhere else (widgets that don't take shortcuts, etc.)
|
|
|
|
\#define KEY(key) ((Fl::test_shortcut( (key) )))
|
|
|
|
processed = 1;
|
|
if KEY( FL_ALT + 's' )
|
|
{
|
|
ui->tabs->value( ui->sequence_tab );
|
|
ui->tabs->do_callback();
|
|
}
|
|
else
|
|
if KEY( FL_ALT + 'a' )
|
|
{
|
|
ui->tabs->value( ui->phrase_tab );
|
|
ui->tabs->do_callback();
|
|
}
|
|
else
|
|
if KEY( FL_ALT + 'p' )
|
|
{
|
|
ui->tabs->value( ui->pattern_tab );
|
|
ui->tabs->do_callback();
|
|
}
|
|
else
|
|
if KEY( FL_ALT + 'c' )
|
|
ui->pattern_channel_spinner->take_focus();
|
|
else
|
|
if KEY( FL_ALT + 'o' )
|
|
ui->pattern_port_spinner->take_focus();
|
|
else
|
|
if KEY( FL_ALT + 'i' )
|
|
ui->mapping_menu->take_focus();
|
|
else
|
|
processed = 0;
|
|
|
|
return processed;} {}
|
|
}
|
|
|
|
class O_Canvas {open : {public Fl_Widget}
|
|
} {
|
|
decl {Canvas *_c;} {private local
|
|
}
|
|
decl {bool _border_drawn;} {private local
|
|
}
|
|
Function {O_Canvas( int X, int Y, int W, int H, const char*L=0) : Fl_Widget(X,Y,W,H,L)} {open
|
|
} {
|
|
code {_c = NULL;
|
|
_border_drawn = false;
|
|
box(FL_FLAT_BOX);} {}
|
|
}
|
|
Function {handle( int m )} {open return_type int
|
|
} {
|
|
code {// Accept focus if offered.
|
|
if ( m == FL_FOCUS || m == FL_UNFOCUS )
|
|
{
|
|
_border_drawn = false;
|
|
redraw_playhead();
|
|
return 1;
|
|
}
|
|
|
|
// Hack in click-to-focus
|
|
if ( m == FL_PUSH )
|
|
if ( Fl::event_inside( this ) )
|
|
take_focus();
|
|
|
|
|
|
if ( Fl_Widget::handle( m ) )
|
|
return 1;
|
|
|
|
// Ignore events unless we have the focus.
|
|
if ( this != Fl::focus() )
|
|
return 0;
|
|
|
|
// MESSAGE( "got event %i for canvas %p", m, _c );
|
|
|
|
int p = 0;
|
|
|
|
if ( _c )
|
|
{
|
|
p = canvas_input_callback( this, _c, m );
|
|
}
|
|
|
|
return p;} {}
|
|
}
|
|
Function {resize( int x, int y, int w, int h )} {open
|
|
} {
|
|
code {Fl_Widget::resize( x, y, w, h );
|
|
|
|
if ( _c )
|
|
{
|
|
DMESSAGE( "Resizing canvas." );
|
|
_c->resize( x + 1, y + 1, w - 1, h - 1 );
|
|
}
|
|
|
|
|
|
// Fl_Window::resize( x, y, w, h );} {}
|
|
}
|
|
Function {draw()} {open return_type void
|
|
} {
|
|
code {draw_border();
|
|
|
|
//if ( ! takesevents() )
|
|
// return;
|
|
|
|
if ( _c )
|
|
{
|
|
/*
|
|
if ( damage() & FL_DAMAGE_ALL ) printf( " damage_all" );
|
|
if ( damage() & FL_DAMAGE_SCROLL ) printf( " damage_scroll" );
|
|
if ( damage() & FL_DAMAGE_USER1 ) printf( " damage_user1" );
|
|
if ( damage() & FL_DAMAGE_USER2 ) printf( " damage_user2" );
|
|
if ( damage() & FL_DAMAGE_EXPOSE ) printf( " damage_expose" );
|
|
printf("\\n");
|
|
*/
|
|
|
|
if ( damage() & FL_DAMAGE_ALL )
|
|
{
|
|
draw_box( FL_FLAT_BOX, x(), y(), w(), h(), canvas_background_color );
|
|
_border_drawn = false;
|
|
draw_border();
|
|
_c->redraw();
|
|
_c->draw_playhead();
|
|
}
|
|
else
|
|
{
|
|
if ( damage() & FL_DAMAGE_SCROLL )
|
|
{
|
|
// optimized draw
|
|
_c->draw();
|
|
}
|
|
if ( damage() & FL_DAMAGE_USER1 )
|
|
{
|
|
// playhead
|
|
_c->draw_playhead();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING( "No canvas set for widget." );
|
|
}} {}
|
|
}
|
|
Function {set_canvas( Canvas *c )} {open
|
|
} {
|
|
code {_c = c;
|
|
|
|
_c->resize( x(), y(), w(), h() );
|
|
|
|
_c->signal_draw.connect( sigc::mem_fun( this, &O_Canvas::redraw_notes ) );
|
|
_c->signal_resize.connect( sigc::mem_fun( this, &O_Canvas::clear ) );
|
|
|
|
_c->signal_settings_change.connect( sigc::ptr_fun( &UI::update_canvas_widgets ) );
|
|
_c->signal_settings_change.connect( sigc::mem_fun( song, &song_settings::set_dirty ) );} {}
|
|
}
|
|
Function {click_to_focus()} {open return_type bool
|
|
} {
|
|
code {return true;} {}
|
|
}
|
|
Function {clear( void )} {open return_type void
|
|
} {
|
|
code {redraw();} {}
|
|
}
|
|
Function {redraw_notes( void )} {open return_type void
|
|
} {
|
|
code {damage( FL_DAMAGE_SCROLL );
|
|
|
|
// this might be called from within draw(), in which case the above does nothing.} {}
|
|
}
|
|
Function {redraw_playhead( void )} {open return_type void
|
|
} {
|
|
code {if ( _c && _c->playhead_moved() )
|
|
{
|
|
damage( FL_DAMAGE_USER1 );
|
|
}} {}
|
|
}
|
|
Function {draw_border()} {open return_type void
|
|
} {
|
|
code {if ( _border_drawn )
|
|
return;
|
|
|
|
if ( this != Fl::focus() )
|
|
fl_color( FL_RED );
|
|
else
|
|
fl_color( FL_BLACK );
|
|
|
|
fl_line_style( FL_DASH );
|
|
fl_rect( x(), y(), w(), h() );
|
|
fl_line_style( FL_SOLID );
|
|
|
|
_border_drawn = true;} {}
|
|
}
|
|
Function {handle_pan( void )} {open return_type void
|
|
} {
|
|
code {int up, left, right, down;
|
|
|
|
if ( ! ui )
|
|
return;
|
|
_c->can_scroll( &left, &right, &up, &down );
|
|
|
|
if ( left == 0 )
|
|
ui->scroll_left_box->hide();
|
|
else
|
|
ui->scroll_left_box->show();
|
|
|
|
if ( up == 0 )
|
|
ui->scroll_up_box->hide();
|
|
else
|
|
ui->scroll_up_box->show();
|
|
|
|
if ( down == 0 )
|
|
ui->scroll_down_box->hide();
|
|
else
|
|
ui->scroll_down_box->show();
|
|
|
|
ui->scroll_right_box->hide();} {}
|
|
}
|
|
}
|
|
|
|
class Instrument_Editor {} {
|
|
Function {Instrument_Editor()} {open return_type void
|
|
} {
|
|
code {make_window();} {}
|
|
}
|
|
decl {Instrument *_inst;} {private local
|
|
}
|
|
decl {int _note;} {private local
|
|
}
|
|
Function {make_window()} {open
|
|
} {
|
|
Fl_Window window {
|
|
label {Instrument Editor}
|
|
callback {done->do_callback();} open
|
|
xywh {670 458 335 190} type Double hide
|
|
} {
|
|
Fl_Box {} {
|
|
label {Instrument Row}
|
|
xywh {8 15 321 28} box ROUNDED_BOX color 94 labelsize 22 labelcolor 39
|
|
}
|
|
Fl_Input name_field {
|
|
label Name
|
|
callback {_inst->note_name( _note, strdup( o->value() ) );}
|
|
xywh {10 70 321 25} selection_color 48 align 1 when 1 textcolor 32
|
|
}
|
|
Fl_Value_Slider volume_slider {
|
|
label {Volume %}
|
|
callback {_inst->velocity( _note, o->value() );}
|
|
xywh {10 112 321 27} type Horizontal align 1 maximum 100 step 1 textsize 14
|
|
}
|
|
Fl_Value_Output note_field {
|
|
label {Note:}
|
|
xywh {52 158 43 24}
|
|
}
|
|
Fl_Return_Button done {
|
|
label Done
|
|
callback {if ( _inst )
|
|
_inst->save();
|
|
|
|
window->hide();}
|
|
xywh {255 157 76 25}
|
|
}
|
|
}
|
|
}
|
|
Function {set( Instrument *i, int n )} {open return_type void
|
|
} {
|
|
code {_inst = i;
|
|
_note = n;
|
|
|
|
volume_slider->value( i->velocity( n ) );
|
|
name_field->value( i->note_name( n ) );
|
|
note_field->value( n );} {}
|
|
}
|
|
Function {run()} {open return_type void
|
|
} {
|
|
code {window->show();
|
|
|
|
while ( window->shown() )
|
|
Fl::wait();} {}
|
|
}
|
|
}
|
|
|
|
class Trigger {open : {public Fl_Dial}
|
|
} {
|
|
Function {Trigger( int X, int Y, int W, int H, const char *L ) : Fl_Dial( X, Y, W, H, L )} {open
|
|
} {
|
|
code {} {}
|
|
}
|
|
Function {handle( int m )} {open return_type int
|
|
} {
|
|
code {int r = 0;
|
|
|
|
switch ( m )
|
|
{
|
|
case FL_PUSH:
|
|
{
|
|
switch ( Fl::event_button() )
|
|
{
|
|
case 1:
|
|
{
|
|
pattern *p = pattern::pattern_by_number( atoi( label() ) );
|
|
|
|
if ( p )
|
|
{
|
|
if ( TRIGGER == song.play_mode )
|
|
{
|
|
if ( p->playing() )
|
|
p->stop();
|
|
else
|
|
p->trigger();
|
|
}
|
|
else
|
|
{
|
|
if ( p->mode() == PLAY )
|
|
p->mode( MUTE );
|
|
else
|
|
p->mode( PLAY );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
pattern *p = pattern::pattern_by_number( atoi( label() ) );
|
|
|
|
if ( p )
|
|
{
|
|
if ( p->mode() != SOLO )
|
|
p->mode( SOLO );
|
|
else
|
|
p->mode( PLAY );
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
ui->switch_to_pattern( atoi( label() ) );
|
|
}
|
|
break;
|
|
}
|
|
r = 1;
|
|
break;
|
|
}
|
|
case FL_RELEASE:
|
|
do_callback();
|
|
r = 1;
|
|
break;
|
|
case FL_DRAG:
|
|
r = 1;
|
|
break;
|
|
default:
|
|
r = Fl_Widget::handle( m );
|
|
break;
|
|
}
|
|
|
|
|
|
return r;} {}
|
|
}
|
|
}
|
|
|
|
widget_class Triggers {open
|
|
xywh {335 80 1278 1003} type Double hide resizable
|
|
code0 {populate();}
|
|
code1 {\#include <FL/Fl_Dial.H>}
|
|
class Fl_Group
|
|
} {
|
|
Fl_Pack rows {open
|
|
xywh {25 25 15 15}
|
|
} {}
|
|
Function {populate( void )} {open private return_type void
|
|
} {
|
|
code {_timer = 0;
|
|
|
|
int bw = (w() / 16);
|
|
int bh = h() / (128/ 16);
|
|
|
|
begin();
|
|
|
|
for ( int n = 0; n < 128 ; n += 16 )
|
|
{
|
|
Fl_Pack *p = new Fl_Pack( 0, 0, 25, 25 );
|
|
|
|
p->type( Fl_Pack::HORIZONTAL );
|
|
|
|
for ( int i = 0; i < 16; i++ )
|
|
{
|
|
|
|
Trigger *b = new Trigger( 0, 0, bw, 50, "Num" );
|
|
|
|
char pat[4];
|
|
|
|
sprintf( pat, "%d", n + i + 1 );
|
|
|
|
b->label( strdup( pat ) );
|
|
b->minimum( 0 );
|
|
b->maximum( 1 );
|
|
b->angles( 0, 360 );
|
|
b->type( FL_FILL_DIAL );
|
|
b->color2( FL_GRAY );
|
|
b->box( FL_ROUNDED_BOX );
|
|
// b->down_box( FL_ROUNDED_BOX );
|
|
b->selection_color( FL_GREEN );
|
|
b->color( FL_BLACK );
|
|
b->align( FL_ALIGN_CENTER );
|
|
|
|
p->add( b );
|
|
}
|
|
|
|
p->end();
|
|
|
|
p->resize( 0, 0, w(), bh );
|
|
rows->add( p );
|
|
}
|
|
|
|
|
|
end();
|
|
|
|
rows->resize( x(), y(), w(), h() );
|
|
|
|
redraw();} {}
|
|
}
|
|
Function {update( void )} {open return_type void
|
|
} {
|
|
code {++_timer;
|
|
|
|
if ( !visible_r() )
|
|
return;
|
|
|
|
if ( ! takesevents() )
|
|
return;
|
|
|
|
Fl_Color mode_color[3];
|
|
|
|
// mode_color[PLAY] = fl_color_average( FL_GRAY, FL_GREEN, 0.5 );
|
|
mode_color[PLAY] = FL_DARK2;
|
|
mode_color[MUTE] = FL_LIGHT2;
|
|
mode_color[SOLO] = fl_color_average( FL_GRAY, FL_RED, 0.5 );
|
|
|
|
int i;
|
|
for ( i = 0; i < MAX_PATTERN; i++ )
|
|
{
|
|
|
|
|
|
Trigger *b = (Trigger*)(((Fl_Pack*)rows->child( i / 16 ))->child( i % 16 ));
|
|
|
|
if ( i >= pattern::patterns() )
|
|
{
|
|
b->color( FL_BLACK );
|
|
b->value( 0 );
|
|
continue;
|
|
}
|
|
|
|
pattern *p = pattern::pattern_by_number( i + 1 );
|
|
|
|
if ( p->playing() )
|
|
{
|
|
b->color( FL_GRAY );
|
|
|
|
b->selection_color( mode_color[ p->mode() ] );
|
|
|
|
if ( p->queue() >= 0 )
|
|
{
|
|
if ( _timer % 16 < 8 )
|
|
{
|
|
b->color( mode_color[ p->queue() ] );
|
|
}
|
|
}
|
|
|
|
b->value( (double)p->index() / p->length() );
|
|
}
|
|
else
|
|
{
|
|
b->value( 0 );
|
|
}
|
|
|
|
}} {}
|
|
}
|
|
Function {resize( int X, int Y, int W, int H )} {open return_type void
|
|
} {
|
|
code {for ( int i = rows->children(); i--; )
|
|
{
|
|
Fl_Pack *p = (Fl_Pack*) rows->child( i );
|
|
|
|
for ( int j = p->children(); j--; )
|
|
{
|
|
int bw = W / p->children();
|
|
p->child( j )->resize( 0, 0, bw, 25 );;
|
|
}
|
|
|
|
p->resize( 0, 0, W, H / rows->children() );
|
|
|
|
p->redraw();
|
|
}
|
|
|
|
Fl_Group::resize( X, Y, W, H );} {}
|
|
}
|
|
decl {unsigned long _timer;} {private local
|
|
}
|
|
}
|