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