1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <ctype.h>
5 #include <errno.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8
9 #include "../include/fio.h"
10 #include "../include/disk.h"
11 #include "../include/string.h"
12
13 #include "sound.h"
14 #include "musiclistio.h"
15 #include "sar.h"
16 #include "config.h"
17
18
19 sar_music_ref_struct *SARMusicMatchPtr(
20 sar_music_ref_struct **ml, int total,
21 int id, int *music_ref_num
22 );
23
24 void SARMusicListDeleteAll(
25 sar_music_ref_struct ***ml, int *total
26 );
27 int SARMusicListLoadFromFile(
28 const char *filename,
29 sar_music_ref_struct ***ml, int *total
30 );
31
32
33 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
34 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
35 #define ATOF(s) (((s) != NULL) ? (float)atof(s) : 0.0f)
36 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
37
38 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
39 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
40 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
41 #define STRLEN(s) (((s) != NULL) ? (int)strlen(s) : 0)
42 #define STRISEMPTY(s) (((s) != NULL) ? (*(s) == '\0') : 1)
43
44 #define RADTODEG(r) ((r) * 180.0 / PI)
45 #define DEGTORAD(d) ((d) * PI / 180.0)
46
47
48 /*
49 * Matches the music reference structure in the given list with
50 * the given id code.
51 */
SARMusicMatchPtr(sar_music_ref_struct ** ml,int total,int id,int * music_ref_num)52 sar_music_ref_struct *SARMusicMatchPtr(
53 sar_music_ref_struct **ml, int total,
54 int id, int *music_ref_num
55 )
56 {
57 int i;
58 sar_music_ref_struct *mr_ptr;
59
60
61 if(music_ref_num != NULL)
62 *music_ref_num = -1;
63
64 if((ml == NULL) || (total < 1) || (id < 0))
65 return(NULL);
66
67 for(i = 0; i < total; i++)
68 {
69 mr_ptr = ml[i];
70 if(mr_ptr == NULL)
71 continue;
72
73 if(mr_ptr->id == id)
74 {
75 if(music_ref_num != NULL)
76 *music_ref_num = i;
77 return(mr_ptr);
78 }
79 }
80
81 return(NULL);
82 }
83
84
85 /*
86 * Deletes the Music List.
87 */
SARMusicListDeleteAll(sar_music_ref_struct *** ml,int * total)88 void SARMusicListDeleteAll(
89 sar_music_ref_struct ***ml, int *total
90 )
91 {
92 int i;
93 sar_music_ref_struct *mr_ptr;
94
95 if((ml == NULL) || (total == NULL))
96 return;
97
98 for(i = 0; i < (*total); i++)
99 {
100 mr_ptr = (*ml)[i];
101 if(mr_ptr == NULL)
102 continue;
103
104 free(mr_ptr->filename);
105 free(mr_ptr);
106 }
107
108 if(*ml != NULL)
109 {
110 free(*ml);
111 *ml = NULL;
112 }
113 *total = 0;
114 }
115
116 /*
117 * Loads the Music List from file.
118 */
SARMusicListLoadFromFile(const char * filename,sar_music_ref_struct *** ml,int * total)119 int SARMusicListLoadFromFile(
120 const char *filename,
121 sar_music_ref_struct ***ml, int *total
122 )
123 {
124 int i;
125 FILE *fp;
126 char *buf = NULL;
127 struct stat stat_buf;
128 double value[10];
129 sar_music_ref_struct *mr_ptr = NULL;
130
131 if(STRISEMPTY(filename) || (ml == NULL) || (total == NULL))
132 return(-1);
133
134 /* Delete existing Music List */
135 SARMusicListDeleteAll(ml, total);
136
137 /* Check if the file exists and get its stats */
138 if(stat(filename, &stat_buf))
139 {
140 char *s = STRDUP(strerror(errno));
141 if(s == NULL)
142 s = STRDUP("no such file");
143 *s = toupper(*s);
144 fprintf(
145 stderr,
146 "%s: %s.\n",
147 filename, s
148 );
149 free(s);
150 return(-1);
151 }
152 #ifdef S_ISDIR
153 if(S_ISDIR(stat_buf.st_mode))
154 {
155 fprintf(
156 stderr,
157 "%s: Is a directory.\n",
158 filename
159 );
160 return(-1);
161 }
162 #endif /* S_ISDIR */
163
164 /* Open the music list file for reading */
165 fp = FOpen(filename, "rb");
166 if(fp == NULL)
167 {
168 fprintf(
169 stderr,
170 "%s: Unable to open the Music List file for reading.\n",
171 filename
172 );
173 return(-1);
174 }
175
176 do
177 {
178 buf = FSeekNextParm(
179 fp,
180 buf,
181 SAR_COMMENT_CHAR,
182 SAR_CFG_DELIM_CHAR
183 );
184 if(buf == NULL)
185 break;
186
187 if(!strcasecmp(buf, "Version"))
188 {
189 FGetValuesF(fp, value, 3);
190 }
191
192 else if(!strcasecmp(buf, "MusicAdd"))
193 {
194 char *s = FGetString(fp);
195
196 i = MAX(*total, 0);
197 *total = i + 1;
198 *ml = (sar_music_ref_struct **)realloc(
199 *ml,
200 (*total) * sizeof(sar_music_ref_struct *)
201 );
202 if(*ml == NULL)
203 {
204 *total = 0;
205 break;
206 }
207
208 (*ml)[i] = mr_ptr = SAR_MUSIC_REF(calloc(
209 1, sizeof(sar_music_ref_struct)
210 ));
211 mr_ptr->id = ATOI(s);
212
213 free(s);
214 }
215 else if(!strcasecmp(buf, "MusicFileName"))
216 {
217 char *s = FGetString(fp);
218 if(mr_ptr != NULL)
219 {
220 free(mr_ptr->filename);
221 mr_ptr->filename = STRDUP(s);
222 }
223 free(s);
224 }
225 else if(!strcasecmp(buf, "MusicFlags"))
226 {
227 char *s = FGetString(fp);
228 const char *s2 = s;
229
230 /* Iterate through value string, checking each flag */
231 while((s2 != NULL) ? (*s2 != '\0') : 0)
232 {
233 if(strcasepfx(s2, "repeating"))
234 mr_ptr->flags |= SAR_MUSIC_REF_FLAGS_REPEAT;
235 else if(strcasepfx(s2, "fade_in") ||
236 strcasepfx(s2, "fadein")
237 )
238 mr_ptr->flags |= SAR_MUSIC_REF_FLAGS_FADE_IN;
239 else if(strcasepfx(s2, "fade_out") ||
240 strcasepfx(s2, "fadeout")
241 )
242 mr_ptr->flags |= SAR_MUSIC_REF_FLAGS_FADE_OUT;
243
244 while(!ISBLANK(*s2) && (*s2 != '\0'))
245 s2++;
246 while(ISBLANK(*s2))
247 s2++;
248 }
249
250 free(s);
251 }
252
253 else
254 {
255 fprintf(
256 stderr,
257 "%s: Unsupported parameter \"%s\".\n",
258 filename, buf
259 );
260 FSeekNextLine(fp);
261 }
262
263 } while(1);
264
265 free(buf);
266
267 /* Close file */
268 FClose(fp);
269
270 return(0);
271 }
272