1 /*
2  * cd.c -- cd functions
3  *
4  * Copyright (C) 2004, 2005, 2006, 2007, 2013 Svend Sorensen
5  * For license terms, see the file COPYING in this distribution.
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "cd.h"
12 
13 typedef struct Data Data;
14 struct Data {
15 	int type;			/* DataType */
16 	char *name;			/* data source name */
17 	long start;			/* start time for data */
18 	long length;			/* length of data */
19 };
20 
21 struct Track {
22 	Data zero_pre;			/* pre-gap generated with zero data */
23 	Data file;			/* track data file */
24 	Data zero_post;			/* post-gap generated with zero data */
25 	int mode;			/* track mode */
26 	int sub_mode;			/* sub-channel mode */
27 	int flags;			/* flags */
28 	char *isrc;			/* IRSC Code (5.22.4) 12 bytes */
29 	Cdtext *cdtext;			/* CD-TEXT */
30 	int nindex;			/* number of indexes */
31 	long index[MAXINDEX];		/* indexes (in frames) (5.29.2.5)
32 					 * relative to start of track
33 					 * index[0] should always be zero */
34 };
35 
36 struct Cd {
37 	int mode;			/* disc mode */
38 	char *catalog;			/* Media Catalog Number (5.22.3) */
39 	Cdtext *cdtext;			/* CD-TEXT */
40 	int ntrack;			/* number of tracks in album */
41 	Track *track[MAXTRACK];		/* array of tracks */
42 };
43 
cd_init()44 Cd *cd_init()
45 {
46 	Cd *cd = NULL;
47 	cd = malloc(sizeof(Cd));
48 
49 	if(NULL == cd) {
50 		fprintf(stderr, "unable to create cd\n");
51 	} else {
52 		cd->mode = MODE_CD_DA;
53 		cd->catalog = NULL;
54 		cd->cdtext = cdtext_init();
55 		cd->ntrack = 0;
56 	}
57 
58 	return cd;
59 }
60 
track_init()61 Track *track_init()
62 {
63 	Track *track = NULL;
64 	track = malloc(sizeof(Track));
65 
66 	if (NULL == track) {
67 		fprintf(stderr, "unable to create track\n");
68 	} else {
69 		track->zero_pre.type = DATA_ZERO;
70 		track->zero_pre.name = NULL;
71 		track->zero_pre.start = 0;
72 		track->zero_pre.length = 0;
73 
74 		track->file.type = DATA_AUDIO;
75 		track->file.name = NULL;
76 		track->file.start = 0;
77 		track->file.length = 0;
78 
79 		track->zero_post.type = DATA_ZERO;
80 		track->zero_post.name = NULL;
81 		track->zero_post.start = 0;
82 		track->zero_post.length = 0;
83 
84 		track->mode = MODE_AUDIO;
85 		track->sub_mode = SUB_MODE_RW;
86 		track->flags = FLAG_NONE;
87 		track->isrc = NULL;
88 		track->cdtext = cdtext_init();
89 		track->nindex = 0;
90 	}
91 
92 	return track;
93 }
94 
95 /*
96  * cd structure functions
97  */
cd_set_mode(Cd * cd,int mode)98 void cd_set_mode(Cd *cd, int mode)
99 {
100 	cd->mode = mode;
101 }
102 
cd_get_mode(Cd * cd)103 int cd_get_mode(Cd *cd)
104 {
105 	return cd->mode;
106 }
107 
cd_set_catalog(Cd * cd,char * catalog)108 void cd_set_catalog(Cd *cd, char *catalog)
109 {
110 	if (cd->catalog) {
111 		free(cd->catalog);
112 	}
113 
114 	cd->catalog = strdup(catalog);
115 }
116 
cd_get_catalog(Cd * cd)117 char *cd_get_catalog(Cd *cd)
118 {
119 	return cd->catalog;
120 }
121 
cd_get_cdtext(Cd * cd)122 Cdtext *cd_get_cdtext(Cd *cd)
123 {
124 	return cd->cdtext;
125 }
126 
cd_add_track(Cd * cd)127 Track *cd_add_track(Cd *cd)
128 {
129 	if (MAXTRACK > cd->ntrack) {
130 		cd->ntrack++;
131 	} else {
132 		fprintf(stderr, "too many tracks\n");
133 	}
134 
135 	/* this will reinit last track if there were too many */
136 	cd->track[cd->ntrack - 1] = track_init();
137 
138 	return cd->track[cd->ntrack - 1];
139 }
140 
141 
cd_get_ntrack(Cd * cd)142 int cd_get_ntrack(Cd *cd)
143 {
144 	return cd->ntrack;
145 }
146 
cd_get_track(Cd * cd,int i)147 Track *cd_get_track(Cd *cd, int i)
148 {
149 	if (0 < i && i <= cd->ntrack) {
150 		return cd->track[i - 1];
151 	}
152 
153 	return NULL;
154 }
155 
156 /*
157  * track structure functions
158  */
159 
track_set_filename(Track * track,char * filename)160 void track_set_filename(Track *track, char *filename)
161 {
162 	if (track->file.name) {
163 		free(track->file.name);
164 	}
165 
166 	track->file.name = strdup(filename);
167 }
168 
track_get_filename(Track * track)169 char *track_get_filename(Track *track)
170 {
171 	return track->file.name;
172 }
173 
track_set_start(Track * track,long start)174 void track_set_start(Track *track, long start)
175 {
176 	track->file.start = start;
177 }
178 
track_get_start(Track * track)179 long track_get_start(Track *track)
180 {
181 	return track->file.start;
182 }
183 
track_set_length(Track * track,long length)184 void track_set_length(Track *track, long length)
185 {
186 	track->file.length = length;
187 }
188 
track_get_length(Track * track)189 long track_get_length(Track *track)
190 {
191 	return track->file.length;
192 }
193 
track_set_mode(Track * track,int mode)194 void track_set_mode(Track *track, int mode)
195 {
196 	track->mode = mode;
197 }
198 
track_get_mode(Track * track)199 int track_get_mode(Track *track)
200 {
201 	return track->mode;
202 }
203 
track_set_sub_mode(Track * track,int sub_mode)204 void track_set_sub_mode(Track *track, int sub_mode)
205 {
206 	track->sub_mode = sub_mode;
207 }
208 
track_get_sub_mode(Track * track)209 int track_get_sub_mode(Track *track)
210 {
211 	return track->sub_mode;
212 }
213 
track_set_flag(Track * track,int flag)214 void track_set_flag(Track *track, int flag)
215 {
216 	track->flags |= flag;
217 }
218 
track_clear_flag(Track * track,int flag)219 void track_clear_flag(Track *track, int flag)
220 {
221 	track->flags &= ~flag;
222 }
223 
track_is_set_flag(Track * track,int flag)224 int track_is_set_flag(Track *track, int flag)
225 {
226 	return track->flags & flag;
227 }
228 
track_set_zero_pre(Track * track,long length)229 void track_set_zero_pre(Track *track, long length)
230 {
231 	track->zero_pre.length = length;
232 }
233 
track_get_zero_pre(Track * track)234 long track_get_zero_pre(Track *track)
235 {
236 	return track->zero_pre.length;
237 }
238 
track_set_zero_post(Track * track,long length)239 void track_set_zero_post(Track *track, long length)
240 {
241 	track->zero_post.length = length;
242 }
243 
track_get_zero_post(Track * track)244 long track_get_zero_post(Track *track)
245 {
246 	return track->zero_post.length;
247 }
track_set_isrc(Track * track,char * isrc)248 void track_set_isrc(Track *track, char *isrc)
249 {
250 	if (track->isrc) {
251 		free(track->isrc);
252 	}
253 
254 	track->isrc = strdup(isrc);
255 }
256 
track_get_isrc(Track * track)257 char *track_get_isrc(Track *track)
258 {
259 	return track->isrc;
260 }
261 
track_get_cdtext(Track * track)262 Cdtext *track_get_cdtext(Track *track)
263 {
264 	return track->cdtext;
265 }
266 
track_add_index(Track * track,long index)267 void track_add_index(Track *track, long index)
268 {
269 	if (MAXINDEX > track->nindex) {
270 		track->nindex++;
271 	} else {
272 		fprintf(stderr, "too many indexes\n");
273 	}
274 
275 	/* this will overwrite last index if there were too many */
276 	track->index[track->nindex - 1] = index;
277 }
278 
track_get_nindex(Track * track)279 int track_get_nindex(Track *track)
280 {
281 	return track->nindex;
282 }
283 
track_get_index(Track * track,int i)284 long track_get_index(Track *track, int i)
285 {
286 	if (0 <= i && i < track->nindex) {
287 		return track->index[i];
288 	}
289 
290 	return -1;
291 }
292 
293 /*
294  * dump cd information
295  */
cd_track_dump(Track * track)296 void cd_track_dump(Track *track)
297 {
298 	int i;
299 
300 	printf("zero_pre: %ld\n", track->zero_pre.length);
301 	printf("filename: %s\n", track->file.name);
302 	printf("start: %ld\n", track->file.start);
303 	printf("length: %ld\n", track->file.length);
304 	printf("zero_post: %ld\n", track->zero_post.length);
305 	printf("mode: %d\n", track->mode);
306 	printf("sub_mode: %d\n", track->sub_mode);
307 	printf("flags: 0x%x\n", track->flags);
308 	printf("isrc: %s\n", track->isrc);
309 	printf("indexes: %d\n", track->nindex);
310 
311 	for (i = 0; i < track->nindex; ++i) {
312 		printf("index %d: %ld\n", i, track->index[i]);
313 	}
314 
315 	if (NULL != track->cdtext) {
316 		printf("cdtext:\n");
317 		cdtext_dump(track->cdtext, 1);
318 	}
319 }
320 
cd_dump(Cd * cd)321 void cd_dump(Cd *cd)
322 {
323 	int i;
324 
325 	printf("Disc Info\n");
326 	printf("mode: %d\n", cd->mode);
327 	printf("catalog: %s\n", cd->catalog);
328 	if (NULL != cd->cdtext) {
329 		printf("cdtext:\n");
330 		cdtext_dump(cd->cdtext, 0);
331 	}
332 
333 	for (i = 0; i < cd->ntrack; ++i) {
334 		printf("Track %d Info\n", i + 1);
335 		cd_track_dump(cd->track[i]);
336 	}
337 }
338