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 
get_next(FILE * in)20 int get_next(FILE *in)
21 {
22 int ch;
23 
24   while(1)
25   {
26     ch=getc(in);
27 
28     if (ch==' ' || ch=='\t')
29     { continue; }
30       else
31     if (ch=='\n' || ch=='\r')
32     {
33       ch=getc(in);
34       if (ch!='\r' && ch!='\n') ungetc(ch,in);
35       return '\n';
36     }
37       else
38     if (ch==EOF)
39     { return EOF; }
40       else
41     { return tolower(ch); }
42   }
43 
44   return 0;
45 }
46 
get_field(FILE * in,char * field_name,char * field_value)47 int get_field(FILE *in, char *field_name, char *field_value)
48 {
49 int ch,ptr,p;
50 char *buffer;
51 int marker;
52 
53   buffer=field_name;
54   marker=ftell(in);
55 
56   field_name[0]=0;
57   field_value[0]=0;
58 
59   ptr=0; p=0;
60   while(1)
61   {
62     ch=getc(in);
63 
64     if (ptr==0 && p==0)
65     {
66       if (ch=='\r' || ch=='\n') continue;
67       if (ch==EOF) return -1;
68     }
69 
70     if (ch==':' && p==0)
71     {
72       buffer[ptr]=0;
73       if (strcasecmp(buffer,"melody")==0) return 2;
74 
75       buffer=field_value;
76       ptr=0;
77       p++;
78       continue;
79     }
80 
81     if (ch=='\n' || ch=='\r' || ch==EOF || ptr==1023)
82     {
83       if (p==0)
84       {
85         fseek(in,marker,SEEK_SET);
86         return 1;
87       }
88 
89       buffer[ptr]=0;
90       return 0;
91     }
92 
93     buffer[ptr++]=ch;
94   }
95 
96   return 0;
97 }
98 
parse_num(FILE * in)99 int parse_num(FILE *in)
100 {
101 int ch,i;
102 
103   i=0;
104 
105   while(1)
106   {
107     ch=getc(in);
108     if (ch>='0' && ch<='9')
109     {
110       i=(i*10)+(ch-'0');
111     }
112       else
113     { ungetc(ch,in); return i; }
114   }
115 }
116 
parse_melody(FILE * in,FILE * out,struct note_t * note,int out_type)117 void parse_melody(FILE *in, FILE *out, struct note_t *note, int out_type)
118 {
119 int ch,t;
120 int tone_modifier;
121 int repeat,repeat_count=0;
122 unsigned char default_octave;
123 char token[255];
124 
125   default_octave=4;
126   tone_modifier=0;
127   repeat=ftell(in);
128 
129   header_route(out,note,1,out_type);
130 
131   while(1)
132   {
133     ch=get_next(in);
134     if (ch==EOF || ch=='\n') break;
135 
136     if (ch=='*')
137     {
138       ch=get_next(in);
139       if (ch==EOF || ch=='\n') break;
140 
141       default_octave=ch-'0';
142       if (default_octave>8) default_octave=4;
143       continue;
144     }
145 
146     if (ch=='{')
147     {
148       repeat=ftell(in);
149 
150       continue;
151     }
152 
153     if (ch=='}')
154     {
155       ch=get_next(in);
156       if (ch==EOF || ch=='\n') break;
157       if (ch=='@')
158       {
159         gettoken(in,token,2);
160         t=atoi(token);
161 #ifdef DEBUG
162         printf("%d\n",t);
163 #endif
164         if (repeat_count<t)
165         { fseek(in,repeat,SEEK_SET); }
166 
167         repeat_count++;
168 
169         continue;
170       }
171 
172       break;
173     }
174 
175     if (ch=='v')
176     {
177       ch=get_next(in);
178       if (ch==EOF || ch=='\n') break;
179 
180       if (ch=='-') { note->volume--; }
181         else
182       if (ch=='+') { note->volume++; }
183         else
184       if (ch>='0' && ch<='9') note->volume=parse_num(in);
185 
186       if (note->volume<0) note->volume=0;
187         else
188       if (note->volume>15) note->volume=15;
189 
190       volume_route(out,note,1,out_type);
191 
192       continue;
193     }
194 
195     if (ch=='#')
196     {
197       tone_modifier=1;
198       continue;
199     }
200 
201     if (ch=='&')
202     {
203       tone_modifier=-1;
204       continue;
205     }
206 
207     if (ch=='a') note->tone=10;
208       else
209     if (ch=='h' || ch=='b') note->tone=12;
210       else
211     if (ch=='c') note->tone=1;
212       else
213     if (ch=='d') note->tone=3;
214       else
215     if (ch=='e') note->tone=5;
216       else
217     if (ch=='f') note->tone=6;
218       else
219     if (ch=='g') note->tone=8;
220       else
221     if (ch=='p' || ch=='r') note->tone=0;
222 
223     note->tone=note->tone+tone_modifier;
224     if (note->tone<1 && ch!='r' && ch!='p')
225     {
226       note->tone=12;
227       note->scale--;
228     }
229       else
230     if (note->tone>12)
231     {
232       note->tone=1;
233       note->scale++;
234     }
235 
236     ch=get_next(in);
237     /* if (ch==EOF || ch=='\n') break; */
238 
239     note->length=2;
240     if (ch>='0' && ch<='5')
241     {
242       note->length=ch-'0';
243       ch=get_next(in);
244     }
245 
246     if (ch=='.') note->modifier=1;
247       else
248     if (ch==':') note->modifier=2;
249       else
250     if (ch==';') note->modifier=3;
251       else
252     {
253       ungetc(ch,in);
254       note->modifier=0;
255     }
256 
257     note->scale=default_octave-3;
258     if (note->scale<0) note->scale=0;
259 
260     note_route(out,note,1,out_type);
261 
262     if (ch==EOF || ch=='\n') break;
263 
264     tone_modifier=0;
265   }
266 
267   footer_route(out,note,1,out_type);
268 }
269 
parse_imelody(FILE * in,FILE * out,int out_type,struct note_t * note)270 int parse_imelody(FILE *in, FILE *out, int out_type, struct note_t *note)
271 {
272 char field_name[1024],field_value[1024];
273 int i;
274 
275   note->bpm=120;
276 
277   while(1)
278   {
279     i=get_field(in,field_name,field_value);
280 
281     if (i==1 || i==2)
282     {
283       parse_melody(in,out,note,out_type);
284       break;
285     }
286       else
287     if (i==-1)
288     { break; }
289 
290     if (strcasecmp(field_name,"name")==0)
291     {
292       strncpy(note->songname,field_value,SONGNAME_LEN);
293       note->songname[SONGNAME_LEN-1]=0;
294     }
295       else
296     if (strcasecmp(field_name,"beat")==0)
297     {
298       note->bpm=atoi(field_value);
299       if (note->bpm==0) note->bpm=120;
300     }
301       else
302     if (strcasecmp(field_name,"volume")==0)
303     {
304       note->volume=atoi(field_value);
305       if (note->volume<=0 || note->volume>15) note->volume=7;
306     }
307       else
308     if (strcasecmp(field_name,"style")==0 && strlen(field_value)==2)
309     {
310       note->style=field_value[1]-'0';
311       if (note->style<0 || note->style>2) note->style=0;
312     }
313   }
314 
315   return (0);
316 }
317 
318 
319 
320