Fixed remaining known use of uninitialized data.
[epichord.git] / src / saveload.cpp
blob53c75e60dd229fe723e861a85910d94d926bc90d
1 /*
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
23 #include <iostream>
24 #include <fstream>
25 #include <vector>
26 #include <list>
28 #include <limits>
30 #include <arpa/inet.h>
31 #include <string.h>
32 #include <stdlib.h>
34 #include <fltk/file_chooser.h>
35 #include <fltk/filename.h>
37 #include "ui.h"
39 #include "backend.h"
41 #include "saveload.h"
43 #include "util.h"
45 #include "uihelper.h"
47 #include "backend.h"
49 extern UI* ui;
51 extern std::vector<track*> tracks;
54 extern struct conf config;
56 using namespace std;
58 std::string last_filename;
59 char last_dir[1024] = "";
62 void nextline(ifstream& f){
63 char dummy[512];
64 f.getline(dummy,512);
65 printf("%s\n",dummy);
69 std::list<pattern*> collectpatterns(){
70 std::list<pattern*> patlist;
72 for(int i=0; i<tracks.size(); i++){
73 seqpat* s = tracks[i]->head->next;
74 while(s){
75 if(s->layers){
76 for(int j=0; j<s->layers->total; j++){
77 pattern* p = s->layers->array[j];
78 patlist.push_back(p);
81 else{
82 patlist.push_back(s->p);
84 s=s->next;
88 patlist.sort();
89 patlist.unique();
91 return patlist;
94 int findpatternindex(pattern* p, std::list<pattern*>& patlist){
95 std::list<pattern*>::iterator i = patlist.begin();
96 int q = 0;
97 while(i != patlist.end()){
98 if(*i==p){
99 return q;
101 q++;
102 i++;
104 return -1;
107 pattern* findpatternbyindex(int index, std::list<pattern*>& patlist){
108 std::list<pattern*>::iterator i = patlist.begin();
109 int q = 0;
110 while(i != patlist.end()){
111 if(q==index){
112 return *i;
114 q++;
115 i++;
117 return NULL;
121 int clear(){
123 pause_backend();
124 reset_backend(0);
126 last_filename = "";
128 set_beats_per_measure(4);
129 set_measures_per_phrase(4);
131 set_bpm(120);
132 set_beats_per_minute(120);
133 update_config_gui();
135 track* t;
136 int total = tracks.size();
138 for(int i=0; i<total; i++){
139 t = tracks[tracks.size()-1];
140 tracks.pop_back();
141 delete t;
147 ui->title_text->text("");
148 ui->author_text->text("");
150 fltk::TextBuffer* tb = ui->info_text->buffer();
151 tb->text("");
153 ui->track_info->clear_tracks();
155 ui->main_window->redraw();
159 void set_last_dir(const char* name){
160 const char* theend = fltk::filename_name(name);
161 int n = (int)(theend - name) / sizeof(char);
162 memcpy(last_dir,name,n);
163 last_dir[n] = '\0';
166 const char* get_last_dir(){
167 return last_dir;
170 int save(){
171 if(last_filename != ""){
172 return save(last_filename.c_str());
174 else{
175 return save(fltk::file_chooser("save file",NULL,last_dir));
181 int save(const char* filename){
183 if(filename == NULL){
184 return -1;
187 //create file
188 fstream file;
189 file.open(filename, fstream::out);
191 if(!file.is_open()){
192 printf("error, cant open file for saving\n");
193 return -1;
196 last_filename = filename;
197 set_last_dir(filename);
199 //header to protect against accidentally opening wrong file
200 file << "J2ULJwCgwHA" << endl;
201 file << "epichord" << endl;
202 file << "fileversion " << FILE_VERSION << endl;
203 file << "ticksperbeat " << TICKS_PER_BEAT << endl << endl;
205 //write song info
206 file << "title " << ui->title_text->size() << " "
207 << ui->title_text->text() << endl;
208 file << "author " << ui->author_text->size() << " "
209 << ui->author_text->text() << endl;
210 file << "info " << ui->info_text->size() << " "
211 << ui->info_text->text() << endl;
213 file << "bpm " << ui->bpm_wheel->value() << endl;
214 file << "beatspermeasure " << config.beats_per_measure << endl;
215 file << "measuresperphrase " << config.measures_per_phrase << endl;
217 file << "loopstart " << get_loop_start() << endl;
218 file << "loopend " << get_loop_end() << endl;
220 file << endl;
223 //collect all visible patterns
224 std::list<pattern*> patlist = collectpatterns();
226 //for each pattern
227 std::list<pattern*>::iterator p = patlist.begin();
228 mevent* e;
229 int P = 0;
230 while(p != patlist.end()){
231 file << "pattern " << endl;
232 file << (*p)->h << " " << (*p)->s << " " << (*p)->v << endl;
233 e = (*p)->events->next;
234 mevent* eoff;
235 int n = 0;
236 int m = n;
237 int last_tick = 0;
238 int delta;
239 while(e){
240 delta = e->tick - last_tick;
241 last_tick = e->tick;
242 file << delta << " ";
243 file << e->type << " ";
244 file << e->value1 << " ";
245 file << e->value2 << endl;
246 //file << e->dur << endl;
247 n++;
248 e = e->next;
250 P++;
251 file << -1 << endl << endl;
252 p++;
255 seqpat* s;
256 for(int i=0; i<tracks.size(); i++){
257 file << endl << endl << "track " << endl;
258 file << "port " << tracks[i]->port << endl;
259 file << "chan " << tracks[i]->chan << endl;
260 file << "prog " << tracks[i]->prog << endl;
261 file << "bank " << tracks[i]->bank << endl;
262 file << "mute " << tracks[i]->mute << endl;
263 file << "solo " << tracks[i]->solo << endl;
264 file << "vol " << tracks[i]->vol << endl;
265 file << "pan " << tracks[i]->pan << endl;
266 file << "name " << strlen(tracks[i]->name) << " "
267 << tracks[i]->name << endl;
268 file << "alive " << tracks[i]->alive << endl;
269 s = tracks[i]->head->next;
270 int m = 0;
271 while(s){
272 file << endl << endl << "seqpat " << endl;
273 file << s->tick << " " << s->dur << endl;
274 file << s->scrollx << " " << s->scrolly << endl;
276 if(s->layers){
277 file << s->layers->total << " ";
278 for(int j=0; j<s->layers->total; j++){
280 int index = findpatternindex(s->layers->array[j],patlist);
281 if(index < 0){
282 printf("save: pattern not found, cannot save\n");
283 file.close();
284 return -1;
286 file << index << " ";
289 file << s->layers->index;
291 else{
292 file << 1 << " ";
293 int index = findpatternindex(s->p,patlist);
294 if(index < 0){
295 printf("save: pattern not found, cannot save\n");
296 file.close();
297 return -1;
299 file << index;
302 file << endl;
303 m++;
304 s = s->next;
306 file << "kcart";
311 file.close();
313 return 0;
319 int load(const char* filename){
322 if(filename == NULL){
323 return -1;
326 ifstream file;
327 string str;
328 file.open(filename, fstream::in);
330 if(!file.is_open()){
331 printf("error, cant open file for saving\n");
332 return -1;
335 show_song_edit();
337 clear();
338 last_filename = filename;
339 set_last_dir(filename);
341 //pattern* pend = patterns;
342 std::list<pattern*> patlist;
345 //sanity check
346 file >> str;
347 if(str != "J2ULJwCgwHA"){
348 printf("load: this is definitely not a valid file (missing magic)\n");
349 file.close();
350 return -1;
352 file >> str;
353 if(str != "epichord"){
354 printf("load: this is definitely not a valid file (missing magic)\n");
355 file.close();
356 return -1;
358 file >> str;
359 if(str != "fileversion"){
360 printf("load: this is definitely not a valid file\n");
361 file.close();
362 return -1;
364 int M;
365 file >> M;
366 if(M!=FILE_VERSION){
367 printf("load: file has wrong version %d (need %d).\n",M,FILE_VERSION);
369 file >> str;
370 if(str != "ticksperbeat"){
371 printf("load: file is broken. (missing ticks per beat)\n");
372 file.close();
373 return -1;
375 int file_tpb;
376 file >> file_tpb;
377 if(file_tpb < 1){
378 printf("load: file is broken. (bad ticks per beat %d)\n",file_tpb);
379 file.close();
380 return -1;
384 file >> str;
385 while(!file.eof()){
387 int n;
389 if(str == "title"){
390 file >> n;
391 file.get();
392 char buf[256];
393 file.read(buf,n);
394 buf[n] = '\0';
395 ui->title_text->text(buf);
397 else if(str == "author"){
398 file >> n;
399 file.get();
400 char buf[256];
401 file.read(buf,n);
402 buf[n] = '\0';
403 ui->author_text->text(buf);
405 else if(str == "info"){
406 file >> n;
407 file.get();
408 fltk::TextBuffer* tb = ui->info_text->buffer();
409 char buf[1024];
410 file.read(buf,n);
411 buf[n] = '\0';
412 tb->text(buf);
414 else if(str == "bpm"){
415 int bpm;
416 file >> bpm;
417 set_bpm(bpm);
418 ui->bpm_wheel->value(bpm);
419 ui->bpm_output->value(bpm);
421 else if(str == "beatspermeasure"){
422 int N;
423 file >> N;
424 set_beats_per_measure(N);
426 else if(str == "measuresperphrase"){
427 int N;
428 file >> N;
429 set_measures_per_phrase(N);
431 else if(str == "loopstart"){
432 int ls;
433 file >> ls;
434 set_loop_start(ls);
436 else if(str == "loopend"){
437 int le;
438 file >> le;
439 set_loop_end(le);
441 else if(str == "pattern"){
442 pattern* p = new pattern();
443 file >> p->h;
444 file >> p->s;
445 file >> p->v;
446 p->regen_colors();
447 mevent* eend = p->events;
448 int off_index;
449 int type;
450 mevent* e;
451 int tick = 0;
452 int delta;
453 while(1){
454 e = new mevent();
456 file >> delta;
457 if(delta == -1){delete e; break;}
458 tick += delta;
459 e->tick = tick;
461 file >> e->type;
462 file >> e->value1;
463 file >> e->value2;
464 //file >> e->dur;
465 e->prev = eend;
466 eend->next = e;
467 eend = e;
469 p->fixdur();
470 patlist.push_back(p);
472 else if(str == "track"){
473 int track_number;
474 string key;
475 track* t = new track();
476 t->head->track = tracks.size();
477 seqpat* send = t->head;
478 file >> key;
480 while(key != "kcart"){
481 if(key == "port"){ file >> t->port; }
482 else if(key == "chan"){ file >> t->chan; }
483 else if(key == "prog"){ file >> t->prog; }
484 else if(key == "bank"){ file >> t->bank; }
485 else if(key == "mute"){ file >> t->mute; }
486 else if(key == "solo"){ file >> t->solo; }
487 else if(key == "vol"){ file >> t->vol; }
488 else if(key == "pan"){ file >> t->pan; }
489 else if(key == "name"){
490 file >> n;
491 file.get();
492 char* buf = (char*)malloc(n+1);
493 file.read(buf,n);
494 buf[n] = '\0';
495 t->name = buf;
497 else if(key == "alive"){ file >> t->alive; }
498 else if(key == "seqpat"){
499 int pattern_number;
500 seqpat* s = new seqpat();
501 s->track = tracks.size();
502 file >> s->tick;
503 file >> s->dur;
504 int total_layers;
505 int index;
506 pattern* p;
508 file >> s->scrollx >> s->scrolly;
509 file >> total_layers;
511 if(total_layers == 1){
512 file >> index;
513 p = findpatternbyindex(index, patlist);
514 s->p = p;
515 s->layers = NULL;
517 else if(total_layers > 1){
518 file >> index;
519 p = findpatternbyindex(index, patlist);
520 layerstack* layers = new layerstack(p);
522 for(int j=1; j<total_layers; j++){
523 file >> index;
524 p = findpatternbyindex(index,patlist);
525 layers->push_new(p);
528 file >> layers->index;
529 s->p = layers->array[layers->index];
530 s->layers = layers;
531 layers->ref_c = 1;
533 else{
534 printf("load: bad number of layers\n");
535 file.close();
536 return -1;
539 s->prev = send;
540 send->next = s;
541 send = s;
543 file >> key;
545 tracks.push_back(t);
546 ui->track_info->add_track();
548 else{
549 file.ignore(std::numeric_limits<streamsize>::max(),'\n');
552 file >> str;
555 set_rec_track(0);
556 ui->track_info->set_rec(0);
557 ui->track_info->update();
559 ui->arranger->redraw();
561 reset_backend(0);
563 file.close();
565 return 0;
571 int tick2delta(unsigned tick, vector<unsigned char>& vbuf){
572 unsigned char buf[4];
573 uint32_t n;
574 if(tick < 128){
575 vbuf.push_back(tick);
576 return 1;
578 else if(tick < 16383){
579 n = htonl(tick);
580 memcpy(buf,&n,4);
581 vbuf.push_back(0x80|((buf[0]<<1)|(buf[1]&0x80)>>7));
582 vbuf.push_back(buf[1]&0x7f);
583 return 2;
585 else if(tick < 2097151){
586 n = htonl(tick);
587 memcpy(buf,&n,4);
588 vbuf.push_back(0x80|((buf[0]<<2)|(buf[1]&0xC0)>>6));
589 vbuf.push_back(0x80|((buf[1]<<1)|(buf[2]&0x80)>>7));
590 vbuf.push_back(buf[2]&0x7f);
591 return 3;
593 else{
594 n = htonl(tick);
595 memcpy(buf,&n,4);
596 vbuf.push_back(0x80|((buf[0]<<3)|(buf[1]&0xE0)>>5));
597 vbuf.push_back(0x80|((buf[1]<<2)|(buf[2]&0xC0)>>6));
598 vbuf.push_back(0x80|((buf[2]<<1)|(buf[3]&0x80)>>7));
599 vbuf.push_back(buf[3]&0x7f);
600 return 4;
604 int savesmf(const char* filename){
606 if(filename == NULL){
607 return -1;
610 fstream file;
611 file.open(filename, fstream::out);
613 if(!file.is_open()){
614 printf("error, cant open file for saving\n");
615 return -1;
618 unsigned char buf[64];
620 //chunk id
621 buf[0] = 'M';
622 buf[1] = 'T';
623 buf[2] = 'h';
624 buf[3] = 'd';
626 //chunk size
627 buf[4] = 0x00;
628 buf[5] = 0x00;
629 buf[6] = 0x00;
630 buf[7] = 0x06;
632 //type 1 midi file
633 buf[8] = 0x00;
634 buf[9] = 0x01;
636 //number of tracks
637 uint16_t L = tracks.size();
638 L = htons(L);
639 memcpy(buf+10,&L,2);
641 //128 ticks per beat, 128 | 0x0000
642 buf[12] = 0x00;
643 buf[13] = 0x80;
645 file.write((const char*)buf,14);
647 vector<unsigned char> vbuf;
648 int last_tick = 0;
649 uint32_t N = 0;
650 int MAX = tracks.size();
652 for(int i=0; i<MAX; i++){
654 //chunk id
655 N = 0;
656 last_tick = 0;
657 vbuf.clear();
658 vbuf.push_back('M');
659 vbuf.push_back('T');
660 vbuf.push_back('r');
661 vbuf.push_back('k');
663 //chunk size (yet unknown)
665 vbuf.push_back(0x00);
666 vbuf.push_back(0x00);
667 vbuf.push_back(0x00);
668 vbuf.push_back(0x00);
670 track* t = tracks[i];
671 seqpat* s;
672 pattern* p;
673 mevent* e;
675 //change program for this track
677 //write events
678 s = t->head->next;
680 while(s){
681 e = s->p->events->next;
683 while(e){
685 if(e->tick > s->dur){
686 break;
688 switch(e->type){
689 case 0x80://note off
690 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
691 last_tick = e->tick+s->tick;
692 vbuf.push_back(0x80 | t->chan);
693 vbuf.push_back(e->value1);
694 vbuf.push_back(e->value2);
695 N += 3;
696 break;
697 case 0x90://note on
698 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
699 last_tick = e->tick+s->tick;
700 vbuf.push_back(0x90 | t->chan);
701 vbuf.push_back(e->value1);
702 vbuf.push_back(e->value2);
703 N += 3;
704 break;
705 case 0xA0://after touch
706 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
707 last_tick = e->tick+s->tick;
708 vbuf.push_back(0xA0 | t->chan);
709 vbuf.push_back(e->value1);
710 vbuf.push_back(e->value2);
711 N += 3;
712 break;
713 case 0xB0://control change
714 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
715 last_tick = e->tick+s->tick;
716 vbuf.push_back(0xB0 | t->chan);
717 vbuf.push_back(e->value1);
718 vbuf.push_back(e->value2);
719 N += 3;
720 break;
721 case 0xC0://program change
722 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
723 last_tick = e->tick+s->tick;
724 vbuf.push_back(0xC0 | t->chan);
725 vbuf.push_back(e->value1);
726 N += 2;
727 break;
728 case 0xD0://channel pressure
729 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
730 last_tick = e->tick+s->tick;
731 vbuf.push_back(0xD0 | t->chan);
732 vbuf.push_back(e->value1);
733 N += 2;
734 break;
735 case 0xE0://pitch wheel
736 N += tick2delta(e->tick+s->tick - last_tick,vbuf);
737 last_tick = e->tick+s->tick;
738 vbuf.push_back(0xE0 | t->chan);
739 vbuf.push_back(e->value1);
740 vbuf.push_back(e->value2);
741 N += 3;
742 break;
744 e = e->next;
747 s = s->next;
750 //end of track meta event
751 vbuf.push_back(0x00);
752 vbuf.push_back(0xff);
753 vbuf.push_back(0x2f);
754 vbuf.push_back(0x00);
755 N += 4;
757 N = htonl(N);
758 memcpy(buf,&N,4);
759 vbuf[4] = buf[0];
760 vbuf[5] = buf[1];
761 vbuf[6] = buf[2];
762 vbuf[7] = buf[3];
764 for(int i=0; i<vbuf.size(); i++){
765 buf[0] = vbuf[i];
766 file.write((const char*)buf,1);
770 file.close();
776 int getdelta(std::fstream& f){
777 unsigned char a,b,c,d;
779 f.read((char*)&a,1);
780 if(a<0x80){return a;}
782 f.read((char*)&b,1);
783 if(b<0x80){return ((a&0x7f)<<7) | b;}
785 f.read((char*)&c,1);
786 if(c<0x80){return ((a&0x7f)<<14) | ((b&0x7f)<<7) | c;}
788 f.read((char*)&d,1);
789 return ((a&0x7f)<<21) | ((b&0x7f)<<14) | ((c&0x7f)<<7) | d;
797 char fifths[15][8] = {
798 "Cb",
799 "Gb",
800 "Db",
801 "Ab",
802 "Eb",
803 "Bb",
804 "F",
805 "C",
806 "G",
807 "D",
808 "A",
809 "E",
810 "B",
811 "F#",
812 "C#"
816 int loadsmf(const char* filename){
817 if(filename == NULL){
818 return -1;
821 fstream file;
822 file.open(filename, fstream::in);
824 if(!file.is_open()){
825 printf("error, cant open file for saving\n");
826 return -1;
829 last_filename = filename;
830 set_last_dir(filename);
832 clear();
834 unsigned char buf[64];
835 char* abuf;
836 char sbuf[256];
837 char* tbuf;
838 uint32_t size;
839 uint32_t micros;
840 int N = 0;
841 int tempo_flag = 0;
843 std::list<pattern*> patlist;
844 std::vector<int> chanlist;
845 std::vector<int> proglist;
846 std::vector<int> banklist;
848 std::vector<track*> extratracks;
850 std::vector<char*> tracknames;
852 int maxblockdur = 0;
854 for(int i=0; i<16; i++){
855 extratracks.push_back(NULL);
858 while(!file.eof()){
860 file.read((char*)buf,4);
861 if(memcmp(buf,"MThd",4)){
862 printf("missing header, probably not a midi file\n");
863 file.close();
864 return -1;
866 //printf("MThd\n");
867 scope_print("Standard Midi File\n");
869 file.read((char*)buf,4);
870 if(buf[3] != 6){
871 printf("header has wrong size, probably a broken midi file\n");
872 scope_print("error: bad header size");
873 file.close();
874 return -1;
876 //printf("header size\n");
878 file.read((char*)buf,2);
879 if(buf[0] != 0){
880 printf("bad smf type code, probably a broken midi file\n");
881 scope_print("error: bad smf type");
882 file.close();
883 return -1;
887 int smftype;
888 switch(buf[1]){
889 case 0: smftype=0; break;
890 case 1: smftype=1; break;
891 case 2: smftype=2; break;
892 default:
893 printf("bad smf type code, probably a broken midi file\n");
894 scope_print("error: bad smf type");
895 file.close();
896 return -1;
899 snprintf(sbuf,256," type: %d\n",smftype);
900 scope_print(sbuf);
902 file.read((char*)buf,2);
903 size = ntohs(*(unsigned short*)buf);
904 if(size==0){
905 printf("track count of zero, probably a broken midi file\n");
906 scope_print("error: zero tracks");
907 file.close();
908 return -1;
910 int ntracks = size;
912 snprintf(sbuf,256," tracks: %d\n",ntracks);
913 scope_print(sbuf);
916 int tpb = TICKS_PER_BEAT;
917 file.read((char*)buf,2);
918 size = ntohs(*(unsigned short*)buf);
919 if(size >> 15 == 0){
920 tpb = size&0x7fff;
921 snprintf(sbuf,256," time division: %d ticks per beat\n",tpb);
922 scope_print(sbuf);
924 else{
925 int fps = size&0x7fff;
926 snprintf(sbuf,256," time division: %d frames per second (wrong)\n",fps);
927 scope_print(sbuf);
928 scope_print("error: smpte time division not support\n");
929 file.close();
930 return -1;
934 int trackindex = 0;
935 /*** read tracks ***/
936 file.read((char*)buf,4);
937 while(!file.eof()){
939 if(memcmp(buf,"MTrk",4)){
940 printf("bad track header, probably a broken midi file\n");
941 file.close();
942 return -1;
945 pattern* p = new pattern();
946 mevent* e;
948 trackindex++;
949 snprintf(sbuf,256," track %d\n",trackindex);
950 scope_print(sbuf);
952 file.read((char*)buf,4);
953 size = ntohl(*(unsigned long*)buf);
954 if(size==0){
955 printf("empty track\n");
956 file.close();
957 return -1;
960 int time = 0;
961 int tick = 0;
962 int endtrack=0;
964 chanlist.push_back(-1);
965 banklist.push_back(-1);
966 proglist.push_back(-1);
968 tracknames.push_back(NULL);
970 /***read events***/
971 while(!endtrack){
973 int delta = getdelta(file);
974 if(delta < 0){
975 printf("bad delta time, broken midi file\n");
976 file.close();
977 return -1;
979 time += delta;
980 tick = time*TICKS_PER_BEAT/tpb;
982 if(tick > maxblockdur){
983 maxblockdur = tick;
986 int last_byte0;
987 file.read((char*)buf,1);
988 int byte0 = buf[0];
989 int byte1 = -1;
991 if(byte0 < 0x80){//implicit byte0
992 byte1 = byte0;
993 byte0 = last_byte0;
995 last_byte0 = byte0;
997 if(byte0 < 0xf0){//channel event
999 int type = byte0&0xf0;
1000 int chan = byte0&0x0f;
1002 if(chanlist[N]==-1){
1003 chanlist[N]=chan;
1006 if(byte1<0){//didnt read byte1 yet
1007 file.read((char*)buf,1);
1008 byte1 = buf[0];
1013 int val1 = byte1;
1014 int val2;
1016 if(!(type == 0xC0 || type == 0xD0)){
1017 file.read((char*)buf,1);
1018 val2 = buf[0];
1021 e = new mevent(type,tick,val1);
1024 switch(type){
1025 case 0x90://note on
1026 if(val2==0){//fake note off
1027 e->type = 0x80;
1029 e->value2 = val2;
1030 break;
1031 case 0x80://note off
1032 case 0xA0://aftertouch
1033 case 0xB0://controller change
1034 case 0xE0://pitchbend
1035 if(type==0xB0 && val1==0x00 && banklist[N]==-1){
1036 banklist[N]=val2;
1038 e->value2 = val2;
1039 break;
1041 case 0xC0://program change
1042 if(proglist[N]==-1){
1043 proglist[N]=val1;
1045 break;
1046 case 0xD0://channel pressure
1047 break;
1048 default:
1049 printf("unrecognized channel event %d\n",type);
1050 file.close();
1051 return -1;
1054 if(chan!=chanlist[N]){//put event in the a misfit track
1055 //printf("mistfit N=%d chan=%d type=%d\n",chanlist[N],chan,type);
1056 if(extratracks[chan] == NULL){
1057 track* t = new track();
1058 t->chan = chan;
1059 t->prog = -1;
1060 t->port = 0;
1061 t->bank = -1;
1063 extratracks[chan] = t;
1064 seqpat* s = new seqpat();
1065 t->head->next = s;
1066 s->prev = t->head;
1067 s->p = new pattern();
1068 //more track setup
1070 extratracks[chan]->head->next->p->insert(e,tick);
1072 else{//put it in a normal track
1073 p->append(e);
1077 else{/*** not a channel event ***/
1081 if(byte0 == 255){//meta events
1083 file.read((char*)buf,1);
1084 int meta = buf[0];
1087 size = getdelta(file);
1088 if(size < 0){
1089 printf("bad delta time\n");
1090 file.close();
1091 return -1;
1095 abuf = new char[size+1];
1097 switch(meta){
1098 case 0://sequence number
1100 snprintf(sbuf,256," %d sequence: ? ?\n",time);
1101 scope_print(sbuf);
1102 if(size != 2){
1103 printf("bad sequence number data length: %d\n",size);
1104 file.close();
1105 return -1;
1107 file.read((char*)buf,2);
1108 break;
1109 case 1://text event
1110 file.read(abuf,size);
1111 abuf[size]='\0';
1112 asprintf(&tbuf," %d text: \"%s\"\n",time,abuf);
1113 scope_print(tbuf);
1114 free(tbuf);
1116 ui->info_text->buffer()->append(abuf);
1117 ui->info_text->buffer()->append("\n");
1119 break;
1120 case 2://copyright notice
1121 file.read((char*)abuf,size);
1122 abuf[size]='\0';
1123 asprintf(&tbuf," %d copyright: \"%s\"\n",time,abuf);
1124 scope_print(tbuf);
1125 free(tbuf);
1126 break;
1127 case 3://track name
1128 file.read((char*)abuf,size);
1129 abuf[size]='\0';
1130 asprintf(&tbuf," %d track name: \"%s\"\n",time,abuf);
1131 scope_print(tbuf);
1132 free(tbuf);
1134 tracknames[N] = (char*)malloc(sizeof(char)*(size+1));
1135 strncpy(tracknames[N],abuf,size+1);
1137 break;
1138 case 4://instrument name
1139 file.read((char*)abuf,size);
1140 abuf[size]='\0';
1141 asprintf(&tbuf," %d instrument name: \"%s\"\n",time,abuf);
1142 scope_print(tbuf);
1143 free(tbuf);
1144 break;
1145 case 5://lyrics
1146 file.read((char*)abuf,size);
1147 abuf[size]='\0';
1148 asprintf(&tbuf," %d lyrics: \"%s\"\n",time,abuf);
1149 scope_print(tbuf);
1150 free(tbuf);
1151 break;
1152 case 6://marker
1153 file.read((char*)abuf,size);
1154 abuf[size]='\0';
1155 asprintf(&tbuf," %d marker: \"%s\"\n",time,abuf);
1156 scope_print(tbuf);
1157 free(tbuf);
1158 break;
1159 case 7://cue point
1160 file.read((char*)abuf,size);
1161 abuf[size]='\0';
1162 asprintf(&tbuf," %d cue point: \"%s\"\n",time,abuf);
1163 scope_print(tbuf);
1164 free(tbuf);
1165 break;
1166 case 32://channel prefix
1167 if(size!=1){
1168 printf("bad channel prefix data size: %d\n",size);
1169 file.close();
1170 return -1;
1172 file.read((char*)buf,1);
1173 asprintf(&tbuf," %d channel prefix: %d\n",time,buf[0]);
1174 scope_print(tbuf);
1175 free(tbuf);
1176 break;
1177 case 47://end of track
1178 if(size!=0){
1179 printf("end of track has non zero data size: %d\n",size);
1180 file.close();
1181 return -1;
1183 endtrack=1;
1184 break;
1185 case 81://set tempo
1186 if(size!=3){
1187 printf("set tempo has non-3 data size: %d\n",size);
1188 file.close();
1189 return -1;
1191 file.read((char*)buf,3);
1193 buf[3] = buf[2];
1194 buf[2] = buf[1];
1195 buf[1] = buf[0];
1196 buf[0] = 0;
1198 micros = *(unsigned*)buf;
1199 micros = ntohl(micros);
1201 asprintf(&tbuf," %d set tempo: %d us/quarter\n",time,micros);
1202 scope_print(tbuf);
1203 free(tbuf);
1205 if(time==0){
1206 tempo_flag = 1;
1207 set_beats_per_minute(60000000/micros);
1210 break;
1211 case 84://smpte offset
1212 if(size!=5){
1213 printf("smpte offset has non-5 data size: %d\n",size);
1214 file.close();
1215 return -1;
1217 file.read((char*)buf,5);
1218 asprintf(&tbuf," %d smpte offset: ?\n",time);
1219 scope_print(tbuf);
1220 free(tbuf);
1221 break;
1222 case 88://time signature
1223 if(size!=4){
1224 printf("time signature has non-4 data size: %d\n",size);
1225 file.close();
1226 return -1;
1228 file.read((char*)buf,4);
1229 asprintf(&tbuf," %d time signature: %d/%d\n",time,buf[0],1<<buf[1]);
1230 scope_print(tbuf);
1231 free(tbuf);
1232 break;
1233 case 89://key signature
1234 if(size!=2){
1235 printf("key signature has non-2 data size: %d\n",size);
1236 file.close();
1237 return -1;
1239 file.read((char*)buf,2);
1240 asprintf(&tbuf," %d key signature: %s %s\n",time,fifths[(signed char)buf[0]+7],buf[1]?"minor":"major");
1241 scope_print(tbuf);
1242 free(tbuf);
1243 break;
1244 case 127://sequencer specific
1245 file.read((char*)abuf,size);
1246 abuf[size]='\0';
1247 asprintf(&tbuf," %d sequencer specific: \"%s\"\n",time,abuf);
1248 scope_print(tbuf);
1249 free(tbuf);
1250 break;
1251 default://unknown meta event
1252 file.read((char*)abuf,size);
1253 abuf[size]='\0';
1254 asprintf(&tbuf," %d meta %d: \"%s\"\n",time,meta,abuf);
1255 scope_print(tbuf);
1256 free(tbuf);
1258 free(abuf);
1260 else if(byte0 == 240){//sysex event
1261 size = getdelta(file);
1262 if(size < 0){
1263 printf("bad delta time\n");
1264 return -1;
1266 abuf = new char[size+1];
1267 file.read((char*)abuf,size);
1268 abuf[size]='\0';
1270 asprintf(&tbuf," %d sysex: \"%s\"\n",time,abuf);
1271 scope_print(tbuf);
1272 free(tbuf);
1274 file.read((char*)buf,1);
1275 if(buf[0]!=0xf7){
1276 file.putback(buf[0]);
1278 else{
1279 scope_print(" end of sysex\n");
1284 free(abuf);
1286 else if(byte0 == 247){//divided sysex event
1287 size = getdelta(file);
1288 if(size < 0){
1289 printf("bad delta time\n");
1290 return -1;
1292 abuf = new char[size+1];
1293 file.read((char*)abuf,size);
1294 abuf[size]='\0';
1296 asprintf(&tbuf," %d sysex fragment: \"%s\"\n",time,abuf);
1297 scope_print(tbuf);
1298 free(tbuf);
1300 file.read((char*)buf,1);
1301 if(buf[0]!=0xf7){
1302 file.putback(buf[0]);
1304 else{
1305 scope_print(" end of sysex\n");
1307 free(abuf);
1309 else{
1310 printf("bad event type %d, broken midi file\n",byte0);
1311 file.close();
1312 return -1;
1319 if(proglist[N]==-1){
1320 proglist[N]=0;
1322 if(banklist[N]==-1){
1323 banklist[N]=0;
1325 if(chanlist[N]==-1){
1326 chanlist[N]=0;
1328 N++;
1331 p->fixdur();
1333 patlist.push_back(p);
1335 file.read((char*)buf,4);//read first byte of next track or EOF
1340 scope_print("End Of File\n\n");
1341 file.close();
1343 //TODO set up track settings using data remembered from the reading
1344 std::list<pattern*>::iterator p = patlist.begin();
1345 int i=0;
1346 while(p!=patlist.end()){
1347 track* t = new track();
1348 seqpat* s = new seqpat(i,0,128*64,*p);
1349 int Q = TICKS_PER_BEAT;
1350 s->dur = maxblockdur / Q * Q + Q;
1351 t->head->next = s;
1352 s->prev = t->head;
1353 t->skip = s;
1355 s->p->h = 360*i / 16;
1356 s->p->v = 0.8;
1357 while(s->p->h > 360){s->p->h -= 360;}
1358 s->p->regen_colors();
1360 t->chan = chanlist[i];
1361 t->prog = proglist[i];
1362 t->bank = banklist[i];
1363 t->port = 0;
1365 if(tracknames[i]){
1366 t->name = tracknames[i];
1368 else{
1369 t->name = (char*)malloc(8);
1370 t->name[0] = '\0';
1373 add_track(t);
1374 p++;
1375 i++;
1378 if(tempo_flag == 0){
1379 set_beats_per_minute(120);
1382 set_rec_track(0);
1383 ui->track_info->set_rec(0);
1384 ui->track_info->update();
1386 ui->arranger->redraw();
1388 update_config_gui();
1390 reset_backend(0);
1392 return 0;