1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 
6 #include "general.h"
7 #include "fileoutput.h"
8 
9 /*
10 
11 Ringtone Tools - Copyright 2001-2005 Michael Kohn (mike@mikekohn.net)
12 This falls under the Kohnian license.  Please read
13 it at http://ringtonetools.mikekohn.net/
14 
15 This program is NOT opensourced.  You may not use any part
16 of this program for your own software.
17 
18 */
19 
20 int pushback=-1;
21 
gettoken(FILE * fp,char * token,int flag)22 int gettoken(FILE *fp, char *token, int flag)
23 {
24 int tokentype;
25 int ptr,ch;
26 
27   tokentype=0;
28   ptr=0;
29   token[0]=0;
30 
31   while (1)
32   {
33     if (ptr>15) break;
34 
35     if (pushback!=-1)
36     { ch=pushback; pushback=-1; }
37       else
38     { ch=getc(fp); }
39 
40     if (flag==0)
41     { if ((ch==' ' || ch=='\t') || (ch=='\n' || ch=='\r')) continue; }
42       else
43     { if ((ch==' ' || ch=='\t' || ch=='\n' || ch=='\r') && ptr==0) continue; }
44 
45     if (flag==2 && (ch<'0' || ch>'9'))
46     {
47       ungetc(ch,fp);
48       break;
49     }
50 
51     if (ch==EOF && ptr==0) return -1;
52       else
53     if (ch==EOF) { pushback=ch; break; }
54 
55     if ((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'))
56     {
57       if (tokentype==1) { token[ptr++]=ch; }
58         else
59       if (ptr==0) { token[ptr++]=ch; tokentype=1; }
60         else
61       { pushback=ch; break; }
62     }
63       else
64     if (ch>='0' && ch<='9')
65     {
66       if (tokentype==2) { token[ptr++]=ch; }
67         else
68       if (ptr==0) { token[ptr++]=ch; tokentype=2; }
69         else
70       { pushback=ch; break; }
71     }
72       else
73     {
74       if (ptr==0)
75       {
76         tokentype=3;
77         token[ptr++]=ch;
78         break;
79       }
80         else
81       {
82         pushback=ch;
83         break;
84       }
85     }
86 
87   }
88 
89   token[ptr]=0;
90   return tokentype;
91 }
92 
parse_rtttl(FILE * in,FILE * out,int out_type,struct note_t * note)93 int parse_rtttl(FILE *in, FILE *out, int out_type, struct note_t *note)
94 {
95 char token[16];
96 int t,r,l,ch;
97 int d,o,scale;
98 int length,tone,octave,modifier;
99 
100   d=4;
101   o=6;
102   note->bpm=63;
103   tone=0;
104 
105   scale=-1;
106 
107   l=0;
108   t=0;
109   if (note->songname[0]!=0) t=1;
110   while(1)
111   {
112     ch=getc(in);
113     if (ch==':') break;
114     if (ch==EOF)
115     {
116       printf("Error: Illegal RTTTL format file\n");
117       return -1;
118     }
119 
120     if (l<SONGNAME_LEN-1 && t==0) note->songname[l++]=ch;
121   }
122 
123   if (t!=0) note->songname[l]=0;
124 
125 #ifdef DEBUG
126   printf("\n       Song Name: %s\n",note->songname);
127 #endif
128 
129   r=0;
130   while(1)
131   {
132     if (gettoken(in,token,0)==-1)
133     {
134       printf("Error: Illegal RTTTL format file\n");
135       return -1;
136     }
137 
138     if (r==0)
139     {
140       if (strcmp(token,",")==0) continue;
141         else
142       if (strcmp(token,":")==0) break;
143         else
144       if (strcasecmp(token,"d")==0) r=1;
145         else
146       if (strcasecmp(token,"o")==0) r=2;
147         else
148       if (strcasecmp(token,"b")==0) r=3;
149         else
150       if (strcasecmp(token,"s")==0) r=4;
151         else
152       if (strcasecmp(token,"l")==0) r=5;
153     }
154       else
155     if (strcmp(token,"=")==0)
156     {
157       gettoken(in,token,0);
158 
159       if (r==1) d=atoi(token);
160         else
161       if (r==2) o=atoi(token);
162         else
163       if (r==3) note->bpm=atoi(token);
164         else
165       if (r==4)
166       {
167         if (strcasecmp(token,"n")==0)
168         { note->style=0; }
169           else
170         if (strcasecmp(token,"c")==0)
171         { note->style=1; }
172           else
173         if (strcasecmp(token,"s")==0)
174         { note->style=2; }
175       }
176         else
177       if (r==5) note->flats=atoi(token);
178       r=0;
179     }
180       else
181     {
182       printf("Error: Illegal format\n");
183       return -1;
184     }
185   }
186 
187   if (note->flats==15) note->flats=31;
188 
189 #ifdef DEBUG
190   printf("Default Duration: %d\n",d);
191   printf("   Default Scale: %d\n",o);
192   printf("Beats Per Minute: %d\n",note->bpm);
193   printf("           Style: ");
194   if (note->style==0) printf("Natural\n");
195     else
196   if (note->style==1) printf("Continuous\n");
197     else
198   if (note->style==2) printf("Staccato\n");
199   printf("            Loop: %d\n",note->flats);
200 #endif
201 
202   header_route(out,note,0,out_type);
203 
204   while(1)
205   {
206     t=gettoken(in,token,0);
207     if (t==-1)
208     { break; }
209 
210 #ifdef DEBUG
211     printf("%s\n",token);
212 #endif
213     if (strcmp(token,";")==0) break;
214 
215     length=d;
216 
217     if (t==2)
218     {
219       length=atoi(token);
220       t=gettoken(in,token,0);
221     }
222 
223 #ifdef DEBUG
224     printf("Length: %d\n",length);
225 #endif
226 
227     if (length==1) length=0;
228       else
229     if (length==2) length=1;
230       else
231     if (length==4) length=2;
232       else
233     if (length==8) length=3;
234       else
235     if (length==16) length=4;
236       else
237     if (length==32) length=5;
238 
239     token[0]=tolower(token[0]);
240 
241     if (token[0]=='p') tone=0;
242       else
243     if (token[0]=='a') tone=10;
244       else
245     if (token[0]=='h' || token[0]=='b') tone=12;
246       else
247     if (token[0]=='c') tone=1;
248       else
249     if (token[0]=='d') tone=3;
250       else
251     if (token[0]=='e') tone=5;
252       else
253     if (token[0]=='f') tone=6;
254       else
255     if (token[0]=='g') tone=8;
256       else
257     if (token[0]=='o') tone=1;
258       else
259     if (token[0]=='s') tone=2;
260 
261 #ifdef DEBUG
262   printf("tone: %d\n",tone);
263 #endif
264 
265     t=gettoken(in,token,0);
266 
267     if (token[0]=='=')
268     {
269 #ifdef DEBUG
270 printf("equals\n");
271 #endif
272       t=gettoken(in,token,0);
273 #ifdef DEBUG
274 printf("token: %s\n",token);
275 #endif
276 
277       if (tone==12)
278       {
279         note->bpm=atoi(token);
280         tempo_route(out, note, 0, out_type);
281       }
282         else
283       if (tone==1)
284       {
285         o=atoi(token);
286       }
287         else
288       if (tone==2)
289       {
290         if (strcasecmp(token,"n")==0)
291         { note->style=0; }
292           else
293         if (strcasecmp(token,"c")==0)
294         { note->style=1; }
295           else
296         if (strcasecmp(token,"s")==0)
297         { note->style=2; }
298 
299         if (out_type==4)
300         { write_nokia_style(out, note); }
301       }
302 
303       t=gettoken(in,token,0);
304       if (strcmp(token,",")!=0)
305       {
306         printf("Error: expecting , and found %s\n",token);
307       }
308 
309       continue;
310     }
311 
312     modifier=0;
313     octave=-1;
314 
315     while(1)
316     {
317       if (token[0]==',' || token[0]==';' || t==-1) break;
318 
319       if (token[0]=='#')
320       { tone=tone+1; }
321         else
322       if (t==2)
323       { octave=atoi(token); }
324         else
325       if (strcmp(token,".")==0)
326       { modifier++; }
327 
328       t=gettoken(in,token,0);
329     }
330 
331     if (tone!=0)
332     {
333       if (octave==-1) octave=o;
334       if (tone>12)
335       {
336         tone=tone-12;
337         octave++;
338       }
339 
340       if (scale!=octave)
341       {
342         scale=octave;
343       }
344     }
345 
346     note->tone=tone;
347     note->length=length;
348     note->modifier=modifier;
349     note->scale=octave-note->a440;
350 
351     note_route(out,note,0,out_type);
352 
353     if (t==-1)
354     { break; }
355   }
356 
357   footer_route(out,note,0,out_type);
358 
359   return (0);
360 }
361 
362 
363 
364