Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / diskimage / plugins / cue / flac.c
blob601e8a66cd2510bb8d36b46d612e810b1be21fc7
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 "audio/flac.h"
35 #include "cue.h"
36 #include "rev/diskimage.device_rev.h"
38 BOOL CUE_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
39 BOOL FLAC_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
40 const UBYTE *test, LONG testsize);
41 APTR FLAC_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 flac_plugin = {
51 PLUGIN_NODE(0, "FLAC"),
52 PLUGIN_FLAG_M68K,
54 ZERO,
55 NULL,
56 CUE_Init,
57 NULL,
58 FLAC_CheckImage,
59 FLAC_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 FLAC_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
75 const UBYTE *test, LONG testsize)
77 return testsize >= 4 && FLAC_header(test);
80 LONG cue_fix_track_indexes (struct CUEImage *image);
82 APTR FLAC_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name) {
83 LONG done = FALSE;
84 LONG error = NO_ERROR;
85 LONG error_string = NO_ERROR_STRING;
86 IPTR error_args[4] = {0};
87 struct CUEImage *image = NULL;
88 struct CUEFile *cue_file = NULL;
89 struct CUETrack *track = NULL;
90 struct CUETrack *prev_track = NULL;
91 LONG track_num, index_type;
92 ULONG index;
93 LONG i, j;
94 FLAC_STREAM *stream;
95 FLAC__StreamMetadata_CueSheet *cuesheet;
96 FLAC__StreamMetadata_CueSheet_Track *flac_track;
97 FLAC__StreamMetadata_CueSheet_Index *flac_index;
99 Close(file);
101 image = AllocVec(sizeof(*image), MEMF_CLEAR);
102 if (!image) {
103 error = ERROR_NO_FREE_STORE;
104 goto error;
107 image->files = cue_file = AllocVec(sizeof(*cue_file), MEMF_CLEAR);
108 if (!cue_file) {
109 error = ERROR_NO_FREE_STORE;
110 goto error;
112 cue_file->type = FILE_FLAC;
113 cue_file->f.aud.stream = (AUDIO_STREAM *)(stream = FLAC_open(name, TRUE));
114 if (!stream) {
115 error = IoErr();
116 goto error;
118 if (!stream->cuesheet) {
119 error = ERROR_REQUIRED_ARG_MISSING;
120 goto error;
123 cuesheet = &stream->cuesheet->data.cue_sheet;
124 for (i = 0; i < cuesheet->num_tracks; i++) {
125 flac_track = &cuesheet->tracks[i];
126 track_num = flac_track->number;
127 if (track_num >= 0xA0) {
128 continue;
130 prev_track = track;
131 if (!track) {
132 track = image->tracks = AllocVec(sizeof(*track), MEMF_CLEAR);
133 } else {
134 track = track->next = AllocVec(sizeof(*track), MEMF_CLEAR);
136 if (!track) {
137 error = ERROR_NO_FREE_STORE;
138 break;
140 track->file = cue_file;
141 cue_file->refcount++;
142 track->track_num = track_num;
143 if (!image->first_track || track_num < image->first_track) {
144 image->first_track = track_num;
146 if (!image->last_track || track_num > image->last_track) {
147 image->last_track = track_num;
149 #if defined(__GNUC__)
150 track->audio = !flac_track->type;
151 #else
152 track->audio = !(flac_track->bitfield & 0x80);
153 #endif
154 track->sector_size = 2352;
155 track->sync_size = 16;
156 index = flac_track->offset / SAMPLESPERFRAME;
157 if (prev_track && prev_track->index2 == -1) {
158 prev_track->index2 = index;
160 track->index0 = index;
161 track->index1 = index;
162 track->index2 = -1;
163 for (j = 0; j < flac_track->num_indices; j++) {
164 flac_index = &flac_track->indices[j];
165 index = flac_index->offset / SAMPLESPERFRAME;
166 index_type = flac_index->number;
167 switch (index_type) {
168 case 0:
169 track->index0 = track->index0 + index;
170 break;
171 case 1:
172 track->index1 = track->index0 + index;
173 break;
177 if (error != NO_ERROR) {
178 goto error;
181 if (!image->tracks) {
182 error = ERROR_REQUIRED_ARG_MISSING;
183 goto error;
186 if ((error = cue_fix_track_indexes(image)) != NO_ERROR) {
187 goto error;
190 done = TRUE;
192 error:
193 if (!done) {
194 Plugin_CloseImage(Self, image);
195 image = NULL;
196 if (error == NO_ERROR) {
197 error = ERROR_OBJECT_WRONG_TYPE;
198 error_string = MSG_EOF;
200 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
202 return image;