2 (c) 2004: Jelmer Vernooij <jelmer@samba.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <libxml/xmlmemory.h>
25 #include <libxml/parser.h>
28 #define SMART_ADD_CHILD_STRING(parent, name, contents) if(contents) { xmlNodePtr tmp = xmlNewNode(NULL, name); xmlNodeSetContent(tmp, contents); xmlAddChild(parent, tmp); }
29 #define SMART_ADD_CHILD_INT(parent, name, contents) { char tmpc[100]; xmlNodePtr tmp = xmlNewNode(NULL, name); g_snprintf(tmpc, 100, "%d", contents); xmlNodeSetContent(tmp, tmpc); xmlAddChild(parent, tmp); }
31 xmlNodePtr xml_write_font(struct ptb_font *font)
33 xmlNodePtr xfont = xmlNewNode(NULL, "font");
35 g_snprintf(tmp, 100, "%d", font->size); xmlSetProp(xfont, "size", tmp);
36 g_snprintf(tmp, 100, "%d", font->thickness); xmlSetProp(xfont, "thickness", tmp);
37 g_snprintf(tmp, 100, "%d", font->underlined); xmlSetProp(xfont, "underlined", tmp);
38 g_snprintf(tmp, 100, "%d", font->italic); xmlSetProp(xfont, "italic", tmp);
39 xmlSetProp(xfont, "family", font->family);
43 xmlNodePtr xml_write_directions(GList *directions)
45 xmlNodePtr xdirections = xmlNewNode(NULL, "directions");
46 GList *gl = directions;
49 struct ptb_direction *direction = gl->data;
50 xmlNodePtr xdirection = xmlNewNode(NULL, "direction");
51 xmlAddChild(xdirections, xdirection);
58 xmlNodePtr xml_write_rhythmslashes(GList *rhythmslashs)
60 xmlNodePtr xrhythmslashs = xmlNewNode(NULL, "rhythmslashs");
61 GList *gl = rhythmslashs;
64 struct ptb_rhythmslash *rhythmslash = gl->data;
65 xmlNodePtr xrhythmslash = xmlNewNode(NULL, "rhythmslash");
66 xmlAddChild(xrhythmslashs, xrhythmslash);
74 xmlNodePtr xml_write_chordtexts(GList *chordtexts)
76 xmlNodePtr xchordtexts = xmlNewNode(NULL, "chordtexts");
77 GList *gl = chordtexts;
80 struct ptb_chordtext *chordtext = gl->data;
81 xmlNodePtr xchordtext = xmlNewNode(NULL, "chordtext");
82 xmlAddChild(xchordtexts, xchordtext);
84 SMART_ADD_CHILD_INT(xchordtext, "note1", chordtext->name[0]);
85 SMART_ADD_CHILD_INT(xchordtext, "note2", chordtext->name[1]);
86 SMART_ADD_CHILD_INT(xchordtext, "offset", chordtext->offset);
87 SMART_ADD_CHILD_INT(xchordtext, "additions", chordtext->additions);
88 SMART_ADD_CHILD_INT(xchordtext, "alterations", chordtext->alterations);
89 SMART_ADD_CHILD_INT(xchordtext, "properties", chordtext->properties);
96 xmlNodePtr xml_write_musicbars(GList *musicbars)
98 xmlNodePtr xmusicbars = xmlNewNode(NULL, "musicbars");
99 GList *gl = musicbars;
102 struct ptb_musicbar *musicbar = gl->data;
103 xmlNodePtr xmusicbar = xmlNewNode(NULL, "musicbar");
104 xmlAddChild(xmusicbars, xmusicbar);
108 g_snprintf(tmp, 100, "%c", musicbar->letter);
109 xmlSetProp(xmusicbar, "letter", tmp);
112 xmlNodeSetContent(xmusicbar, musicbar->description);
119 xmlNodePtr xml_write_linedatas(GList *linedatas)
121 xmlNodePtr xlinedatas = xmlNewNode(NULL, "linedatas");
122 GList *gl = linedatas;
125 struct ptb_linedata *linedata = gl->data;
126 xmlNodePtr xlinedata = xmlNewNode(NULL, "linedata");
127 xmlAddChild(xlinedatas, xlinedata);
129 SMART_ADD_CHILD_INT(xlinedata, "tone", linedata->tone);
130 SMART_ADD_CHILD_INT(xlinedata, "properties", linedata->properties);
131 SMART_ADD_CHILD_INT(xlinedata, "transcribe", linedata->transcribe);
132 SMART_ADD_CHILD_INT(xlinedata, "conn_to_next", linedata->conn_to_next);
139 xmlNodePtr xml_write_positions(GList *positions)
141 xmlNodePtr xpositions = xmlNewNode(NULL, "positions");
142 GList *gl = positions;
145 struct ptb_position *position = gl->data;
146 xmlNodePtr xposition = xmlNewNode(NULL, "position");
147 xmlAddChild(xpositions, xposition);
149 SMART_ADD_CHILD_INT(xposition, "offset", position->offset);
150 SMART_ADD_CHILD_INT(xposition, "length", position->length);
151 SMART_ADD_CHILD_INT(xposition, "properties", position->properties);
152 SMART_ADD_CHILD_INT(xposition, "let_ring", position->let_ring);
153 SMART_ADD_CHILD_INT(xposition, "fermenta", position->fermenta);
155 xmlAddChild(xposition, xml_write_linedatas(position->linedatas));
162 xmlNodePtr xml_write_staffs(GList *staffs)
164 xmlNodePtr xstaffs = xmlNewNode(NULL, "staffs");
168 struct ptb_staff *staff = gl->data;
169 xmlNodePtr xstaff = xmlNewNode(NULL, "staff");
170 xmlAddChild(xstaffs, xstaff);
172 SMART_ADD_CHILD_INT(xstaff, "highest_note", staff->highest_note);
173 SMART_ADD_CHILD_INT(xstaff, "lowest_note", staff->lowest_note);
174 SMART_ADD_CHILD_INT(xstaff, "properties", staff->properties);
176 xmlAddChild(xstaff, xml_write_positions(staff->positions1));
177 xmlAddChild(xstaff, xml_write_musicbars(staff->musicbars));
184 xmlNodePtr xml_write_sections(GList *sections)
186 xmlNodePtr sctns = xmlNewNode(NULL, "sections");
187 GList *gl = sections;
190 struct ptb_section *section = gl->data;
191 xmlNodePtr meter_type;
192 xmlNodePtr xsection = xmlNewNode(NULL, "section");
194 xmlAddChild(sctns, xsection);
198 g_snprintf(tmp, 100, "%c", section->letter);
199 xmlSetProp(xsection, "letter", tmp);
202 switch(section->end_mark) {
203 case END_MARK_TYPE_NORMAL:
204 SMART_ADD_CHILD_STRING(xsection, "end-mark", "normal");
206 case END_MARK_TYPE_REPEAT:
207 SMART_ADD_CHILD_STRING(xsection, "end-mark", "repeat");
211 meter_type = xmlNewNode(NULL, "meter-type");
212 xmlAddChild(xsection, meter_type);
214 if(section->meter_type & METER_TYPE_BEAM_2) SMART_ADD_CHILD_STRING(meter_type, "beam_2", "");
215 if(section->meter_type & METER_TYPE_BEAM_3) SMART_ADD_CHILD_STRING(meter_type, "beam_3", "");
216 if(section->meter_type & METER_TYPE_BEAM_4) SMART_ADD_CHILD_STRING(meter_type, "beam_4", "");
217 if(section->meter_type & METER_TYPE_BEAM_5) SMART_ADD_CHILD_STRING(meter_type, "beam_5", "");
218 if(section->meter_type & METER_TYPE_BEAM_6) SMART_ADD_CHILD_STRING(meter_type, "beam_6", "");
219 if(section->meter_type & METER_TYPE_COMMON) SMART_ADD_CHILD_STRING(meter_type, "common", "");
220 if(section->meter_type & METER_TYPE_CUT) SMART_ADD_CHILD_STRING(meter_type, "cut", "");
221 if(section->meter_type & METER_TYPE_SHOW) SMART_ADD_CHILD_STRING(meter_type, "show", "");
223 SMART_ADD_CHILD_INT(xsection, "beat", section->beat_value);
224 SMART_ADD_CHILD_INT(xsection, "metronome-pulses-per-measure", section->metronome_pulses_per_measure);
225 SMART_ADD_CHILD_INT(xsection, "properties", section->properties);
226 SMART_ADD_CHILD_INT(xsection, "key-extra", section->key_extra);
227 SMART_ADD_CHILD_INT(xsection, "position-width", section->position_width);
228 SMART_ADD_CHILD_STRING(xsection, "description", section->description);
230 xmlAddChild(xsection, xml_write_chordtexts(section->chordtexts));
231 xmlAddChild(xsection, xml_write_rhythmslashes(section->rhythmslashes));
232 xmlAddChild(xsection, xml_write_directions(section->directions));
233 xmlAddChild(xsection, xml_write_staffs(section->staffs));
241 xmlNodePtr xml_write_guitars(GList *guitars)
243 xmlNodePtr gtrs = xmlNewNode(NULL, "guitars");
249 struct ptb_guitar *gtr = gl->data;
250 xmlNodePtr xgtr = xmlNewNode(NULL, "guitar");
252 xmlAddChild(gtrs, xgtr);
254 g_snprintf(tmp, 100, "%d", gtr->index);
255 xmlSetProp(xgtr, "id", tmp);
257 strings = xmlNewNode(NULL, "strings");
258 xmlAddChild(xgtr, strings);
260 for(i = 0; i < gtr->nr_strings; i++) {
261 SMART_ADD_CHILD_INT(strings, "string", gtr->strings[i]);
264 SMART_ADD_CHILD_INT(xgtr, "reverb", gtr->reverb);
265 SMART_ADD_CHILD_INT(xgtr, "chorus", gtr->chorus);
266 SMART_ADD_CHILD_INT(xgtr, "tremolo", gtr->tremolo);
267 SMART_ADD_CHILD_INT(xgtr, "pan", gtr->pan);
268 SMART_ADD_CHILD_INT(xgtr, "capo", gtr->capo);
269 SMART_ADD_CHILD_INT(xgtr, "initial_volume", gtr->initial_volume);
270 SMART_ADD_CHILD_INT(xgtr, "midi_instrument", gtr->midi_instrument);
271 SMART_ADD_CHILD_INT(xgtr, "half_up", gtr->half_up);
272 SMART_ADD_CHILD_INT(xgtr, "simulate", gtr->simulate);
280 xmlNodePtr xml_write_guitarins(GList *guitarins)
282 GList *gl = guitarins;
283 xmlNodePtr xguitarins = xmlNewNode(NULL, "guitarins");
286 struct ptb_guitarin *guitarin = gl->data;
287 xmlNodePtr xguitarin = xmlNewNode(NULL, "guitarin");
288 xmlAddChild(xguitarins, xguitarin);
290 SMART_ADD_CHILD_INT(xguitarin, "offset", guitarin->offset);
291 SMART_ADD_CHILD_INT(xguitarin, "section", guitarin->section);
292 SMART_ADD_CHILD_INT(xguitarin, "staff", guitarin->staff);
293 SMART_ADD_CHILD_INT(xguitarin, "rhythm_slash", guitarin->rhythm_slash);
294 SMART_ADD_CHILD_INT(xguitarin, "staff_in", guitarin->staff_in);
302 xmlNodePtr xml_write_tempomarkers(GList *tempomarkers)
304 GList *gl = tempomarkers;
305 xmlNodePtr xtempomarkers = xmlNewNode(NULL, "tempomarkers");
308 struct ptb_tempomarker *tempomarker = gl->data;
309 xmlNodePtr xtempomarker = xmlNewNode(NULL, "tempomarker");
310 xmlAddChild(xtempomarkers, xtempomarker);
312 SMART_ADD_CHILD_INT(xtempomarker, "type", tempomarker->type);
313 SMART_ADD_CHILD_INT(xtempomarker, "bpm", tempomarker->bpm);
314 xmlNodeSetContent(xtempomarker, tempomarker->description);
319 return xtempomarkers;
322 xmlNodePtr xml_write_dynamics(GList *dynamics)
324 GList *gl = dynamics;
325 xmlNodePtr xdynamics = xmlNewNode(NULL, "dynamics");
328 struct ptb_dynamic *dynamic = gl->data;
329 xmlNodePtr xdynamic = xmlNewNode(NULL, "dynamic");
330 xmlAddChild(xdynamics, xdynamic);
332 SMART_ADD_CHILD_INT(xdynamic, "offset", dynamic->offset);
340 xmlNodePtr xml_write_chorddiagrams(GList *chorddiagrams)
342 GList *gl = chorddiagrams;
343 xmlNodePtr xchorddiagrams = xmlNewNode(NULL, "chorddiagrams");
346 struct ptb_chorddiagram *chorddiagram = gl->data;
348 xmlNodePtr xchorddiagram = xmlNewNode(NULL, "chorddiagram");
349 xmlNodePtr strings = xmlNewNode(NULL, "strings");
350 xmlAddChild(xchorddiagrams, xchorddiagram);
351 xmlAddChild(xchorddiagram, strings);
353 SMART_ADD_CHILD_INT(xchorddiagram, "note1", chorddiagram->name[0]);
354 SMART_ADD_CHILD_INT(xchorddiagram, "note2", chorddiagram->name[1]);
355 SMART_ADD_CHILD_INT(xchorddiagram, "frets", chorddiagram->frets);
356 SMART_ADD_CHILD_INT(xchorddiagram, "type", chorddiagram->type);
358 for(i = 0; i < chorddiagram->nr_strings; i++) {
359 SMART_ADD_CHILD_INT(strings, "string", chorddiagram->tones[i]);
365 return xchorddiagrams;
368 xmlNodePtr xml_write_sectionsymbols(GList *sectionsymbols)
370 GList *gl = sectionsymbols;
371 xmlNodePtr xsectionsymbols = xmlNewNode(NULL, "sectionsymbols");
374 struct ptb_sectionsymbol *sectionsymbol = gl->data;
375 xmlNodePtr xsectionsymbol = xmlNewNode(NULL, "sectionsymbol");
376 xmlAddChild(xsectionsymbols, xsectionsymbol);
378 SMART_ADD_CHILD_INT(xsectionsymbol, "repeat-ending", sectionsymbol->repeat_ending);
383 return xsectionsymbols;
386 xmlNodePtr xml_write_floatingtexts(GList *floatingtexts)
388 GList *gl = floatingtexts;
389 xmlNodePtr xfloatingtexts = xmlNewNode(NULL, "floatingtexts");
392 struct ptb_floatingtext *floatingtext = gl->data;
393 xmlNodePtr xfloatingtext = xmlNewNode(NULL, "floatingtext");
394 xmlAddChild(xfloatingtexts, xfloatingtext);
396 SMART_ADD_CHILD_INT(xfloatingtext, "beginpos", floatingtext->beginpos);
398 switch(floatingtext->alignment) {
400 SMART_ADD_CHILD_STRING(xfloatingtext, "alignment", "left");
403 SMART_ADD_CHILD_STRING(xfloatingtext, "alignment", "right");
406 SMART_ADD_CHILD_STRING(xfloatingtext, "alignment", "center");
409 xmlNodeSetContent(xfloatingtext, floatingtext->text);
411 xmlAddChild(xfloatingtext, xml_write_font(&floatingtext->font));
416 return xfloatingtexts;
419 xmlNodePtr xml_write_instrument(struct ptbf *bf, int i)
422 xmlNodePtr instrument = xmlNewNode(NULL, "instrument");
423 g_snprintf(tmp, 100, "%d", i);
424 xmlSetProp(instrument, "id", tmp);
426 xmlAddChild(instrument, xml_write_guitars(bf->instrument[i].guitars));
427 xmlAddChild(instrument, xml_write_sections(bf->instrument[i].sections));
428 xmlAddChild(instrument, xml_write_guitarins(bf->instrument[i].guitarins));
429 xmlAddChild(instrument, xml_write_chorddiagrams(bf->instrument[i].chorddiagrams));
430 xmlAddChild(instrument, xml_write_tempomarkers(bf->instrument[i].tempomarkers));
431 xmlAddChild(instrument, xml_write_dynamics(bf->instrument[i].dynamics));
432 xmlAddChild(instrument, xml_write_floatingtexts(bf->instrument[i].floatingtexts));
433 xmlAddChild(instrument, xml_write_sectionsymbols(bf->instrument[i].sectionsymbols));
437 xmlNodePtr xml_write_song_header(struct ptb_hdr *hdr)
439 xmlNodePtr song = xmlNewNode(NULL, "song");
441 SMART_ADD_CHILD_STRING(song, "title", hdr->class_info.song.title);
442 SMART_ADD_CHILD_STRING(song, "artist", hdr->class_info.song.artist);
443 SMART_ADD_CHILD_STRING(song, "words-by", hdr->class_info.song.words_by);
444 SMART_ADD_CHILD_STRING(song, "music-by", hdr->class_info.song.music_by);
445 SMART_ADD_CHILD_STRING(song, "arranged-by", hdr->class_info.song.arranged_by);
446 SMART_ADD_CHILD_STRING(song, "guitar-transcribed-by", hdr->class_info.song.guitar_transcribed_by);
447 SMART_ADD_CHILD_STRING(song, "bass-transcribed-by", hdr->class_info.song.bass_transcribed_by);
448 SMART_ADD_CHILD_STRING(song, "lyrics", hdr->class_info.song.lyrics);
449 SMART_ADD_CHILD_STRING(song, "copyright", hdr->class_info.song.copyright);
451 /* FIXME: Sub stuff */
456 xmlNodePtr xml_write_lesson_header(struct ptb_hdr *hdr)
458 xmlNodePtr lesson = xmlNewNode(NULL, "lesson");
460 SMART_ADD_CHILD_STRING(lesson, "title", hdr->class_info.lesson.title);
461 SMART_ADD_CHILD_STRING(lesson, "artist", hdr->class_info.lesson.artist);
462 SMART_ADD_CHILD_STRING(lesson, "author", hdr->class_info.lesson.author);
463 SMART_ADD_CHILD_STRING(lesson, "copyright", hdr->class_info.lesson.copyright);
465 switch(hdr->class_info.lesson.level) {
466 case LEVEL_BEGINNER: xmlSetProp(lesson, "level", "beginner"); break;
467 case LEVEL_INTERMEDIATE: xmlSetProp(lesson, "level", "intermediate"); break;
468 case LEVEL_ADVANCED: xmlSetProp(lesson, "level", "advanced"); break;
476 xmlNodePtr xml_write_header(struct ptb_hdr *hdr)
478 xmlNodePtr header = xmlNewNode(NULL, "header");
479 switch(hdr->classification) {
480 case CLASSIFICATION_SONG:
481 xmlSetProp(header, "classification", "song");
482 xmlAddChild(header, xml_write_song_header(hdr));
484 case CLASSIFICATION_LESSON:
485 xmlSetProp(header, "classification", "lesson");
486 xmlAddChild(header, xml_write_lesson_header(hdr));
492 int main(int argc, const char **argv)
496 xmlNodePtr root_node;
503 struct poptOption options[] = {
505 {"debug", 'd', POPT_ARG_NONE, &debugging, 0, "Turn on debugging output" },
506 {"outputfile", 'o', POPT_ARG_STRING, &output, 0, "Write to specified file", "FILE" },
507 {"version", 'v', POPT_ARG_NONE, &version, 'v', "Show version information" },
511 pc = poptGetContext(argv[0], argc, argv, options, 0);
512 poptSetOtherOptionHelp(pc, "file.ptb");
513 while((c = poptGetNextOpt(pc)) >= 0) {
516 printf("ptb2ascii Version "PTB_VERSION"\n");
517 printf("(C) 2004 Jelmer Vernooij <jelmer@samba.org>\n");
523 ptb_set_debug(debugging);
525 if(!poptPeekArg(pc)) {
526 poptPrintUsage(pc, stderr, 0);
529 ret = ptb_read_file(poptGetArg(pc));
532 perror("Read error: ");
536 doc = xmlNewDoc(BAD_CAST "1.0");
537 root_node = xmlNewNode(NULL, BAD_CAST "powertab");
538 xmlDocSetRootElement(doc, root_node);
540 comment = xmlNewComment("\nGenerated by ptb2xml, part of ptabtools. \n"
541 "(C) 2004 by Jelmer Vernooij <jelmer@samba.org>\n"
542 "See http://jelmer.vernstok.nl/oss/ptabtools/ for details\n");
543 xmlAddChild(root_node, comment);
545 xmlAddChild(root_node, xml_write_header(&ret->hdr));
547 for(i = 0; i < 2; i++) {
548 xmlAddChild(root_node, xml_write_instrument(ret, i));
551 xmlSaveFormatFileEnc(output?output:"-", doc, "UTF-8", 1);