Fix compatibility with newer versions of lilypond.
[jelmer/ptabtools.git] / ptb2abc.c
1 /*
2         (c) 2005-2006 Jelmer Vernooij <jelmer@samba.org>
3
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 3 of the License, or
7         (at your option) any later version.
8
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.
13
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.
17 */
18
19 #include <stdio.h>
20 #include <errno.h>
21 #include <popt.h>
22 #include <string.h>
23 #include <ctype.h>
24
25 #ifdef HAVE_CONFIG_H
26 #  include "config.h"
27 #endif
28
29 #ifdef HAVE_STDINT_H
30 #  include <stdint.h>
31 #endif
32
33 #include "ptb.h"
34
35 void abc_write_header(FILE *out, struct ptbf *ret) 
36 {
37         if(ret->hdr.classification == CLASSIFICATION_SONG) {
38                 if(ret->hdr.class_info.song.title)      fprintf(out, "T: %s\n", ret->hdr.class_info.song.title);
39                 if(ret->hdr.class_info.song.music_by) fprintf(out, "C: %s\n", ret->hdr.class_info.song.music_by);
40                 if(ret->hdr.class_info.song.words_by) fprintf(out, "%%  Words By: %s\n", ret->hdr.class_info.song.words_by);
41                 if(ret->hdr.class_info.song.copyright) fprintf(out, "%%  Copyright: %s\n", ret->hdr.class_info.song.copyright);
42                 if(ret->hdr.class_info.song.guitar_transcribed_by) fprintf(out, "Z: %s\n", ret->hdr.class_info.song.guitar_transcribed_by);
43                 if(ret->hdr.class_info.song.release_type == RELEASE_TYPE_PR_AUDIO &&
44                    ret->hdr.class_info.song.release_info.pr_audio.album_title) fprintf(out, "%%  Album Title: %s\n", ret->hdr.class_info.song.release_info.pr_audio.album_title);
45         } else if(ret->hdr.classification == CLASSIFICATION_LESSON) {
46                 if(ret->hdr.class_info.lesson.title)    fprintf(out, "T:%s\n", ret->hdr.class_info.lesson.title);
47                 if(ret->hdr.class_info.lesson.artist) fprintf(out, "C: %s\n", ret->hdr.class_info.lesson.artist);
48                 if(ret->hdr.class_info.lesson.author) fprintf(out, "Z: %s\n", ret->hdr.class_info.lesson.author);
49                 if(ret->hdr.class_info.lesson.copyright) fprintf(out, "%%  Copyright: %s\n", ret->hdr.class_info.lesson.copyright);
50         }
51         fprintf(out, "\n");
52 }
53
54 static char *note_names[] = { "c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b" };
55
56 void abc_write_linedata(FILE *out, struct ptb_guitar *gtr, struct ptb_linedata *ld)
57 {
58         uint8_t octave = ptb_get_octave(gtr, ld->detailed.string, ld->detailed.fret);
59         uint8_t step = ptb_get_step(gtr, ld->detailed.string, ld->detailed.fret);
60         int i;
61         char n[3];
62
63         strcpy(n, note_names[step]);
64
65         if (octave < 4) n[0] = toupper(n[0]);
66
67         fprintf(out, "%s", n);
68
69         for (i = octave; i < 4; i++) fprintf(out, ",");
70         for (i = 5; i < octave; i++) fprintf(out, "'");
71 }
72
73 void abc_write_position(FILE *out, struct ptb_guitar *gtr, struct ptb_position *ps)
74 {
75         struct ptb_linedata *ld;
76
77         for (ld = ps->linedatas; ld; ld = ld->next) {
78                 abc_write_linedata(out, gtr, ld);
79         }
80 }
81
82 void abc_write_staff(FILE *out, struct ptb_guitar *gtr, struct ptb_staff *staff)
83 {
84         struct ptb_position *ps;
85         
86         for (ps = staff->positions[0]; ps; ps = ps->next) {
87                 abc_write_position(out, gtr, ps);
88         }
89
90         fprintf(out, "\n");
91 }
92
93 void abc_write_section(FILE *out, struct ptb_guitar *gtr, struct ptb_section *sec)
94 {
95         struct ptb_staff *st;
96         
97         for (st = sec->staffs; st; st = st->next) {
98                 abc_write_staff(out, gtr, st);
99         }
100 }
101
102 void abc_write_chordtext(FILE *out, struct ptb_chordtext *name) {
103         fprintf(out, "\"");
104
105         if(name->properties & CHORDTEXT_PROPERTY_NOCHORD) {
106                 fprintf(out, "N.C.");
107         }
108
109         if(name->properties & CHORDTEXT_PROPERTY_PARENTHESES) {
110                 fprintf(out, "(");
111         }
112
113         if(!(name->properties & CHORDTEXT_PROPERTY_NOCHORD) | 
114            (name->properties & CHORDTEXT_PROPERTY_PARENTHESES)) {
115                 if(name->name[0] == name->name[1]) {
116                         fprintf(out, "%s", ptb_get_tone(name->name[0]));
117                 } else { 
118                         fprintf(out, "%s/%s", ptb_get_tone(name->name[0]),
119                                                 ptb_get_tone(name->name[1]));
120                 }
121         }
122
123         if(name->properties & CHORDTEXT_PROPERTY_PARENTHESES) {
124                 fprintf(out, ")");
125         }
126
127         fprintf(out, "\" ");
128 }
129
130 int abc_write_lyrics(FILE *out, struct ptbf *ret)
131 {
132         if(ret->hdr.classification != CLASSIFICATION_SONG || !ret->hdr.class_info.song.lyrics) return 0;
133         fprintf(out, "W: %s\n\n", ret->hdr.class_info.song.lyrics);
134         return 1;
135 }
136
137 int main(int argc, const char **argv) 
138 {
139         FILE *out;
140         struct ptbf *ret;
141         int debugging = 0;
142         struct ptb_section *section;
143         int instrument = 0;
144         int c;
145         int version = 0;
146         const char *input;
147         char *output = NULL;
148         poptContext pc;
149         struct poptOption options[] = {
150                 POPT_AUTOHELP
151                 {"debug", 'd', POPT_ARG_NONE, &debugging, 0, "Turn on debugging output" },
152                 {"outputfile", 'o', POPT_ARG_STRING, &output, 0, "Write to specified file", "FILE" },
153                 {"regular", 'r', POPT_ARG_NONE, &instrument, 0, "Write tabs for regular guitar" },
154                 {"bass", 'b', POPT_ARG_NONE, &instrument, 1, "Write tabs for bass guitar"},
155                 {"version", 'v', POPT_ARG_NONE, &version, 'v', "Show version information" },
156                 POPT_TABLEEND
157         };
158
159         pc = poptGetContext(argv[0], argc, argv, options, 0);
160         poptSetOtherOptionHelp(pc, "file.ptb");
161         while((c = poptGetNextOpt(pc)) >= 0) {
162                 switch(c) {
163                 case 'v':
164                         printf("ptb2abc Version "PACKAGE_VERSION"\n");
165                         printf("(C) 2005-2006 Jelmer Vernooij <jelmer@samba.org>\n");
166                         exit(0);
167                         break;
168                 }
169         }
170                         
171         ptb_set_debug(debugging);
172         
173         if(!poptPeekArg(pc)) {
174                 poptPrintUsage(pc, stderr, 0);
175                 return -1;
176         }
177         input = poptGetArg(pc);
178         ret = ptb_read_file(input);
179         
180         if(!ret) {
181                 perror("Read error: ");
182                 return -1;
183         } 
184
185         if(!output) {
186                 int baselength = strlen(input);
187                 if (!strcmp(input + strlen(input) - 4, ".ptb")) {
188                         baselength -= 4;
189                 }
190                 output = malloc(baselength + 6);
191                 strncpy(output, input, baselength);
192                 strcpy(output + baselength, ".abc");
193         }
194
195         if(!strcmp(output, "-")) {
196                 out = stdout;
197         } else {
198                 out = fopen(output, "w+");
199                 if(!out) {
200                         perror("open");
201                         return -1;
202                 }
203         } 
204         
205         fprintf(out, "%% Generated by ptb2abc (C) 2005-2006 Jelmer Vernooij <jelmer@samba.org>\n");
206         fprintf(out, "%% See http://jelmer.vernstok.nl/oss/ptabtools/ for more info\n\n");
207         fprintf(out, "X:1\n");
208                 
209         abc_write_header(out, ret);
210         abc_write_lyrics(out, ret);
211
212         fprintf(out, "M: C\n");
213         fprintf(out, "K: Cm\n");
214         fprintf(out, "L: 1/4\n");
215
216         section = ret->instrument[instrument].sections;
217         while(section) {
218                 abc_write_section(out, ret->instrument[instrument].guitars, section);
219                 fprintf(out, "\n\n");
220                 section = section->next;
221         }
222
223         if(output)fclose(out);
224         
225         return (ret?0:1);
226 }