Read combined blocks of additional data correctly
[jelmer/ptabtools.git] / ptb.c
1 /*
2    Parser library for the PowerTab (PTB) file format
3    (c) 2004-2005: Jelmer Vernooij <jelmer@samba.org>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
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.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #include <stdio.h>
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <string.h>
24 #include <stdarg.h>
25 #include "dlinklist.h"
26
27 #ifndef __PRETTY_FUNCTION__
28 #define __PRETTY_FUNCTION__ ""
29 #endif
30
31 #ifdef HAVE_CONFIG_H
32 #  include "config.h"
33 #endif
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #else
38 #include <io.h>
39 typedef int ssize_t;
40 #endif
41
42 #ifdef HAVE_STDINT_H
43 #  include <stdint.h>
44 #endif
45
46 #define PTB_CORE
47 #include "ptb.h"
48
49 int assert_is_fatal = 0;
50
51 #define ptb_assert(ptb, expr) \
52         if (!(expr)) { ptb_debug("---------------------------------------------"); \
53                 ptb_debug("file: %s, line: %d (%s): assertion failed: %s. Current position: 0x%lx", __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr, ptb->curpos); \
54                 if(assert_is_fatal) abort(); \
55         }
56
57 #define malloc_p(t,n) (t *) calloc(sizeof(t), n)
58
59 #define GET_ITEM(bf, dest, type)  ((bf)->mode == O_WRONLY?(type *)(*(dest)):malloc_p(type, 1))
60
61 #define ptb_assert_0(ptb, expr) \
62         if(expr) ptb_debug("%s == 0x%x!", #expr, expr); \
63 /*      ptb_assert(ptb, (expr) == 0); */
64
65 struct ptb_list {
66         struct ptb_list *prev, *next;
67 };
68
69 struct ptb_section_handler {
70         char *name;
71         int (*handler) (struct ptbf *, const char *section, struct ptb_list **ret);
72 };
73
74 extern struct ptb_section_handler ptb_section_handlers[];
75
76 void ptb_debug(const char *fmt, ...);
77
78 int debugging = 0;
79
80 static ssize_t ptb_read(struct ptbf *f, void *data, ssize_t length)
81 {
82         ssize_t ret = read(f->fd, data, length);
83 #define read DONT_USE_READ
84
85         if(ret == -1) { 
86                 perror("read"); 
87                 ptb_assert(f, 0);
88         } else if (ret != length) {
89                 ptb_debug("Expected read of %d bytes, got %d\n", length, ret);
90         }
91
92         f->curpos+=ret;
93         
94         return ret;
95 }
96
97 static ssize_t ptb_write(struct ptbf *f, void *data, size_t length)
98 {
99         ssize_t ret = write(f->fd, data, length);
100 #define write DONT_USE_WRITE
101
102         if(ret == -1) { 
103                 perror("write"); 
104                 ptb_assert(f, 0);
105         }
106
107         f->curpos+=ret;
108         
109         return ret;
110 }
111
112 static ssize_t ptb_data(struct ptbf *f, void *data, size_t length)
113 {
114         switch (f->mode) {
115         case O_RDONLY: return ptb_read(f, data, length);
116         case O_WRONLY: return ptb_write(f, data, length);
117         }
118         ptb_assert(f, 0);
119         return 0;
120 }
121
122 static ssize_t ptb_data_constant(struct ptbf *f, unsigned char expected) 
123 {
124         unsigned char real;
125         ssize_t ret;
126         
127         if (f->mode == O_WRONLY) {
128                 ret = ptb_data(f, &expected, 1);
129         } else {
130                         ret = ptb_data(f, &real, 1);
131         
132                 if(real != expected) {
133                         ptb_debug("%04x: Expected %02x, got %02x", f->curpos-1, expected, real);
134                         ptb_assert(f, 0);
135                 }
136         }
137
138         return ret;
139 }
140
141 static ssize_t ptb_data_constant_string(struct ptbf *f, const char *expected, int length)
142 {
143         int i, ret = 0;
144         for (i = 0; i < length; i++) {
145                 ret = ptb_data_constant(f, expected[i]);
146         }
147
148         return ret;
149 }
150
151 static ssize_t ptb_data_unknown(struct ptbf *f, size_t length) {
152         char unknown[255];
153         ssize_t ret;
154         off_t oldpos = f->curpos;
155         size_t i;
156
157         memset(unknown, 0, length);
158         ret = ptb_data(f, unknown, length);
159         if(debugging) {
160                 for(i = 0; i < length; i++) 
161                         ptb_debug("Unknown[%04lx]: %02x", oldpos + i, unknown[i]);
162         }
163         return ret;
164 }
165
166 static ssize_t ptb_read_string(struct ptbf *f, char **dest)
167 {
168         uint8_t shortlength;
169         uint16_t length;
170         char *data;
171         ptb_data(f, &shortlength, 1);
172
173         /* If length is 0xff, this is followed by a uint16_t length */
174         if(shortlength == 0xff) {
175                 if(ptb_data(f, &length, 2) < 2) return -1;
176         } else {
177                 length = shortlength;
178         }
179
180         if(length) {
181                 data = malloc_p(char, length+1);
182                 if(ptb_data(f, data, length) < length) return -1;
183                 ptb_debug("Read string: %s", data);
184                 *dest = data;
185         } else {
186                 ptb_debug("Empty string");
187                 *dest = NULL;
188         }
189
190         return length;
191 }
192
193 static ssize_t ptb_write_string(struct ptbf *f, char **dest)
194 {
195         uint8_t shortlength;
196         uint16_t length = 0;
197         
198         if (*dest == NULL) {
199                 shortlength = 0;
200         } else if (strlen(*dest) >= 0xff) {
201                 shortlength = 0xff;
202                 length = strlen(*dest);
203         } else {
204                 shortlength = strlen(*dest);
205         }
206         
207         ptb_data(f, &shortlength, 1);
208
209         /* If length is 0xff, this is followed by a uint16_t length */
210         if(shortlength == 0xff) {
211                 if(ptb_data(f, &length, 2) < 2) return -1;
212         } else {
213                 length = shortlength;
214         }
215
216         if(ptb_data(f, *dest, length) < length) return -1;
217
218         return length;
219 }
220
221 static ssize_t ptb_data_string(struct ptbf *bf, char **dest) {
222         switch (bf->mode) {
223         case O_RDONLY: return ptb_read_string(bf, dest);
224         case O_WRONLY: return ptb_write_string(bf, dest);
225         default: ptb_assert(bf, 0);
226         }
227         return 0;
228 }
229
230 static ssize_t ptb_data_font(struct ptbf *f, struct ptb_font *dest) {
231         int ret = 0;
232         ret+=ptb_data_string(f, &dest->family);
233         ret+=ptb_data(f, &dest->size, 1);
234         ret+=ptb_data_unknown(f, 5);
235         ret+=ptb_data(f, &dest->thickness, 1);
236         ret+=ptb_data_unknown(f, 2);
237         ret+=ptb_data(f, &dest->italic, 1);
238         ret+=ptb_data(f, &dest->underlined, 1);
239         ret+=ptb_data_unknown(f, 4);
240         return ret;
241 }
242
243 static ssize_t ptb_data_header(struct ptbf *f, struct ptb_hdr *hdr)
244 {
245         ptb_data_constant_string(f, "ptab", 4);
246
247         ptb_data(f, &hdr->version, 2);
248         ptb_data(f, &hdr->classification, 1);
249
250         switch(hdr->classification) {
251         case CLASSIFICATION_SONG:
252                 ptb_data_unknown(f, 1); /* FIXME */
253                 ptb_data_string(f, &hdr->class_info.song.title);
254                 ptb_data_string(f, &hdr->class_info.song.artist);
255
256                 ptb_data(f, &hdr->class_info.song.release_type, 1);
257
258                 switch(hdr->class_info.song.release_type) {
259                 case RELEASE_TYPE_PR_AUDIO:
260                         ptb_data(f, &hdr->class_info.song.release_info.pr_audio.type, 1);
261                         ptb_data_string(f, &hdr->class_info.song.release_info.pr_audio.album_title);
262                         ptb_data(f, &hdr->class_info.song.release_info.pr_audio.year, 2);
263                         ptb_data(f, &hdr->class_info.song.release_info.pr_audio.is_live_recording, 1);
264                         break;
265                 case RELEASE_TYPE_PR_VIDEO:
266                         ptb_data_string(f, &hdr->class_info.song.release_info.pr_video.video_title);
267                         ptb_data(f, &hdr->class_info.song.release_info.pr_video.is_live_recording, 1);
268                         break;
269                 case RELEASE_TYPE_BOOTLEG:
270                         ptb_data_string(f, &hdr->class_info.song.release_info.bootleg.title);
271                         ptb_data(f, &hdr->class_info.song.release_info.bootleg.day, 2);
272                         ptb_data(f, &hdr->class_info.song.release_info.bootleg.month, 2);
273                         ptb_data(f, &hdr->class_info.song.release_info.bootleg.year, 2);
274                         break;
275                 case RELEASE_TYPE_UNRELEASED:
276                         break;
277
278                 default:
279                         fprintf(stderr, "Unknown release type: %d\n", hdr->class_info.song.release_type);
280                         break;
281                 }
282
283                 ptb_data(f, &hdr->class_info.song.is_original_author_unknown, 1);
284                 ptb_data_string(f, &hdr->class_info.song.music_by);
285                 ptb_data_string(f, &hdr->class_info.song.words_by);
286                 ptb_data_string(f, &hdr->class_info.song.arranged_by);
287                 ptb_data_string(f, &hdr->class_info.song.guitar_transcribed_by);
288                 ptb_data_string(f, &hdr->class_info.song.bass_transcribed_by);
289                 ptb_data_string(f, &hdr->class_info.song.copyright);
290                 ptb_data_string(f, &hdr->class_info.song.lyrics);
291                 ptb_data_string(f, &hdr->guitar_notes);
292                 ptb_data_string(f, &hdr->bass_notes);
293                 break;
294         case CLASSIFICATION_LESSON:
295                 ptb_data_string(f, &hdr->class_info.lesson.title);
296                 ptb_data_string(f, &hdr->class_info.lesson.artist);
297                 ptb_data(f, &hdr->class_info.lesson.style, 2);
298                 ptb_data(f, &hdr->class_info.lesson.level, 1);
299                 ptb_data_string(f, &hdr->class_info.lesson.author);
300                 ptb_data_string(f, &hdr->guitar_notes);
301                 ptb_data_string(f, &hdr->class_info.lesson.copyright);
302                 break;
303
304         default:
305                 fprintf(stderr, "Unknown classification: %d\n", hdr->classification);
306                 break;
307
308         }
309
310         return 0;
311 }
312
313 int debug_level = 0;
314
315 void ptb_debug(const char *fmt, ...) 
316 {
317         va_list ap;
318         int i;
319         if(debugging == 0) return;
320
321         /* Add spaces */
322         for(i = 0; i < debug_level; i++) fprintf(stderr, " ");
323
324         va_start(ap, fmt);
325         vfprintf(stderr, fmt, ap);
326         va_end(ap);
327         fputc('\n', stderr);
328 }
329
330 static int ptb_read_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result) {
331         int i;
332         uint16_t unknownval;
333         uint16_t l;
334         uint16_t length;
335         uint16_t header;
336         uint16_t nr_items;
337         int ret = 0;
338
339         *result = NULL;
340
341         ret+=ptb_data(bf, &nr_items, 2);        
342         if(ret == 0 || nr_items == 0x0) return 1; 
343         ret+=ptb_data(bf, &header, 2);
344
345         ptb_debug("Going to read %d items", nr_items);
346
347         if(header == 0xffff) { /* New section */
348                 char *my_section_name;
349                 /* Read Section */
350                 ret+=ptb_data(bf, &unknownval, 2);
351
352                 if(unknownval != 0x0001) {
353                         fprintf(stderr, "Unknownval: %04x\n", unknownval);
354                         return 0;
355                 }
356
357                 ret+=ptb_data(bf, &length, 2);
358
359                 my_section_name = malloc_p(char, length + 1);
360                 ret+=ptb_data(bf, my_section_name, length);
361
362         } else if(header & 0x8000) {
363         } else { 
364                 ptb_debug("Expected new item type (%s), got %04x %02x\n", assumed_type, nr_items, header);
365                 ptb_assert(bf, 0);
366                 return 0;
367         }
368
369         for(i = 0; ptb_section_handlers[i].name; i++) {
370                 if(!strcmp(ptb_section_handlers[i].name, assumed_type)) {
371                         break;
372                 }
373         }
374
375         if(!ptb_section_handlers[i].handler) {
376                 fprintf(stderr, "Unable to find handler for section %s\n", assumed_type);
377                 return 0;
378         }
379
380         for(l = 0; l < nr_items; l++) {
381                 struct ptb_list *item;
382                 int ret;
383                 uint16_t next_thing;
384
385                 ptb_debug("%04x ============= Handling %s (%d of %d) =============", bf->curpos, assumed_type, l+1, nr_items);
386                 debug_level++;
387                 item = NULL;
388                 ret = ptb_section_handlers[i].handler(bf, ptb_section_handlers[i].name, (struct ptb_list **)&item);
389                 if (!ret) item = NULL;
390                 debug_level--;
391
392                 ptb_debug("%04x ============= END Handling %s (%d of %d) =============", bf->curpos, ptb_section_handlers[i].name, l+1, nr_items);
393
394                 if(!item) {
395                         fprintf(stderr, "Error parsing section '%s'\n", ptb_section_handlers[i].name);
396                 } else {
397                         DLIST_ADD_END((*result), item, struct ptb_list *);
398                 }
399                 
400                 if(l < nr_items - 1) {
401                         ret+=ptb_data(bf, &next_thing, 2);
402                         if(!(next_thing & 0x8000)) {
403                                 ptb_debug("Warning: got %04x, expected | 0x8000\n", next_thing);
404                                 ptb_assert(bf, 0);
405                         }
406                 }
407         }
408
409         return 1;
410 }
411
412 static int generate_header_id(struct ptbf *bf, const char *assumed_type)
413 {
414         static int i = 0;
415         /* FIXME */
416         return ++i;
417 }
418
419 static int ptb_write_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result) 
420 {
421         int i;
422         uint16_t length;
423         uint16_t header;
424         uint16_t id = 0x20;
425         uint16_t nr_items;
426         struct ptb_list *gl;
427         int ret = 0;
428
429         DLIST_LEN(*result, nr_items, struct ptb_list *);
430
431         ret+=ptb_data(bf, &nr_items, 2);        
432         if(nr_items == 0x0) return 1; 
433
434         header = generate_header_id(bf, assumed_type);
435         if (header == 0) header = 0xffff;
436
437         ret+=ptb_data(bf, &header, 2);
438
439         ptb_debug("Going to write %d items", nr_items);
440
441         if (header == 0xffff) {
442                 uint16_t unknownval = 0x0001; /* FIXME */
443
444                 ret+=ptb_data(bf, &unknownval, 2);
445                 length = strlen(assumed_type);
446                 ret+=ptb_data(bf, &length, 2);
447                 ret+=ptb_data(bf, (void *)assumed_type, length);
448         }
449
450
451         for(i = 0; ptb_section_handlers[i].name; i++) {
452                 if(!strcmp(ptb_section_handlers[i].name, assumed_type)) {
453                         break;
454                 }
455         }
456
457         if(!ptb_section_handlers[i].handler) {
458                 fprintf(stderr, "Unable to find handler for section %s\n", assumed_type);
459                 return 0;
460         }
461
462         gl = *result;
463         while(gl) 
464         {
465                 debug_level++;
466                 ptb_section_handlers[i].handler(bf, ptb_section_handlers[i].name, (struct ptb_list **)&gl);
467                 debug_level--;
468
469                 if(gl->next) {
470                         ret+=ptb_data(bf, &id, 2);
471                 }
472                 gl = gl->next;
473         }
474
475         return 1;
476
477 }
478
479 static int ptb_data_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result)
480 {
481         switch (bf->mode) {
482         case O_RDONLY: return ptb_read_items(bf, assumed_type, result);
483         case O_WRONLY: return ptb_write_items(bf, assumed_type, result);
484         default: ptb_assert(bf, 0);
485         }
486         return 0;
487 }
488
489
490
491 void ptb_set_debug(int level) { debugging = level; }
492
493 void ptb_set_asserts_fatal(int y) { assert_is_fatal = y; }
494
495 static void ptb_data_instrument(struct ptbf *bf, int i)
496 {
497         ptb_data_items(bf, "CGuitar", (struct ptb_list **)&bf->instrument[i].guitars);
498         ptb_data_items(bf, "CChordDiagram",(struct ptb_list **) &bf->instrument[i].chorddiagrams);
499         ptb_data_items(bf, "CFloatingText",(struct ptb_list **) &bf->instrument[i].floatingtexts);
500         ptb_data_items(bf, "CGuitarIn",(struct ptb_list **) &bf->instrument[i].guitarins);
501         ptb_data_items(bf, "CTempoMarker", (struct ptb_list **)&bf->instrument[i].tempomarkers);
502         ptb_data_items(bf, "CDynamic", (struct ptb_list **)&bf->instrument[i].dynamics);
503         ptb_data_items(bf, "CSectionSymbol", (struct ptb_list **)&bf->instrument[i].sectionsymbols);
504         ptb_data_items(bf, "CSection", (struct ptb_list **)&bf->instrument[i].sections);
505 }
506
507 static ssize_t ptb_data_file(struct ptbf *bf)
508 {
509         int i;
510         if(ptb_data_header(bf, &bf->hdr) < 0) {
511                 fprintf(stderr, "Error parsing header\n");      
512                 return -1;
513         } else if(debugging) {
514                 fprintf(stderr, "Header parsed correctly\n");
515         }
516
517         for(i = 0; i < 2; i++) {
518                 ptb_data_instrument(bf, i);
519         }
520
521         ptb_data_font(bf, &bf->tablature_font);
522         ptb_data_font(bf, &bf->chord_name_font);
523         ptb_data_font(bf, &bf->default_font);
524
525         ptb_data_unknown(bf, 12);
526         return 0;
527 }
528
529 struct ptbf *ptb_read_file(const char *file)
530 {
531         struct ptbf *bf = malloc_p(struct ptbf, 1);
532
533         bf->mode = O_RDONLY;
534         bf->fd = open(file, bf->mode
535 #ifdef O_BINARY
536                                   | O_BINARY
537 #endif
538                                   );
539
540         strncpy(bf->data, "abc", 3);
541
542         bf->filename = strdup(file);
543
544         if(bf->fd < 0) return NULL;
545
546         bf->curpos = 1;
547
548         if (ptb_data_file(bf) == -1) 
549                 return NULL;
550
551         close(bf->fd);
552         return bf;
553 }
554
555 int ptb_write_file(const char *file, struct ptbf *bf)
556 {
557         bf->mode = O_WRONLY;
558         bf->fd = creat(file, 0644);
559
560         strncpy(bf->data, "abc", 3);
561
562         bf->filename = strdup(file);
563
564         if(bf->fd < 0) return -1;
565
566         bf->curpos = 1;
567
568         if (ptb_data_file(bf) == -1) 
569                 return -1;
570
571         close(bf->fd);
572         return 0;
573 }
574
575 static int handle_unknown (struct ptbf *bf, const char *section, struct ptb_list **dest) {
576         fprintf(stderr, "Unknown section '%s'\n", section);     
577         return 1; 
578 }
579
580 static int handle_CGuitar (struct ptbf *bf, const char *section, struct ptb_list **dest) {
581         struct ptb_guitar *guitar = GET_ITEM(bf, dest, struct ptb_guitar);
582
583         ptb_data(bf, &guitar->index, 1);
584         ptb_data_string(bf, &guitar->title);
585
586         ptb_data(bf, &guitar->midi_instrument, 1);
587         ptb_data(bf, &guitar->initial_volume, 1);
588         ptb_data(bf, &guitar->pan, 1);
589         ptb_data(bf, &guitar->reverb, 1);
590         ptb_data(bf, &guitar->chorus, 1);
591         ptb_data(bf, &guitar->tremolo, 1);
592
593         ptb_data(bf, &guitar->simulate, 1);
594         ptb_data(bf, &guitar->capo, 1);
595                 
596         ptb_data_string(bf, &guitar->type);
597
598         ptb_data(bf, &guitar->half_up, 1);
599         ptb_data(bf, &guitar->nr_strings, 1);
600
601         if (bf->mode == O_RDONLY) {
602                 guitar->strings = malloc_p(uint8_t, guitar->nr_strings);
603         }
604
605         ptb_data(bf, guitar->strings, guitar->nr_strings);
606
607         *dest = (struct ptb_list *)guitar;
608
609         return 1;
610 }
611
612
613 static int handle_CFloatingText (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
614         struct ptb_floatingtext *text = GET_ITEM(bf, dest, struct ptb_floatingtext);
615
616         ptb_data_string(bf, &text->text);
617         ptb_data(bf, &text->beginpos, 1);
618         ptb_data_unknown(bf, 15);
619         ptb_data(bf, &text->alignment, 1);
620         ptb_debug("Align: %x", text->alignment);
621         ptb_assert(bf, (text->alignment &~ ALIGN_TIMESTAMP) == ALIGN_LEFT || 
622                                    (text->alignment &~ ALIGN_TIMESTAMP) == ALIGN_CENTER || 
623                                    (text->alignment &~ ALIGN_TIMESTAMP) == ALIGN_RIGHT);
624         ptb_data_font(bf, &text->font);
625         
626         *dest = (struct ptb_list *)text;
627
628         return 1;
629 }
630
631 static int handle_CSection (struct ptbf *bf, const char *sectionname, struct ptb_list **dest) { 
632         struct ptb_section *section = GET_ITEM(bf, dest, struct ptb_section);
633
634         ptb_data_constant(bf, 0x32);
635         ptb_data_unknown(bf, 11);
636         ptb_data(bf, &section->properties, 2);
637         ptb_data_unknown(bf, 2);
638         ptb_data(bf, &section->end_mark, 1);
639         ptb_assert(bf, (section->end_mark &~ END_MARK_TYPE_NORMAL 
640                            & ~END_MARK_TYPE_DOUBLELINE
641                            & ~END_MARK_TYPE_REPEAT) < 24);
642         ptb_data(bf, &section->position_width, 1);
643         ptb_data_unknown(bf, 5);
644         ptb_data(bf, &section->key_extra, 1);
645         ptb_data_unknown(bf, 1);
646         ptb_data(bf, &section->meter_type, 2);
647         ptb_data(bf, &section->beat_info, 1);
648         ptb_data(bf, &section->metronome_pulses_per_measure, 1);
649         ptb_data(bf, &section->letter, 1);
650         ptb_data_string(bf, &section->description);
651
652         ptb_data_items(bf, "CDirection", (struct ptb_list **)&section->directions);
653         ptb_data_items(bf, "CChordText", (struct ptb_list **)&section->chordtexts);
654         ptb_data_items(bf, "CRhythmSlash", (struct ptb_list **)&section->rhythmslashes);
655         ptb_data_items(bf, "CStaff", (struct ptb_list **)&section->staffs);
656         ptb_data_items(bf, "CMusicBar", (struct ptb_list **)&section->musicbars);
657
658         *dest = (struct ptb_list *)section;
659         return 1;
660 }
661
662 static int handle_CTempoMarker (struct ptbf *bf, const char *section, struct ptb_list **dest) {
663         struct ptb_tempomarker *tempomarker = GET_ITEM(bf, dest, struct ptb_tempomarker);
664
665         ptb_data(bf, &tempomarker->section, 1);
666         ptb_data_constant(bf, 0);
667         ptb_data(bf, &tempomarker->offset, 1);
668         ptb_data(bf, &tempomarker->bpm, 1);
669         ptb_data_constant(bf, 0);
670         ptb_data(bf, &tempomarker->type, 2);
671         ptb_data_string(bf, &tempomarker->description);
672
673         *dest = (struct ptb_list *)tempomarker;
674         return 1;
675 }
676
677
678 static int handle_CChordDiagram (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
679         struct ptb_chorddiagram *chorddiagram = GET_ITEM(bf, dest, struct ptb_chorddiagram);
680
681         ptb_data(bf, chorddiagram->name, 2);
682         ptb_data_unknown(bf, 3);
683         ptb_data(bf, &chorddiagram->type, 1);
684         ptb_data(bf, &chorddiagram->frets, 1);
685         ptb_data(bf, &chorddiagram->nr_strings, 1);
686         chorddiagram->tones = malloc_p(uint8_t, chorddiagram->nr_strings);
687         ptb_data(bf, chorddiagram->tones, chorddiagram->nr_strings);
688
689         *dest = (struct ptb_list *)chorddiagram;
690         return 1;
691 }
692
693 static int handle_CLineData (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
694         struct ptb_linedata *linedata = GET_ITEM(bf, dest, struct ptb_linedata);
695
696         ptb_data(bf, &linedata->tone, 1);
697         ptb_data(bf, &linedata->properties, 1);
698         ptb_assert_0(bf, linedata->properties
699                            & ~LINEDATA_PROPERTY_GHOST_NOTE
700                            & ~LINEDATA_PROPERTY_PULLOFF_FROM
701                            & ~LINEDATA_PROPERTY_HAMMERON_FROM
702                            & ~LINEDATA_PROPERTY_TIE
703                            & ~LINEDATA_PROPERTY_NATURAL_HARMONIC
704                            & ~LINEDATA_PROPERTY_MUTED);
705         ptb_data(bf, &linedata->transcribe, 1);
706         ptb_assert(bf, linedata->transcribe == LINEDATA_TRANSCRIBE_8VA 
707                            ||  linedata->transcribe == LINEDATA_TRANSCRIBE_15MA
708                            ||  linedata->transcribe == LINEDATA_TRANSCRIBE_8VB
709                            ||  linedata->transcribe == LINEDATA_TRANSCRIBE_15MB
710                            ||  linedata->transcribe == 0);
711                            
712         ptb_data(bf, &linedata->conn_to_next, 1);
713         
714         if(linedata->conn_to_next) { 
715                 linedata->bends = malloc_p(struct ptb_bend, 1);
716                 ptb_data(bf, linedata->bends, 4*linedata->conn_to_next);
717         } else {
718                 linedata->bends = NULL;
719         }
720
721         *dest = (struct ptb_list *)linedata;
722         return 1;
723 }
724
725
726 static int handle_CChordText (struct ptbf *bf, const char *section, struct ptb_list **dest) {
727         struct ptb_chordtext *chordtext = GET_ITEM(bf, dest, struct ptb_chordtext);
728
729         ptb_data(bf, &chordtext->offset, 1);
730         ptb_data(bf, chordtext->name, 2);
731
732         ptb_data(bf, &chordtext->properties, 1);
733         ptb_assert_0(bf, chordtext->properties 
734                            & ~CHORDTEXT_PROPERTY_NOCHORD
735                            & ~CHORDTEXT_PROPERTY_PARENTHESES
736                            & ~0xc0 /*FIXME*/
737                            & ~CHORDTEXT_PROPERTY_FORMULA_M
738                            & ~CHORDTEXT_PROPERTY_FORMULA_MAJ7);
739         ptb_data(bf, &chordtext->additions, 1);
740         ptb_assert_0(bf, chordtext->additions 
741                            & ~CHORDTEXT_ADD_9);
742         ptb_data(bf, &chordtext->alterations, 1);
743         ptb_data(bf, &chordtext->VII, 1);
744         ptb_assert_0(bf, chordtext->VII & ~CHORDTEXT_VII);
745
746         *dest = (struct ptb_list *)chordtext;
747         return 1;
748 }
749
750 static int handle_CGuitarIn (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
751         struct ptb_guitarin *guitarin = GET_ITEM(bf, dest, struct ptb_guitarin);
752
753         ptb_data(bf, &guitarin->section, 1);
754         ptb_data_constant(bf, 0x0); /* FIXME */
755         ptb_data(bf, &guitarin->staff, 1);
756         ptb_data(bf, &guitarin->offset, 1);
757         ptb_data(bf, &guitarin->rhythm_slash, 1);
758         ptb_data(bf, &guitarin->staff_in, 1);
759
760         *dest = (struct ptb_list *)guitarin;
761         return 1;
762 }
763
764
765 static int handle_CStaff (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
766         uint16_t next;
767         struct ptb_staff *staff = GET_ITEM(bf, dest, struct ptb_staff);
768
769         ptb_data(bf, &staff->properties, 1);
770         ptb_debug("Properties: %02x", staff->properties);
771         ptb_data(bf, &staff->highest_note, 1);
772         ptb_data(bf, &staff->lowest_note, 1);
773         ptb_data_unknown(bf, 2);
774
775         /* FIXME! */
776         ptb_data_items(bf, "CPosition", (struct ptb_list **)&staff->positions[0]);
777         /* This is ugly, but at least it works... */
778         if (bf->mode == O_RDONLY) {
779                 ptb_data(bf, &next, 2);
780                 lseek(bf->fd, -2, SEEK_CUR); bf->curpos-=2;
781                 if(next & 0x8000) {
782                         *dest = (struct ptb_list *)staff;
783                         staff->positions[1] = NULL;
784                         return 1;
785                 }
786         }
787
788         ptb_data_items(bf, "CPosition", (struct ptb_list **)&staff->positions[1]);
789         /* This is ugly, but at least it works... */
790         if (bf->mode == O_RDONLY) {
791                 ptb_data(bf, &next, 2);
792                 lseek(bf->fd, -2, SEEK_CUR);bf->curpos-=2;
793                 if(next & 0x8000) {
794                         *dest = (struct ptb_list *)staff;
795                         return 1;
796                 }
797         }
798
799         *dest = (struct ptb_list *)staff;
800         return 1;
801 }
802
803
804 static int handle_CPosition (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
805         struct ptb_position *position = GET_ITEM(bf, dest, struct ptb_position);
806         int i;
807
808         ptb_data(bf, &position->offset, 1);
809         ptb_data(bf, &position->properties, 2); 
810         ptb_assert_0(bf, position->properties 
811                            & ~POSITION_PROPERTY_IN_SINGLE_BEAM
812                            & ~POSITION_PROPERTY_IN_DOUBLE_BEAM
813                            & ~POSITION_PROPERTY_FIRST_IN_BEAM
814                            & ~POSITION_PROPERTY_LAST_IN_BEAM);
815         ptb_data(bf, &position->dots, 1);
816         ptb_assert_0(bf, position->dots &~ POSITION_DOTS_1 
817                                          & ~POSITION_DOTS_2 & ~POSITION_DOTS_REST & ~POSITION_DOTS_ARPEGGIO_UP);
818         ptb_data(bf, &position->palm_mute, 1);
819         ptb_assert_0(bf, position->palm_mute & ~POSITION_PALM_MUTE & ~POSITION_STACCATO & ~POSITION_ACCENT);
820         ptb_data(bf, &position->fermenta, 1);
821         ptb_assert_0(bf, position->fermenta
822                                         & ~POSITION_FERMENTA_LET_RING
823                                         & ~POSITION_FERMENTA_TRIPLET_1
824                                         & ~POSITION_FERMENTA_TRIPLET_2
825                                         & ~POSITION_FERMENTA_TRIPLET_3
826                                         & ~POSITION_FERMENTA_FERMENTA);
827         ptb_data(bf, &position->length, 1);
828         
829         ptb_data(bf, &position->nr_additional_data, 1);
830
831         position->additional = malloc_p(struct ptb_position_additional, position->nr_additional_data);
832         
833         for (i = 0; i < position->nr_additional_data; i++) {
834                 ptb_data(bf, &position->additional[i].start_volume, 1);
835                 ptb_data(bf, &position->additional[i].end_volume, 1);
836                 ptb_data(bf, &position->additional[i].duration, 1);
837                 ptb_data_unknown(bf, 1);
838         }
839
840         ptb_data_items(bf, "CLineData", (struct ptb_list **)&position->linedatas);
841
842         *dest = (struct ptb_list *)position;
843         return 1;
844 }
845
846 static int handle_CDynamic (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
847         struct ptb_dynamic *dynamic = GET_ITEM(bf, dest, struct ptb_dynamic);
848
849         ptb_data(bf, &dynamic->offset, 1);
850         ptb_data(bf, &dynamic->staff, 1);
851         ptb_data_unknown(bf, 3); /* FIXME */
852         ptb_data(bf, &dynamic->volume, 1);
853
854         *dest = (struct ptb_list *)dynamic;
855         return 1;
856 }
857
858 static int handle_CSectionSymbol (struct ptbf *bf, const char *section, struct ptb_list **dest) {
859         struct ptb_sectionsymbol *sectionsymbol = GET_ITEM(bf, dest, struct ptb_sectionsymbol);
860
861         ptb_data_unknown(bf, 5); /* FIXME */
862         ptb_data(bf, &sectionsymbol->repeat_ending, 2);
863
864         *dest = (struct ptb_list *)sectionsymbol;
865         return 1;
866 }
867
868 static int handle_CMusicBar (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
869         struct ptb_musicbar *musicbar = GET_ITEM(bf, dest, struct ptb_musicbar);
870                                                                                          
871         ptb_data(bf, &musicbar->offset, 1);
872         ptb_data(bf, &musicbar->properties, 1);
873         ptb_data_unknown(bf, 6);
874         ptb_data(bf, &musicbar->letter, 1);
875         ptb_data_string(bf, &musicbar->description);
876
877         *dest = (struct ptb_list *)musicbar; 
878         return 1;
879 }
880
881 static int handle_CRhythmSlash (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
882         struct ptb_rhythmslash *rhythmslash = GET_ITEM(bf, dest, struct ptb_rhythmslash);
883         
884         ptb_data(bf, &rhythmslash->offset, 1);
885         ptb_data(bf, &rhythmslash->properties, 1);
886         ptb_assert_0(bf, rhythmslash->properties & ~RHYTHMSLASH_PROPERTY_FIRST_IN_BEAM);
887         ptb_data(bf, &rhythmslash->dotted, 1);
888         ptb_data_constant(bf, 0);
889         ptb_data(bf, &rhythmslash->length, 1);
890         ptb_data_constant(bf, 0);
891
892         *dest = (struct ptb_list *)rhythmslash;
893         return 1;
894 }
895
896 static int handle_CDirection (struct ptbf *bf, const char *section, struct ptb_list **dest) { 
897         struct ptb_direction *direction = GET_ITEM(bf, dest, struct ptb_direction);
898
899         ptb_data_unknown(bf, 4); /* FIXME */
900
901         *dest = (struct ptb_list *)direction;
902         return 1;
903 }
904
905 struct ptb_section_handler ptb_section_handlers[] = {
906         {"CGuitar", handle_CGuitar },
907         {"CFloatingText", handle_CFloatingText },
908         {"CChordDiagram", handle_CChordDiagram },
909         {"CTempoMarker", handle_CTempoMarker},
910         {"CLineData", handle_CLineData },
911         {"CChordText", handle_CChordText },
912         {"CGuitarIn", handle_CGuitarIn },
913         {"CStaff", handle_CStaff },
914         {"CPosition", handle_CPosition },
915         {"CSection", handle_CSection },
916         {"CDynamic", handle_CDynamic },
917         {"CSectionSymbol", handle_CSectionSymbol },
918         {"CMusicBar", handle_CMusicBar },
919         {"CRhythmSlash", handle_CRhythmSlash },
920         {"CDirection", handle_CDirection },
921         { 0, handle_unknown}
922 };
923
924 const char *ptb_get_tone(ptb_tone id)
925 {
926         const char *chords[] = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", NULL };
927         if((sizeof(chords)/sizeof(chords[0])) < id) return "_UNKNOWN_CHORD_";
928         return chords[id];
929 }
930
931 const char *ptb_get_tone_full(ptb_tone id)
932 {
933         const char *chords[] = { "c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b", NULL };
934         if(id < 16 || sizeof(chords) < id-16) return "_UNKNOWN_CHORD_";
935         return chords[id-16];
936 }
937
938 static struct ptb_position *get_position(struct ptb_staff *staff, int offset)
939 {
940         int i;
941         for(i = 0; i < 2; i++) {
942                 struct ptb_position *p = staff->positions[i];
943                 while(p) {
944                         if(p->offset == offset) return p;
945                         p = p->next;
946                 }
947         }
948         return NULL;
949 }
950
951 void ptb_get_position_difference(struct ptb_section *section, int start, int end, int *bars, int *length)
952 {
953         long l = 0;
954         struct ptb_staff *staff = section->staffs;
955         struct ptb_position *gl = NULL;
956
957         while(staff) { 
958                 gl = get_position(staff, start);
959                 if(gl) break;
960                 staff = staff->next;
961         }
962
963         while(gl) {
964                 if(gl->offset >= end) break;
965                 l += 0x100 / gl->length;
966                 gl = gl->next;
967         }
968
969         *bars = l / 0x100;
970
971         *length = 0;
972         if(l % 0x100) *length = 0x100 / (l % 0x100) ;
973 }       
974
975 static void ptb_free_hdr(struct ptb_hdr *hdr)
976 {
977         if (hdr->classification == CLASSIFICATION_SONG) { 
978                 switch (hdr->class_info.song.release_type) {
979                 case RELEASE_TYPE_PR_AUDIO:
980                         free(hdr->class_info.song.release_info.pr_audio.album_title);
981                         break;
982                 case RELEASE_TYPE_PR_VIDEO:
983                         free(hdr->class_info.song.release_info.pr_video.video_title);
984                         break;
985                 case RELEASE_TYPE_BOOTLEG:
986                         free(hdr->class_info.song.release_info.bootleg.title);
987                         break;
988                 default: break;
989                 }
990                 free (hdr->class_info.song.title);
991                 free (hdr->class_info.song.artist);
992                 free (hdr->class_info.song.words_by);
993                 free (hdr->class_info.song.music_by);
994                 free (hdr->class_info.song.arranged_by);
995                 free (hdr->class_info.song.guitar_transcribed_by);
996                 free (hdr->class_info.song.lyrics);
997                 free (hdr->class_info.song.copyright);
998         } else if (hdr->classification == CLASSIFICATION_LESSON) {
999                 free(hdr->class_info.lesson.artist);
1000                 free(hdr->class_info.lesson.title);
1001                 free(hdr->class_info.lesson.author);
1002                 free(hdr->class_info.lesson.copyright);
1003         }
1004
1005         free(hdr->guitar_notes);
1006         free(hdr->bass_notes);
1007         free(hdr->drum_notes);
1008 }
1009
1010 static void ptb_free_font(struct ptb_font *f)
1011 {
1012         free(f->family);
1013 }
1014
1015 #define FREE_LIST(ls, em, type) \
1016 { \
1017         type tmp; \
1018         type tmp_next; \
1019         for (tmp = ls; tmp; tmp = tmp_next) { \
1020                 em; \
1021                 tmp_next = tmp->next; \
1022                 if (tmp->prev) free(tmp); \
1023         } \
1024 }
1025
1026 static void ptb_free_position(struct ptb_position *pos)
1027 {
1028         FREE_LIST(pos->linedatas, free(tmp->bends), struct ptb_linedata *);
1029 }
1030
1031 static void ptb_free_staff(struct ptb_staff *staff)
1032 {
1033         int i;
1034         for (i = 0; i < 2; i++) {
1035                 FREE_LIST( staff->positions[i], ptb_free_position(tmp), struct ptb_position *);
1036         }
1037 }
1038
1039 static void ptb_free_section(struct ptb_section *section)
1040 {
1041         FREE_LIST(section->staffs, ptb_free_staff(tmp), struct ptb_staff *);
1042         FREE_LIST(section->chordtexts, {} , struct ptb_chordtext *);
1043         FREE_LIST(section->rhythmslashes, {}, struct ptb_rhythmslash *);
1044         FREE_LIST(section->directions, {}, struct ptb_direction *);
1045         FREE_LIST(section->musicbars, free(tmp->description), struct ptb_musicbar *);
1046 }
1047
1048 void ptb_free(struct ptbf *bf)
1049 {
1050         int i;
1051         ptb_free_hdr(&bf->hdr);
1052         ptb_free_font(&bf->default_font);
1053         ptb_free_font(&bf->chord_name_font);
1054         ptb_free_font(&bf->tablature_font);
1055
1056         free(bf->filename);
1057
1058         for (i = 0; i < 2; i++) 
1059         {
1060                 FREE_LIST(
1061                         bf->instrument[i].floatingtexts, 
1062                         free(tmp->text); ptb_free_font(&tmp->font);,
1063                         struct ptb_floatingtext *);
1064                 
1065                 FREE_LIST(
1066                         bf->instrument[i].guitars,
1067                         free(tmp->title); free(tmp->type),
1068                         struct ptb_guitar *);
1069
1070                 FREE_LIST(
1071                         bf->instrument[i].tempomarkers,
1072                         free(tmp->description),
1073                         struct ptb_tempomarker *);
1074
1075                 FREE_LIST(
1076                         bf->instrument[i].chorddiagrams,
1077                         free(tmp->tones),
1078                         struct ptb_chorddiagram *);
1079                         
1080                 FREE_LIST(
1081                         bf->instrument[i].sections,
1082                         free(tmp->description);
1083                         ptb_free_section(tmp),
1084                         struct ptb_section *);
1085
1086                 FREE_LIST(
1087                         bf->instrument[i].sectionsymbols,
1088                 {},
1089                         struct ptb_sectionsymbol *);
1090         }
1091         
1092         free(bf);
1093 }