1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
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"
35 #include "audio/wavpack.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
,
47 LONG
CUE_ReadCDDA (struct DiskImagePlugin
*Self
, APTR image_ptr
, APTR buffer_ptr
, ULONG offset
,
50 struct DiskImagePlugin wavpack_plugin
= {
51 PLUGIN_NODE(0, "WavPack"),
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
) {
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
;
95 char *cuesheet
= NULL
;
96 char *cuesheet_start
= NULL
;
97 char *line
, *last_line
= NULL
;
99 STRPTR argv
[MAX_ARGS
];
100 LONG track_num
, index_type
;
102 WAVPACK_STREAM
*stream
;
106 image
= AllocVec(sizeof(*image
), MEMF_CLEAR
);
108 error
= ERROR_NO_FREE_STORE
;
112 image
->files
= cue_file
= AllocVec(sizeof(*cue_file
), MEMF_CLEAR
);
114 error
= ERROR_NO_FREE_STORE
;
117 cue_file
->type
= FILE_WAVPACK
;
118 cue_file
->f
.aud
.stream
= (AUDIO_STREAM
*)(stream
= WAVPACK_open(name
, TRUE
));
124 if ((cue_len
= WavpackGetTagItem(stream
->wpc
, "cuesheet", NULL
, 0))) {
125 cuesheet
= AllocVec(cue_len
+ 1, MEMF_ANY
);
127 error
= ERROR_NO_FREE_STORE
;
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
);
136 error
= ERROR_NO_FREE_STORE
;
139 WavpackGetBinaryTagItem(stream
->wpc
, "cuesheet", cuesheet
, cue_len
);
140 cuesheet
[cue_len
] = 0;
141 cuesheet_start
= cuesheet
+ strlen(cuesheet
) + 1;
143 error
= ERROR_REQUIRED_ARG_MISSING
;
146 line
= strtok_r(cuesheet_start
, "\n", &last_line
);
148 error
= cue_parse_args(line
, argv
, &argc
);
149 if (error
!= NO_ERROR
) break;
151 if (!strcmp(argv
[0], "TRACK")) {
153 error
= ERROR_REQUIRED_ARG_MISSING
;
157 error
= ERROR_TOO_MANY_ARGS
;
164 track
= image
->tracks
= AllocVec(sizeof(*track
), MEMF_CLEAR
);
166 track
= track
->next
= AllocVec(sizeof(*track
), MEMF_CLEAR
);
169 error
= ERROR_NO_FREE_STORE
;
172 track
->file
= cue_file
;
173 cue_file
->refcount
++;
174 if (StrToLong(argv
[1], &track_num
) == -1) {
175 error
= ERROR_BAD_NUMBER
;
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")) {
199 track
->sector_size
= 2352;
200 track
->sync_size
= 16;
202 error
= ERROR_NOT_IMPLEMENTED
;
208 } else if (!strcmp(argv
[0], "INDEX")) {
210 error
= ERROR_REQUIRED_ARG_MISSING
;
214 error
= ERROR_REQUIRED_ARG_MISSING
;
218 error
= ERROR_TOO_MANY_ARGS
;
221 if (StrToLong(argv
[1], &index_type
) == -1) {
222 error
= ERROR_BAD_NUMBER
;
225 error
= cue_parse_index(argv
[2], &index
);
226 if (error
!= NO_ERROR
) break;
227 switch (index_type
) {
229 if (prev_track
&& prev_track
->index2
== -1) {
230 prev_track
->index2
= index
;
232 track
->index0
= index
;
235 if (prev_track
&& prev_track
->index2
== -1) {
236 prev_track
->index2
= index
;
238 track
->index1
= index
;
243 line
= strtok_r(NULL
, "\n", &last_line
);
245 if (error
!= NO_ERROR
) {
249 if (!image
->tracks
) {
250 error
= ERROR_REQUIRED_ARG_MISSING
;
254 if ((error
= cue_fix_track_indexes(image
)) != NO_ERROR
) {
263 Plugin_CloseImage(Self
, image
);
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
);
274 char *strtok_r (char *str
, const char *sep_set
, char **state_ptr
) {
276 char *last
= *state_ptr
;
280 if (str
== NULL
) goto out
;
283 str
+= strspn(str
, sep_set
);
284 if (*str
== 0) goto out
;
285 size
= strcspn(str
, sep_set
);
286 if (size
== 0) goto out
;
288 if (*last
!= 0) last
++;