Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / diskimage / plugins / cue / wavpack.c
blob7b7eea3abf1706d34b85e474390aa090c835d172
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #define USED_PLUGIN_API_VERSION 8
28 #include <devices/diskimage.h>
29 #include <interfaces/diplugin.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include "device_locale.h"
33 #include "scsicmd.h"
34 #include <string.h>
35 #include "audio/wavpack.h"
36 #include "cue.h"
38 BOOL CUE_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
39 BOOL WavPack_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
40 const UBYTE *test, LONG testsize);
41 APTR WavPack_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
42 void CUE_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
43 LONG CUE_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
44 LONG CUE_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
45 void CUE_GetCDTracks (struct DiskImagePlugin *Self, APTR image_ptr, struct CDTrack **tracks,
46 ULONG *num_tracks);
47 LONG CUE_ReadCDDA (struct DiskImagePlugin *Self, APTR image_ptr, APTR buffer_ptr, ULONG offset,
48 ULONG size);
50 struct DiskImagePlugin wavpack_plugin = {
51 PLUGIN_NODE(0, "WavPack"),
52 PLUGIN_FLAG_M68K,
54 ZERO,
55 NULL,
56 CUE_Init,
57 NULL,
58 WavPack_CheckImage,
59 WavPack_OpenImage,
60 CUE_CloseImage,
61 CUE_Geometry,
62 CUE_Read,
63 NULL,
64 NULL,
65 NULL,
66 CUE_GetCDTracks,
67 CUE_ReadCDDA
70 extern struct Library *SysBase;
71 extern struct Library *DOSBase;
72 extern struct DIPluginIFace *IPlugin;
74 BOOL WavPack_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
75 const UBYTE *test, LONG testsize)
77 return testsize >= 4 && WAVPACK_header(test);
80 LONG cue_parse_args (STRPTR cmd, STRPTR *argv, LONG *argc_ptr);
81 LONG cue_parse_index (CONST_STRPTR index_str, ULONG *index);
82 LONG cue_fix_track_indexes (struct CUEImage *image);
83 char *strtok_r (char *str, const char *sep_set, char **state_ptr);
85 APTR WavPack_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name) {
86 LONG done = FALSE;
87 LONG error = NO_ERROR;
88 LONG error_string = NO_ERROR_STRING;
89 IPTR error_args[4] = {0};
90 struct CUEImage *image = NULL;
91 struct CUEFile *cue_file = NULL;
92 struct CUETrack *track = NULL;
93 struct CUETrack *prev_track = NULL;
94 ULONG cue_len;
95 char *cuesheet = NULL;
96 char *cuesheet_start = NULL;
97 char *line, *last_line = NULL;
98 LONG argc;
99 STRPTR argv[MAX_ARGS];
100 LONG track_num, index_type;
101 ULONG index;
102 WAVPACK_STREAM *stream;
104 Close(file);
106 image = AllocVec(sizeof(*image), MEMF_CLEAR);
107 if (!image) {
108 error = ERROR_NO_FREE_STORE;
109 goto error;
112 image->files = cue_file = AllocVec(sizeof(*cue_file), MEMF_CLEAR);
113 if (!cue_file) {
114 error = ERROR_NO_FREE_STORE;
115 goto error;
117 cue_file->type = FILE_WAVPACK;
118 cue_file->f.aud.stream = (AUDIO_STREAM *)(stream = WAVPACK_open(name, TRUE));
119 if (!stream) {
120 error = IoErr();
121 goto error;
124 if ((cue_len = WavpackGetTagItem(stream->wpc, "cuesheet", NULL, 0))) {
125 cuesheet = AllocVec(cue_len + 1, MEMF_ANY);
126 if (!cuesheet) {
127 error = ERROR_NO_FREE_STORE;
128 goto error;
130 WavpackGetTagItem(stream->wpc, "cuesheet", cuesheet, cue_len);
131 cuesheet[cue_len] = 0;
132 cuesheet_start = cuesheet;
133 } else if ((cue_len = WavpackGetBinaryTagItem(stream->wpc, "cuesheet", NULL, 0))) {
134 cuesheet = AllocVec(cue_len + 1, MEMF_ANY);
135 if (!cuesheet) {
136 error = ERROR_NO_FREE_STORE;
137 goto error;
139 WavpackGetBinaryTagItem(stream->wpc, "cuesheet", cuesheet, cue_len);
140 cuesheet[cue_len] = 0;
141 cuesheet_start = cuesheet + strlen(cuesheet) + 1;
142 } else {
143 error = ERROR_REQUIRED_ARG_MISSING;
144 goto error;
146 line = strtok_r(cuesheet_start, "\n", &last_line);
147 while (line) {
148 error = cue_parse_args(line, argv, &argc);
149 if (error != NO_ERROR) break;
150 if (argc > 0) {
151 if (!strcmp(argv[0], "TRACK")) {
152 if (argc < 3) {
153 error = ERROR_REQUIRED_ARG_MISSING;
154 break;
156 if (argc > 3) {
157 error = ERROR_TOO_MANY_ARGS;
158 break;
160 if (track) {
161 prev_track = track;
163 if (!track) {
164 track = image->tracks = AllocVec(sizeof(*track), MEMF_CLEAR);
165 } else {
166 track = track->next = AllocVec(sizeof(*track), MEMF_CLEAR);
168 if (!track) {
169 error = ERROR_NO_FREE_STORE;
170 break;
172 track->file = cue_file;
173 cue_file->refcount++;
174 if (StrToLong(argv[1], &track_num) == -1) {
175 error = ERROR_BAD_NUMBER;
176 break;
178 track->track_num = track_num;
179 if (!image->first_track || track_num < image->first_track) {
180 image->first_track = track_num;
182 if (!image->last_track || track_num > image->last_track) {
183 image->last_track = track_num;
185 if (!strcmp(argv[2], "MODE1/2048")) {
186 track->audio = FALSE;
187 track->sector_size = 2048;
188 track->sync_size = 0;
189 } else if (!strcmp(argv[2], "MODE1/2352")) {
190 track->audio = FALSE;
191 track->sector_size = 2352;
192 track->sync_size = 16;
193 } else if (!strcmp(argv[2], "MODE2/2352")) {
194 track->audio = FALSE;
195 track->sector_size = 2352;
196 track->sync_size = 24;
197 } else if (!strcmp(argv[2], "AUDIO")) {
198 track->audio = TRUE;
199 track->sector_size = 2352;
200 track->sync_size = 16;
201 } else {
202 error = ERROR_NOT_IMPLEMENTED;
203 break;
205 track->index0 = -1;
206 track->index1 = -1;
207 track->index2 = -1;
208 } else if (!strcmp(argv[0], "INDEX")) {
209 if (!track) {
210 error = ERROR_REQUIRED_ARG_MISSING;
211 break;
213 if (argc < 3) {
214 error = ERROR_REQUIRED_ARG_MISSING;
215 break;
217 if (argc > 3) {
218 error = ERROR_TOO_MANY_ARGS;
219 break;
221 if (StrToLong(argv[1], &index_type) == -1) {
222 error = ERROR_BAD_NUMBER;
223 break;
225 error = cue_parse_index(argv[2], &index);
226 if (error != NO_ERROR) break;
227 switch (index_type) {
228 case 0:
229 if (prev_track && prev_track->index2 == -1) {
230 prev_track->index2 = index;
232 track->index0 = index;
233 break;
234 case 1:
235 if (prev_track && prev_track->index2 == -1) {
236 prev_track->index2 = index;
238 track->index1 = index;
239 break;
243 line = strtok_r(NULL, "\n", &last_line);
245 if (error != NO_ERROR) {
246 goto error;
249 if (!image->tracks) {
250 error = ERROR_REQUIRED_ARG_MISSING;
251 goto error;
254 if ((error = cue_fix_track_indexes(image)) != NO_ERROR) {
255 goto error;
258 done = TRUE;
260 error:
261 FreeVec(cuesheet);
262 if (!done) {
263 Plugin_CloseImage(Self, image);
264 image = NULL;
265 if (error == NO_ERROR) {
266 error = ERROR_OBJECT_WRONG_TYPE;
267 error_string = MSG_EOF;
269 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
271 return image;
274 char *strtok_r (char *str, const char *sep_set, char **state_ptr) {
275 char *result = NULL;
276 char *last = *state_ptr;
277 size_t size;
278 if (str == NULL) {
279 str = last;
280 if (str == NULL) goto out;
282 last = NULL;
283 str += strspn(str, sep_set);
284 if (*str == 0) goto out;
285 size = strcspn(str, sep_set);
286 if (size == 0) goto out;
287 last = &str[size];
288 if (*last != 0) last++;
289 str[size] = 0;
290 result = str;
291 out:
292 *state_ptr = last;
293 return result;