2 Parser library for the PowerTab (PTB) file format
3 (c) 2004-2005: Jelmer Vernooij <jelmer@samba.org>
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.
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 the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "dlinklist.h"
27 #ifndef __PRETTY_FUNCTION__
28 #define __PRETTY_FUNCTION__ ""
49 int assert_is_fatal = 0;
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(); \
57 #define malloc_p(t,n) (t *) calloc(sizeof(t), n)
59 #define GET_ITEM(bf, dest, type) ((bf)->mode == O_WRONLY?(type *)(*(dest)):malloc_p(type, 1))
61 #define ptb_assert_0(ptb, expr) \
62 if(expr) ptb_debug("%s == 0x%x!", #expr, expr); \
63 /* ptb_assert(ptb, (expr) == 0); */
66 struct ptb_list *prev, *next;
69 struct ptb_section_handler {
71 int (*handler) (struct ptbf *, const char *section, struct ptb_list **ret);
74 extern struct ptb_section_handler ptb_section_handlers[];
76 void ptb_debug(const char *fmt, ...);
80 static ssize_t ptb_read(struct ptbf *f, void *data, ssize_t length)
82 ssize_t ret = read(f->fd, data, length);
83 #define read DONT_USE_READ
88 } else if (ret != length) {
89 ptb_debug("Expected read of %d bytes, got %d\n", length, ret);
97 static ssize_t ptb_write(struct ptbf *f, void *data, size_t length)
99 ssize_t ret = write(f->fd, data, length);
100 #define write DONT_USE_WRITE
112 static ssize_t ptb_data(struct ptbf *f, void *data, size_t length)
115 case O_RDONLY: return ptb_read(f, data, length);
116 case O_WRONLY: return ptb_write(f, data, length);
122 static ssize_t ptb_data_constant(struct ptbf *f, unsigned char expected)
127 if (f->mode == O_WRONLY) {
128 ret = ptb_data(f, &expected, 1);
130 ret = ptb_data(f, &real, 1);
132 if(real != expected) {
133 ptb_debug("%04x: Expected %02x, got %02x", f->curpos-1, expected, real);
141 static ssize_t ptb_data_constant_string(struct ptbf *f, const char *expected, int length)
144 for (i = 0; i < length; i++) {
145 ret = ptb_data_constant(f, expected[i]);
151 static ssize_t ptb_data_unknown(struct ptbf *f, size_t length) {
154 off_t oldpos = f->curpos;
157 memset(unknown, 0, length);
158 ret = ptb_data(f, unknown, length);
160 for(i = 0; i < length; i++)
161 ptb_debug("Unknown[%04lx]: %02x", oldpos + i, unknown[i]);
166 static ssize_t ptb_read_string(struct ptbf *f, char **dest)
171 ptb_data(f, &shortlength, 1);
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;
177 length = shortlength;
181 data = malloc_p(char, length+1);
182 if(ptb_data(f, data, length) < length) return -1;
183 ptb_debug("Read string: %s", data);
186 ptb_debug("Empty string");
193 static ssize_t ptb_write_string(struct ptbf *f, char **dest)
200 } else if (strlen(*dest) >= 0xff) {
202 length = strlen(*dest);
204 shortlength = strlen(*dest);
207 ptb_data(f, &shortlength, 1);
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;
213 length = shortlength;
216 if(ptb_data(f, *dest, length) < length) return -1;
221 static ssize_t ptb_data_string(struct ptbf *bf, char **dest) {
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);
230 static ssize_t ptb_data_font(struct ptbf *f, struct ptb_font *dest) {
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);
243 static ssize_t ptb_data_header(struct ptbf *f, struct ptb_hdr *hdr)
245 ptb_data_constant_string(f, "ptab", 4);
247 ptb_data(f, &hdr->version, 2);
248 ptb_data(f, &hdr->classification, 1);
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);
256 ptb_data(f, &hdr->class_info.song.release_type, 1);
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);
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);
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);
275 case RELEASE_TYPE_UNRELEASED:
279 fprintf(stderr, "Unknown release type: %d\n", hdr->class_info.song.release_type);
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);
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);
305 fprintf(stderr, "Unknown classification: %d\n", hdr->classification);
315 void ptb_debug(const char *fmt, ...)
319 if(debugging == 0) return;
322 for(i = 0; i < debug_level; i++) fprintf(stderr, " ");
325 vfprintf(stderr, fmt, ap);
330 static int ptb_read_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result) {
341 ret+=ptb_data(bf, &nr_items, 2);
342 if(ret == 0 || nr_items == 0x0) return 1;
343 ret+=ptb_data(bf, &header, 2);
345 ptb_debug("Going to read %d items", nr_items);
347 if(header == 0xffff) { /* New section */
348 char *my_section_name;
350 ret+=ptb_data(bf, &unknownval, 2);
352 if(unknownval != 0x0001) {
353 fprintf(stderr, "Unknownval: %04x\n", unknownval);
357 ret+=ptb_data(bf, &length, 2);
359 my_section_name = malloc_p(char, length + 1);
360 ret+=ptb_data(bf, my_section_name, length);
362 } else if(header & 0x8000) {
364 ptb_debug("Expected new item type (%s), got %04x %02x\n", assumed_type, nr_items, header);
369 for(i = 0; ptb_section_handlers[i].name; i++) {
370 if(!strcmp(ptb_section_handlers[i].name, assumed_type)) {
375 if(!ptb_section_handlers[i].handler) {
376 fprintf(stderr, "Unable to find handler for section %s\n", assumed_type);
380 for(l = 0; l < nr_items; l++) {
381 struct ptb_list *item;
385 ptb_debug("%04x ============= Handling %s (%d of %d) =============", bf->curpos, assumed_type, l+1, nr_items);
388 ret = ptb_section_handlers[i].handler(bf, ptb_section_handlers[i].name, (struct ptb_list **)&item);
389 if (!ret) item = NULL;
392 ptb_debug("%04x ============= END Handling %s (%d of %d) =============", bf->curpos, ptb_section_handlers[i].name, l+1, nr_items);
395 fprintf(stderr, "Error parsing section '%s'\n", ptb_section_handlers[i].name);
397 DLIST_ADD_END((*result), item, struct ptb_list *);
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);
412 static int generate_header_id(struct ptbf *bf, const char *assumed_type)
419 static int ptb_write_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result)
429 DLIST_LEN(*result, nr_items, struct ptb_list *);
431 ret+=ptb_data(bf, &nr_items, 2);
432 if(nr_items == 0x0) return 1;
434 header = generate_header_id(bf, assumed_type);
435 if (header == 0) header = 0xffff;
437 ret+=ptb_data(bf, &header, 2);
439 ptb_debug("Going to write %d items", nr_items);
441 if (header == 0xffff) {
442 uint16_t unknownval = 0x0001; /* FIXME */
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);
451 for(i = 0; ptb_section_handlers[i].name; i++) {
452 if(!strcmp(ptb_section_handlers[i].name, assumed_type)) {
457 if(!ptb_section_handlers[i].handler) {
458 fprintf(stderr, "Unable to find handler for section %s\n", assumed_type);
466 ptb_section_handlers[i].handler(bf, ptb_section_handlers[i].name, (struct ptb_list **)&gl);
470 ret+=ptb_data(bf, &id, 2);
479 static int ptb_data_items(struct ptbf *bf, const char *assumed_type, struct ptb_list **result)
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);
491 void ptb_set_debug(int level) { debugging = level; }
493 void ptb_set_asserts_fatal(int y) { assert_is_fatal = y; }
495 static void ptb_data_instrument(struct ptbf *bf, int i)
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);
507 static ssize_t ptb_data_file(struct ptbf *bf)
510 if(ptb_data_header(bf, &bf->hdr) < 0) {
511 fprintf(stderr, "Error parsing header\n");
513 } else if(debugging) {
514 fprintf(stderr, "Header parsed correctly\n");
517 for(i = 0; i < 2; i++) {
518 ptb_data_instrument(bf, i);
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);
525 ptb_data_unknown(bf, 12);
529 struct ptbf *ptb_read_file(const char *file)
531 struct ptbf *bf = malloc_p(struct ptbf, 1);
534 bf->fd = open(file, bf->mode
540 strncpy(bf->data, "abc", 3);
542 bf->filename = strdup(file);
544 if(bf->fd < 0) return NULL;
548 if (ptb_data_file(bf) == -1)
555 int ptb_write_file(const char *file, struct ptbf *bf)
558 bf->fd = creat(file, 0644);
560 strncpy(bf->data, "abc", 3);
562 bf->filename = strdup(file);
564 if(bf->fd < 0) return -1;
568 if (ptb_data_file(bf) == -1)
575 static int handle_unknown (struct ptbf *bf, const char *section, struct ptb_list **dest) {
576 fprintf(stderr, "Unknown section '%s'\n", section);
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);
583 ptb_data(bf, &guitar->index, 1);
584 ptb_data_string(bf, &guitar->title);
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);
593 ptb_data(bf, &guitar->simulate, 1);
594 ptb_data(bf, &guitar->capo, 1);
596 ptb_data_string(bf, &guitar->type);
598 ptb_data(bf, &guitar->half_up, 1);
599 ptb_data(bf, &guitar->nr_strings, 1);
601 if (bf->mode == O_RDONLY) {
602 guitar->strings = malloc_p(uint8_t, guitar->nr_strings);
605 ptb_data(bf, guitar->strings, guitar->nr_strings);
607 *dest = (struct ptb_list *)guitar;
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);
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);
626 *dest = (struct ptb_list *)text;
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);
634 ptb_data_constant(bf, 0x32);
635 ptb_data_unknown(bf, 11);
636 ptb_data(bf, §ion->properties, 2);
637 ptb_data_unknown(bf, 2);
638 ptb_data(bf, §ion->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, §ion->position_width, 1);
643 ptb_data_unknown(bf, 5);
644 ptb_data(bf, §ion->key_extra, 1);
645 ptb_data_unknown(bf, 1);
646 ptb_data(bf, §ion->meter_type, 2);
647 ptb_data(bf, §ion->beat_info, 1);
648 ptb_data(bf, §ion->metronome_pulses_per_measure, 1);
649 ptb_data(bf, §ion->letter, 1);
650 ptb_data_string(bf, §ion->description);
652 ptb_data_items(bf, "CDirection", (struct ptb_list **)§ion->directions);
653 ptb_data_items(bf, "CChordText", (struct ptb_list **)§ion->chordtexts);
654 ptb_data_items(bf, "CRhythmSlash", (struct ptb_list **)§ion->rhythmslashes);
655 ptb_data_items(bf, "CStaff", (struct ptb_list **)§ion->staffs);
656 ptb_data_items(bf, "CMusicBar", (struct ptb_list **)§ion->musicbars);
658 *dest = (struct ptb_list *)section;
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);
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);
673 *dest = (struct ptb_list *)tempomarker;
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);
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);
689 *dest = (struct ptb_list *)chorddiagram;
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);
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);
712 ptb_data(bf, &linedata->conn_to_next, 1);
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);
718 linedata->bends = NULL;
721 *dest = (struct ptb_list *)linedata;
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);
729 ptb_data(bf, &chordtext->offset, 1);
730 ptb_data(bf, chordtext->name, 2);
732 ptb_data(bf, &chordtext->properties, 1);
733 ptb_assert_0(bf, chordtext->properties
734 & ~CHORDTEXT_PROPERTY_NOCHORD
735 & ~CHORDTEXT_PROPERTY_PARENTHESES
737 & ~CHORDTEXT_PROPERTY_FORMULA_M
738 & ~CHORDTEXT_PROPERTY_FORMULA_MAJ7);
739 ptb_data(bf, &chordtext->additions, 1);
740 ptb_assert_0(bf, chordtext->additions
742 ptb_data(bf, &chordtext->alterations, 1);
743 ptb_data(bf, &chordtext->VII, 1);
744 ptb_assert_0(bf, chordtext->VII & ~CHORDTEXT_VII);
746 *dest = (struct ptb_list *)chordtext;
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);
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);
760 *dest = (struct ptb_list *)guitarin;
765 static int handle_CStaff (struct ptbf *bf, const char *section, struct ptb_list **dest) {
767 struct ptb_staff *staff = GET_ITEM(bf, dest, struct ptb_staff);
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);
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;
782 *dest = (struct ptb_list *)staff;
783 staff->positions[1] = NULL;
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;
794 *dest = (struct ptb_list *)staff;
799 *dest = (struct ptb_list *)staff;
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);
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);
829 ptb_data(bf, &position->nr_additional_data, 1);
831 position->additional = malloc_p(struct ptb_position_additional, position->nr_additional_data);
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);
840 ptb_data_items(bf, "CLineData", (struct ptb_list **)&position->linedatas);
842 *dest = (struct ptb_list *)position;
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);
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);
854 *dest = (struct ptb_list *)dynamic;
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);
861 ptb_data_unknown(bf, 5); /* FIXME */
862 ptb_data(bf, §ionsymbol->repeat_ending, 2);
864 *dest = (struct ptb_list *)sectionsymbol;
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);
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);
877 *dest = (struct ptb_list *)musicbar;
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);
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);
892 *dest = (struct ptb_list *)rhythmslash;
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);
899 ptb_data_unknown(bf, 4); /* FIXME */
901 *dest = (struct ptb_list *)direction;
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 },
924 const char *ptb_get_tone(ptb_tone id)
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_";
931 const char *ptb_get_tone_full(ptb_tone id)
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];
938 static struct ptb_position *get_position(struct ptb_staff *staff, int offset)
941 for(i = 0; i < 2; i++) {
942 struct ptb_position *p = staff->positions[i];
944 if(p->offset == offset) return p;
951 void ptb_get_position_difference(struct ptb_section *section, int start, int end, int *bars, int *length)
954 struct ptb_staff *staff = section->staffs;
955 struct ptb_position *gl = NULL;
958 gl = get_position(staff, start);
964 if(gl->offset >= end) break;
965 l += 0x100 / gl->length;
972 if(l % 0x100) *length = 0x100 / (l % 0x100) ;
975 static void ptb_free_hdr(struct ptb_hdr *hdr)
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);
982 case RELEASE_TYPE_PR_VIDEO:
983 free(hdr->class_info.song.release_info.pr_video.video_title);
985 case RELEASE_TYPE_BOOTLEG:
986 free(hdr->class_info.song.release_info.bootleg.title);
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);
1005 free(hdr->guitar_notes);
1006 free(hdr->bass_notes);
1007 free(hdr->drum_notes);
1010 static void ptb_free_font(struct ptb_font *f)
1015 #define FREE_LIST(ls, em, type) \
1019 for (tmp = ls; tmp; tmp = tmp_next) { \
1021 tmp_next = tmp->next; \
1022 if (tmp->prev) free(tmp); \
1026 static void ptb_free_position(struct ptb_position *pos)
1028 FREE_LIST(pos->linedatas, free(tmp->bends), struct ptb_linedata *);
1031 static void ptb_free_staff(struct ptb_staff *staff)
1034 for (i = 0; i < 2; i++) {
1035 FREE_LIST( staff->positions[i], ptb_free_position(tmp), struct ptb_position *);
1039 static void ptb_free_section(struct ptb_section *section)
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 *);
1048 void ptb_free(struct ptbf *bf)
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);
1058 for (i = 0; i < 2; i++)
1061 bf->instrument[i].floatingtexts,
1062 free(tmp->text); ptb_free_font(&tmp->font);,
1063 struct ptb_floatingtext *);
1066 bf->instrument[i].guitars,
1067 free(tmp->title); free(tmp->type),
1068 struct ptb_guitar *);
1071 bf->instrument[i].tempomarkers,
1072 free(tmp->description),
1073 struct ptb_tempomarker *);
1076 bf->instrument[i].chorddiagrams,
1078 struct ptb_chorddiagram *);
1081 bf->instrument[i].sections,
1082 free(tmp->description);
1083 ptb_free_section(tmp),
1084 struct ptb_section *);
1087 bf->instrument[i].sectionsymbols,
1089 struct ptb_sectionsymbol *);