2 Epichord - a midi sequencer
3 Copyright (C) 2008 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
28 #include <arpa/inet.h>
31 #include <fltk/file_chooser.h>
32 #include <fltk/filename.h>
48 extern std::vector
<track
*> tracks
;
51 extern struct conf config
;
55 std::string last_filename
;
56 char last_dir
[1024] = "";
59 void nextline(ifstream
& f
){
66 std::list
<pattern
*> collectpatterns(){
67 std::list
<pattern
*> patlist
;
69 for(int i
=0; i
<tracks
.size(); i
++){
70 seqpat
* s
= tracks
[i
]->head
->next
;
73 for(int j
=0; j
<s
->layers
->total
; j
++){
74 pattern
* p
= s
->layers
->array
[j
];
79 patlist
.push_back(s
->p
);
91 int findpatternindex(pattern
* p
, std::list
<pattern
*>& patlist
){
92 std::list
<pattern
*>::iterator i
= patlist
.begin();
94 while(i
!= patlist
.end()){
104 pattern
* findpatternbyindex(int index
, std::list
<pattern
*>& patlist
){
105 std::list
<pattern
*>::iterator i
= patlist
.begin();
107 while(i
!= patlist
.end()){
125 set_beats_per_measure(4);
126 set_measures_per_phrase(4);
130 int total
= tracks
.size();
132 for(int i
=0; i
<total
; i
++){
133 t
= tracks
[tracks
.size()-1];
140 ui
->title_text
->text("");
141 ui
->author_text
->text("");
143 fltk::TextBuffer
* tb
= ui
->info_text
->buffer();
146 ui
->track_info
->clear_tracks();
148 ui
->main_window
->redraw();
152 void set_last_dir(const char* name
){
153 const char* theend
= fltk::filename_name(name
);
154 int n
= (int)(theend
- name
) / sizeof(char);
155 memcpy(last_dir
,name
,n
);
159 const char* get_last_dir(){
164 if(last_filename
!= ""){
165 return save(last_filename
.c_str());
168 return save(fltk::file_chooser("save file",NULL
,last_dir
));
174 int save(const char* filename
){
176 if(filename
== NULL
){
182 file
.open(filename
, fstream::out
);
185 printf("error, cant open file for saving\n");
189 last_filename
= filename
;
190 set_last_dir(filename
);
192 //header to protect against accidentally opening wrong file
193 file
<< "J2ULJwCgwHA" << endl
;
194 file
<< "epichord" << endl
;
195 file
<< "fileversion " << FILE_VERSION
<< endl
;
196 file
<< "ticksperbeat " << TICKS_PER_BEAT
<< endl
<< endl
;
199 file
<< "title " << ui
->title_text
->size() << " "
200 << ui
->title_text
->text() << endl
;
201 file
<< "author " << ui
->author_text
->size() << " "
202 << ui
->author_text
->text() << endl
;
203 file
<< "info " << ui
->info_text
->size() << " "
204 << ui
->info_text
->text() << endl
;
206 file
<< "bpm " << ui
->bpm_wheel
->value() << endl
;
207 file
<< "beatspermeasure " << config
.beats_per_measure
<< endl
;
208 file
<< "measuresperphrase " << config
.measures_per_phrase
<< endl
;
210 file
<< "loopstart " << get_loop_start() << endl
;
211 file
<< "loopend " << get_loop_end() << endl
;
216 //collect all visible patterns
217 std::list
<pattern
*> patlist
= collectpatterns();
220 std::list
<pattern
*>::iterator p
= patlist
.begin();
223 while(p
!= patlist
.end()){
224 file
<< "pattern " << endl
;
225 file
<< (*p
)->h
<< " " << (*p
)->s
<< " " << (*p
)->v
<< endl
;
226 e
= (*p
)->events
->next
;
231 file
<< e
->tick
<< " ";
232 file
<< e
->type
<< " ";
233 file
<< e
->value1
<< " ";
234 file
<< e
->value2
<< endl
;
235 //file << e->dur << endl;
240 file
<< -1 << endl
<< endl
;
245 for(int i
=0; i
<tracks
.size(); i
++){
246 file
<< endl
<< endl
<< "track " << endl
;
247 file
<< "port " << tracks
[i
]->port
<< endl
;
248 file
<< "chan " << tracks
[i
]->chan
<< endl
;
249 file
<< "prog " << tracks
[i
]->prog
<< endl
;
250 file
<< "bank " << tracks
[i
]->bank
<< endl
;
251 file
<< "mute " << tracks
[i
]->mute
<< endl
;
252 file
<< "solo " << tracks
[i
]->solo
<< endl
;
253 file
<< "vol " << tracks
[i
]->vol
<< endl
;
254 file
<< "pan " << tracks
[i
]->pan
<< endl
;
255 file
<< "name " << strlen(tracks
[i
]->name
) << " "
256 << tracks
[i
]->name
<< endl
;
257 file
<< "alive " << tracks
[i
]->alive
<< endl
;
258 s
= tracks
[i
]->head
->next
;
261 file
<< endl
<< endl
<< "seqpat " << endl
;
262 file
<< s
->tick
<< " " << s
->dur
<< endl
;
263 file
<< s
->scrollx
<< " " << s
->scrolly
<< endl
;
266 file
<< s
->layers
->total
<< " ";
267 for(int j
=0; j
<s
->layers
->total
; j
++){
269 int index
= findpatternindex(s
->layers
->array
[j
],patlist
);
271 printf("save: pattern not found, cannot save\n");
275 file
<< index
<< " ";
278 file
<< s
->layers
->index
;
282 int index
= findpatternindex(s
->p
,patlist
);
284 printf("save: pattern not found, cannot save\n");
308 int load(const char* filename
){
311 if(filename
== NULL
){
317 file
.open(filename
, fstream::in
);
320 printf("error, cant open file for saving\n");
327 last_filename
= filename
;
328 set_last_dir(filename
);
330 //pattern* pend = patterns;
331 std::list
<pattern
*> patlist
;
336 if(str
!= "J2ULJwCgwHA"){
337 printf("load: this is definitely not a valid file (missing magic)\n");
342 if(str
!= "epichord"){
343 printf("load: this is definitely not a valid file (missing magic)\n");
348 if(str
!= "fileversion"){
349 printf("load: this is definitely not a valid file\n");
356 printf("load: file has wrong version %d (need %d).\n",M
,FILE_VERSION
);
359 if(str
!= "ticksperbeat"){
360 printf("load: file is broken. (missing ticks per beat)\n");
367 printf("load: file is broken. (bad ticks per beat %d)\n",file_tpb
);
384 ui
->title_text
->text(buf
);
386 else if(str
== "author"){
392 ui
->author_text
->text(buf
);
394 else if(str
== "info"){
397 fltk::TextBuffer
* tb
= ui
->info_text
->buffer();
403 else if(str
== "bpm"){
407 ui
->bpm_wheel
->value(bpm
);
408 ui
->bpm_output
->value(bpm
);
410 else if(str
== "beatspermeasure"){
413 set_beats_per_measure(N
);
415 else if(str
== "measuresperphrase"){
418 set_measures_per_phrase(N
);
420 else if(str
== "loopstart"){
425 else if(str
== "loopend"){
430 else if(str
== "pattern"){
431 pattern
* p
= new pattern();
436 mevent
* eend
= p
->events
;
444 if(e
->tick
== -1){delete e
; break;}
455 patlist
.push_back(p
);
457 else if(str
== "track"){
460 track
* t
= new track();
461 t
->head
->track
= tracks
.size();
462 seqpat
* send
= t
->head
;
465 while(key
!= "kcart"){
466 if(key
== "port"){ file
>> t
->port
; }
467 else if(key
== "chan"){ file
>> t
->chan
; }
468 else if(key
== "prog"){ file
>> t
->prog
; }
469 else if(key
== "bank"){ file
>> t
->bank
; }
470 else if(key
== "mute"){ file
>> t
->mute
; }
471 else if(key
== "solo"){ file
>> t
->solo
; }
472 else if(key
== "vol"){ file
>> t
->vol
; }
473 else if(key
== "pan"){ file
>> t
->pan
; }
474 else if(key
== "name"){
477 char* buf
= (char*)malloc(n
+1);
482 else if(key
== "alive"){ file
>> t
->alive
; }
483 else if(key
== "seqpat"){
485 seqpat
* s
= new seqpat();
486 s
->track
= tracks
.size();
493 file
>> s
->scrollx
>> s
->scrolly
;
494 file
>> total_layers
;
496 if(total_layers
== 1){
498 p
= findpatternbyindex(index
, patlist
);
502 else if(total_layers
> 1){
504 p
= findpatternbyindex(index
, patlist
);
505 layerstack
* layers
= new layerstack(p
);
507 for(int j
=1; j
<total_layers
; j
++){
509 p
= findpatternbyindex(index
,patlist
);
513 file
>> layers
->index
;
514 s
->p
= layers
->array
[layers
->index
];
519 printf("load: bad number of layers\n");
531 ui
->track_info
->add_track();
534 file
.ignore(std::numeric_limits
<streamsize
>::max(),'\n');
541 ui
->track_info
->set_rec(0);
542 ui
->track_info
->update();
544 ui
->arranger
->reset_handle();
545 ui
->arranger
->redraw();
557 int tick2delta(unsigned tick
, vector
<unsigned char>& vbuf
){
558 unsigned char buf
[4];
561 vbuf
.push_back(tick
);
564 else if(tick
< 16383){
567 vbuf
.push_back(0x80|((buf
[0]<<1)|(buf
[1]&0x80)>>7));
568 vbuf
.push_back(buf
[1]&0x7f);
571 else if(tick
< 2097151){
574 vbuf
.push_back(0x80|((buf
[0]<<2)|(buf
[1]&0xC0)>>6));
575 vbuf
.push_back(0x80|((buf
[1]<<1)|(buf
[2]&0x80)>>7));
576 vbuf
.push_back(buf
[2]&0x7f);
582 vbuf
.push_back(0x80|((buf
[0]<<3)|(buf
[1]&0xE0)>>5));
583 vbuf
.push_back(0x80|((buf
[1]<<2)|(buf
[2]&0xC0)>>6));
584 vbuf
.push_back(0x80|((buf
[2]<<1)|(buf
[3]&0x80)>>7));
585 vbuf
.push_back(buf
[3]&0x7f);
590 int savesmf(const char* filename
){
592 if(filename
== NULL
){
597 file
.open(filename
, fstream::out
);
600 printf("error, cant open file for saving\n");
604 unsigned char buf
[64];
623 uint16_t L
= tracks
.size();
627 //128 ticks per beat, 128 | 0x0000
631 file
.write((const char*)buf
,14);
633 vector
<unsigned char> vbuf
;
636 int MAX
= tracks
.size();
638 for(int i
=0; i
<MAX
; i
++){
649 //chunk size (yet unknown)
651 vbuf
.push_back(0x00);
652 vbuf
.push_back(0x00);
653 vbuf
.push_back(0x00);
654 vbuf
.push_back(0x00);
656 track
* t
= tracks
[i
];
661 //change program for this track
667 e
= s
->p
->events
->next
;
671 if(e
->tick
> s
->dur
){
676 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
677 last_tick
= e
->tick
+s
->tick
;
678 vbuf
.push_back(0x80 | t
->chan
);
679 vbuf
.push_back(e
->value1
);
680 vbuf
.push_back(e
->value2
);
684 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
685 last_tick
= e
->tick
+s
->tick
;
686 vbuf
.push_back(0x90 | t
->chan
);
687 vbuf
.push_back(e
->value1
);
688 vbuf
.push_back(e
->value2
);
691 case 0xA0://after touch
692 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
693 last_tick
= e
->tick
+s
->tick
;
694 vbuf
.push_back(0xA0 | t
->chan
);
695 vbuf
.push_back(e
->value1
);
696 vbuf
.push_back(e
->value2
);
699 case 0xB0://control change
700 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
701 last_tick
= e
->tick
+s
->tick
;
702 vbuf
.push_back(0xB0 | t
->chan
);
703 vbuf
.push_back(e
->value1
);
704 vbuf
.push_back(e
->value2
);
707 case 0xC0://program change
708 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
709 last_tick
= e
->tick
+s
->tick
;
710 vbuf
.push_back(0xC0 | t
->chan
);
711 vbuf
.push_back(e
->value1
);
714 case 0xD0://channel pressure
715 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
716 last_tick
= e
->tick
+s
->tick
;
717 vbuf
.push_back(0xD0 | t
->chan
);
718 vbuf
.push_back(e
->value1
);
721 case 0xE0://pitch wheel
722 N
+= tick2delta(e
->tick
+s
->tick
- last_tick
,vbuf
);
723 last_tick
= e
->tick
+s
->tick
;
724 vbuf
.push_back(0xE0 | t
->chan
);
725 vbuf
.push_back(e
->value1
);
726 vbuf
.push_back(e
->value2
);
736 //end of track meta event
737 vbuf
.push_back(0x00);
738 vbuf
.push_back(0xff);
739 vbuf
.push_back(0x2f);
740 vbuf
.push_back(0x00);
750 for(int i
=0; i
<vbuf
.size(); i
++){
752 file
.write((const char*)buf
,1);
762 int getdelta(std::fstream
& f
){
763 unsigned char a
,b
,c
,d
;
766 if(a
<0x80){return a
;}
769 if(b
<0x80){return ((a
&0x7f)<<7) | b
;}
772 if(c
<0x80){return ((a
&0x7f)<<14) | ((b
&0x7f)<<7) | c
;}
775 return ((a
&0x7f)<<21) | ((b
&0x7f)<<14) | ((c
&0x7f)<<7) | d
;
783 char fifths
[15][8] = {
802 int loadsmf(const char* filename
){
803 if(filename
== NULL
){
808 file
.open(filename
, fstream::in
);
811 printf("error, cant open file for saving\n");
815 last_filename
= filename
;
816 set_last_dir(filename
);
820 unsigned char buf
[64];
829 std::list
<pattern
*> patlist
;
830 std::vector
<int> chanlist
;
831 std::vector
<int> proglist
;
832 std::vector
<int> banklist
;
834 std::vector
<track
*> extratracks
;
836 std::vector
<char*> tracknames
;
840 for(int i
=0; i
<16; i
++){
841 extratracks
.push_back(NULL
);
846 file
.read((char*)buf
,4);
847 if(memcmp(buf
,"MThd",4)){
848 printf("missing header, probably not a midi file\n");
853 scope_print("Standard Midi File\n");
855 file
.read((char*)buf
,4);
857 printf("header has wrong size, probably a broken midi file\n");
858 scope_print("error: bad header size");
862 //printf("header size\n");
864 file
.read((char*)buf
,2);
866 printf("bad smf type code, probably a broken midi file\n");
867 scope_print("error: bad smf type");
875 case 0: smftype
=0; break;
876 case 1: smftype
=1; break;
877 case 2: smftype
=2; break;
879 printf("bad smf type code, probably a broken midi file\n");
880 scope_print("error: bad smf type");
885 snprintf(sbuf
,256," type: %d\n",smftype
);
888 file
.read((char*)buf
,2);
889 size
= ntohs(*(unsigned short*)buf
);
891 printf("track count of zero, probably a broken midi file\n");
892 scope_print("error: zero tracks");
898 snprintf(sbuf
,256," tracks: %d\n",ntracks
);
902 int tpb
= TICKS_PER_BEAT
;
903 file
.read((char*)buf
,2);
904 size
= ntohs(*(unsigned short*)buf
);
907 snprintf(sbuf
,256," time division: %d ticks per beat\n",tpb
);
911 int fps
= size
&0x7fff;
912 snprintf(sbuf
,256," time division: %d frames per second (wrong)\n",fps
);
914 scope_print("error: smpte time division not support\n");
921 /*** read tracks ***/
922 file
.read((char*)buf
,4);
925 if(memcmp(buf
,"MTrk",4)){
926 printf("bad track header, probably a broken midi file\n");
931 pattern
* p
= new pattern();
935 snprintf(sbuf
,256," track %d\n",trackindex
);
938 file
.read((char*)buf
,4);
939 size
= ntohl(*(unsigned long*)buf
);
941 printf("empty track\n");
950 chanlist
.push_back(-1);
951 banklist
.push_back(-1);
952 proglist
.push_back(-1);
954 tracknames
.push_back(NULL
);
959 int delta
= getdelta(file
);
961 printf("bad delta time, broken midi file\n");
966 tick
= time
*TICKS_PER_BEAT
/tpb
;
968 if(tick
> maxblockdur
){
973 file
.read((char*)buf
,1);
977 if(byte0
< 0x80){//implicit byte0
983 if(byte0
< 0xf0){//channel event
985 int type
= byte0
&0xf0;
986 int chan
= byte0
&0x0f;
992 if(byte1
<0){//didnt read byte1 yet
993 file
.read((char*)buf
,1);
1002 if(!(type
== 0xC0 || type
== 0xD0)){
1003 file
.read((char*)buf
,1);
1007 e
= new mevent(type
,tick
,val1
);
1012 if(val2
==0){//fake note off
1017 case 0x80://note off
1018 case 0xA0://aftertouch
1019 case 0xB0://controller change
1020 case 0xE0://pitchbend
1021 if(type
==0xB0 && val1
==0x00 && banklist
[N
]==-1){
1027 case 0xC0://program change
1028 if(proglist
[N
]==-1){
1032 case 0xD0://channel pressure
1035 printf("unrecognized channel event %d\n",type
);
1040 if(chan
!=chanlist
[N
]){//put event in the a misfit track
1041 //printf("mistfit N=%d chan=%d type=%d\n",chanlist[N],chan,type);
1042 if(extratracks
[chan
] == NULL
){
1043 track
* t
= new track();
1049 extratracks
[chan
] = t
;
1050 seqpat
* s
= new seqpat();
1053 s
->p
= new pattern();
1056 extratracks
[chan
]->head
->next
->p
->insert(e
,tick
);
1058 else{//put it in a normal track
1063 else{/*** not a channel event ***/
1067 if(byte0
== 255){//meta events
1069 file
.read((char*)buf
,1);
1073 size
= getdelta(file
);
1075 printf("bad delta time\n");
1081 abuf
= new char[size
+1];
1084 case 0://sequence number
1086 snprintf(sbuf
,256," %d sequence: ? ?\n",time
);
1089 printf("bad sequence number data length: %d\n",size
);
1093 file
.read((char*)buf
,2);
1096 file
.read(abuf
,size
);
1098 asprintf(&tbuf
," %d text: \"%s\"\n",time
,abuf
);
1102 ui
->info_text
->buffer()->append(abuf
);
1103 ui
->info_text
->buffer()->append("\n");
1106 case 2://copyright notice
1107 file
.read((char*)abuf
,size
);
1109 asprintf(&tbuf
," %d copyright: \"%s\"\n",time
,abuf
);
1114 file
.read((char*)abuf
,size
);
1116 asprintf(&tbuf
," %d track name: \"%s\"\n",time
,abuf
);
1120 tracknames
[N
] = (char*)malloc(sizeof(char)*(size
+1));
1121 strncpy(tracknames
[N
],abuf
,size
+1);
1124 case 4://instrument name
1125 file
.read((char*)abuf
,size
);
1127 asprintf(&tbuf
," %d instrument name: \"%s\"\n",time
,abuf
);
1132 file
.read((char*)abuf
,size
);
1134 asprintf(&tbuf
," %d lyrics: \"%s\"\n",time
,abuf
);
1139 file
.read((char*)abuf
,size
);
1141 asprintf(&tbuf
," %d marker: \"%s\"\n",time
,abuf
);
1146 file
.read((char*)abuf
,size
);
1148 asprintf(&tbuf
," %d cue point: \"%s\"\n",time
,abuf
);
1152 case 32://channel prefix
1154 printf("bad channel prefix data size: %d\n",size
);
1158 file
.read((char*)buf
,1);
1159 asprintf(&tbuf
," %d channel prefix: %d\n",time
,buf
[0]);
1163 case 47://end of track
1165 printf("end of track has non zero data size: %d\n",size
);
1173 printf("set tempo has non-3 data size: %d\n",size
);
1177 file
.read((char*)buf
,3);
1184 micros
= *(unsigned*)buf
;
1185 micros
= ntohl(micros
);
1187 asprintf(&tbuf
," %d set tempo: %d us/quarter\n",time
,micros
);
1193 set_beats_per_minute(60000000/micros
);
1197 case 84://smpte offset
1199 printf("smpte offset has non-5 data size: %d\n",size
);
1203 file
.read((char*)buf
,5);
1204 asprintf(&tbuf
," %d smpte offset: ?\n",time
);
1208 case 88://time signature
1210 printf("time signature has non-4 data size: %d\n",size
);
1214 file
.read((char*)buf
,4);
1215 asprintf(&tbuf
," %d time signature: %d/%d\n",time
,buf
[0],1<<buf
[1]);
1219 case 89://key signature
1221 printf("key signature has non-2 data size: %d\n",size
);
1225 file
.read((char*)buf
,2);
1226 asprintf(&tbuf
," %d key signature: %s %s\n",time
,fifths
[(signed char)buf
[0]+7],buf
[1]?"minor":"major");
1230 case 127://sequencer specific
1231 file
.read((char*)abuf
,size
);
1233 asprintf(&tbuf
," %d sequencer specific: \"%s\"\n",time
,abuf
);
1237 default://unknown meta event
1238 file
.read((char*)abuf
,size
);
1240 asprintf(&tbuf
," %d meta %d: \"%s\"\n",time
,meta
,abuf
);
1246 else if(byte0
== 240){//sysex event
1247 size
= getdelta(file
);
1249 printf("bad delta time\n");
1252 abuf
= new char[size
+1];
1253 file
.read((char*)abuf
,size
);
1256 asprintf(&tbuf
," %d sysex: \"%s\"\n",time
,abuf
);
1260 file
.read((char*)buf
,1);
1262 file
.putback(buf
[0]);
1265 scope_print(" end of sysex\n");
1272 else if(byte0
== 247){//divided sysex event
1273 size
= getdelta(file
);
1275 printf("bad delta time\n");
1278 abuf
= new char[size
+1];
1279 file
.read((char*)abuf
,size
);
1282 asprintf(&tbuf
," %d sysex fragment: \"%s\"\n",time
,abuf
);
1286 file
.read((char*)buf
,1);
1288 file
.putback(buf
[0]);
1291 scope_print(" end of sysex\n");
1296 printf("bad event type %d, broken midi file\n",byte0
);
1305 if(proglist
[N
]==-1){
1308 if(banklist
[N
]==-1){
1311 if(chanlist
[N
]==-1){
1319 patlist
.push_back(p
);
1321 file
.read((char*)buf
,4);//read first byte of next track or EOF
1326 scope_print("End Of File\n\n");
1329 //TODO set up track settings using data remembered from the reading
1330 std::list
<pattern
*>::iterator p
= patlist
.begin();
1332 while(p
!=patlist
.end()){
1333 track
* t
= new track();
1334 seqpat
* s
= new seqpat(i
,0,128*64,*p
);
1335 int Q
= TICKS_PER_BEAT
;
1336 s
->dur
= maxblockdur
/ Q
* Q
+ Q
;
1341 s
->p
->h
= 360*i
/ 16;
1343 while(s
->p
->h
> 360){s
->p
->h
-= 360;}
1344 s
->p
->regen_colors();
1346 t
->chan
= chanlist
[i
];
1347 t
->prog
= proglist
[i
];
1348 t
->bank
= banklist
[i
];
1352 t
->name
= tracknames
[i
];
1355 t
->name
= (char*)malloc(8);
1364 if(tempo_flag
== 0){
1365 set_beats_per_minute(120);
1369 ui
->track_info
->set_rec(0);
1370 ui
->track_info
->update();
1372 ui
->arranger
->reset_handle();
1373 ui
->arranger
->redraw();
1375 update_config_gui();