1 /*
2 Copyright (C) 2004-2005, 2008, 2010-2011, 2013, 2017
3 Rocky Bernstein <rocky@gnu.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /*! Common image routines.
20
21 Because _img_private_t may vary over image formats, the routines are
22 included into the image drivers after _img_private_t is defined. In
23 order for the below routines to work, there is a large part of
24 _img_private_t that is common among image drivers. For example, see
25 image.h
26 */
27
28 #include "image.h"
29 #include "image_common.h"
30 #include <cdio/util.h>
31 #include "_cdio_stdio.h"
32
33 #ifdef HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif
36
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #endif
40
41 /*!
42 Eject media -- there's nothing to do here except free resources.
43 We always return DRIVER_OP_UNSUPPORTED.
44 */
45 driver_return_code_t
_eject_media_image(void * p_user_data)46 _eject_media_image(void *p_user_data)
47 {
48 _free_image (p_user_data);
49 return DRIVER_OP_UNSUPPORTED;
50 }
51
52 /*!
53 We don't need the image any more. Free all memory associated with
54 it.
55 */
56 void
_free_image(void * p_user_data)57 _free_image (void *p_user_data)
58 {
59 _img_private_t *p_env = p_user_data;
60 track_t i_track;
61
62 if (NULL == p_env) return;
63
64 for (i_track=0; i_track < p_env->gen.i_tracks; i_track++) {
65 track_info_t *p_tocent = &(p_env->tocent[i_track]);
66 CDIO_FREE_IF_NOT_NULL(p_tocent->filename);
67 CDIO_FREE_IF_NOT_NULL(p_tocent->isrc);
68 if (p_tocent->data_source) cdio_stdio_destroy(p_tocent->data_source);
69 }
70
71 CDIO_FREE_IF_NOT_NULL(p_env->psz_mcn);
72 CDIO_FREE_IF_NOT_NULL(p_env->psz_cue_name);
73 CDIO_FREE_IF_NOT_NULL(p_env->psz_access_mode);
74 cdtext_destroy(p_env->gen.cdtext);
75 cdio_generic_stdio_free(p_env);
76 free(p_env);
77 }
78
79 /*!
80 Return the value associated with the key "arg".
81 */
82 const char *
_get_arg_image(void * user_data,const char key[])83 _get_arg_image (void *user_data, const char key[])
84 {
85 _img_private_t *p_env = user_data;
86
87 if (!strcmp (key, "source")) {
88 return p_env->gen.source_name;
89 } else if (!strcmp (key, "cue")) {
90 return p_env->psz_cue_name;
91 } else if (!strcmp(key, "access-mode")) {
92 return "image";
93 } else if (!strcmp (key, "mmc-supported?")) {
94 return "false";
95 }
96 return NULL;
97 }
98
99 /*!
100 Return CD-Text object
101 */
102 cdtext_t *
_get_cdtext_image(void * user_data)103 _get_cdtext_image (void *user_data)
104 {
105 generic_img_private_t *p_env = user_data;
106
107 if(!p_env)
108 return NULL;
109
110 return p_env->cdtext;
111 }
112
113 /*!
114 Get disc type associated with cd_obj.
115 */
116 discmode_t
_get_discmode_image(void * p_user_data)117 _get_discmode_image (void *p_user_data)
118 {
119 _img_private_t *p_env = p_user_data;
120 return p_env->disc_mode;
121 }
122
123 /*!
124 Return the the kind of drive capabilities of device.
125
126 */
127 void
_get_drive_cap_image(const void * user_data,cdio_drive_read_cap_t * p_read_cap,cdio_drive_write_cap_t * p_write_cap,cdio_drive_misc_cap_t * p_misc_cap)128 _get_drive_cap_image (const void *user_data,
129 cdio_drive_read_cap_t *p_read_cap,
130 cdio_drive_write_cap_t *p_write_cap,
131 cdio_drive_misc_cap_t *p_misc_cap)
132 {
133
134 *p_read_cap = CDIO_DRIVE_CAP_READ_CD_DA
135 | CDIO_DRIVE_CAP_READ_CD_G
136 | CDIO_DRIVE_CAP_READ_CD_R
137 | CDIO_DRIVE_CAP_READ_CD_RW
138 | CDIO_DRIVE_CAP_READ_MODE2_FORM1
139 | CDIO_DRIVE_CAP_READ_MODE2_FORM2
140 | CDIO_DRIVE_CAP_READ_MCN
141 ;
142
143 *p_write_cap = 0;
144
145 /* In the future we may want to simulate
146 LOCK, OPEN_TRAY, CLOSE_TRAY, SELECT_SPEED, etc.
147 */
148 *p_misc_cap = CDIO_DRIVE_CAP_MISC_FILE;
149 }
150
151 /*!
152 Return the number of of the first track.
153 CDIO_INVALID_TRACK is returned on error.
154 */
155 track_t
_get_first_track_num_image(void * p_user_data)156 _get_first_track_num_image(void *p_user_data)
157 {
158 _img_private_t *p_env = p_user_data;
159
160 if (!p_env->gen.toc_init)
161 p_env->gen.cdio->op.read_toc (p_user_data);
162
163 return p_env->gen.toc_init ? p_env->gen.i_first_track : CDIO_INVALID_TRACK;
164 }
165
166 /*!
167 Find out if media has changed since the last call.
168 @param p_user_data the CD object to be acted upon.
169 @return 1 if media has changed since last call, 0 if not. Error
170 return codes are the same as driver_return_code_t
171 There is no such thing as changing a media image so we will
172 always return 0 - no change.
173 */
174 int
get_media_changed_image(const void * p_user_data)175 get_media_changed_image(const void *p_user_data)
176 {
177 return 0;
178 }
179
180 /*!
181 Return the media catalog number (MCN) from the CD or NULL if there
182 is none or we don't have the ability to get it.
183
184 Note: string is malloc'd so caller has to free() the returned
185 string when done with it.
186 */
187 char *
_get_mcn_image(const void * p_user_data)188 _get_mcn_image(const void *p_user_data)
189 {
190 const _img_private_t *p_env = p_user_data;
191
192 if (!p_env || !p_env->psz_mcn) return NULL;
193 return strdup(p_env->psz_mcn);
194 }
195
196 /*!
197 Return the number of tracks.
198 */
199 track_t
_get_num_tracks_image(void * p_user_data)200 _get_num_tracks_image(void *p_user_data)
201 {
202 _img_private_t *p_env = p_user_data;
203
204 return p_env->gen.i_tracks;
205 }
206
207 /*!
208 Return the starting MSF (minutes/secs/frames) for the track number
209 track_num in obj. Tracks numbers start at 1.
210 The "leadout" track is specified either by
211 using track_num LEADOUT_TRACK or the total tracks+1.
212
213 */
214 bool
_get_track_msf_image(void * p_user_data,track_t i_track,msf_t * msf)215 _get_track_msf_image(void *p_user_data, track_t i_track, msf_t *msf)
216 {
217 const _img_private_t *p_env = p_user_data;
218
219 if (NULL == msf) return false;
220
221 if (i_track == CDIO_CDROM_LEADOUT_TRACK)
222 i_track = p_env->gen.i_tracks + p_env->gen.i_first_track;
223
224 if (i_track >= p_env->gen.i_first_track &&
225 i_track <= p_env->gen.i_tracks + p_env->gen.i_first_track) {
226 *msf = p_env->tocent[i_track-p_env->gen.i_first_track].start_msf;
227 return true;
228 } else
229 return false;
230 }
231
232 /*! Return number of channels in track: 2 or 4; -2 if not
233 implemented or -1 for error.
234 Not meaningful if track is not an audio track.
235 */
236 int
get_track_channels_image(const void * p_user_data,track_t i_track)237 get_track_channels_image(const void *p_user_data, track_t i_track)
238 {
239 const _img_private_t *p_env = p_user_data;
240 return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
241 & FOUR_CHANNEL_AUDIO ) ? 4 : 2;
242 }
243
244 /*! Return 1 if copy is permitted on the track, 0 if not, or -1 for error.
245 Is this meaningful if not an audio track?
246 */
247 track_flag_t
get_track_copy_permit_image(void * p_user_data,track_t i_track)248 get_track_copy_permit_image(void *p_user_data, track_t i_track)
249 {
250 const _img_private_t *p_env = p_user_data;
251 return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
252 & COPY_PERMITTED ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
253 }
254
255 /*! Return 1 if track has pre-emphasis, 0 if not, or -1 for error.
256 Is this meaningful if not an audio track?
257
258 pre-emphasis is a non linear frequency response.
259 */
260 track_flag_t
get_track_preemphasis_image(const void * p_user_data,track_t i_track)261 get_track_preemphasis_image(const void *p_user_data, track_t i_track)
262 {
263 const _img_private_t *p_env = p_user_data;
264 return ( p_env->tocent[i_track-p_env->gen.i_first_track].flags
265 & PRE_EMPHASIS ) ? CDIO_TRACK_FLAG_TRUE : CDIO_TRACK_FLAG_FALSE;
266 }
267
268 /*! Return the starting LBA for the pregap for track number i_track.
269 Track numbers start at 1.
270 CDIO_INVALID_LBA is returned on error.
271 */
272 lba_t
get_track_pregap_lba_image(const void * p_user_data,track_t i_track)273 get_track_pregap_lba_image(const void *p_user_data, track_t i_track)
274 {
275 const _img_private_t *p_env = p_user_data;
276 lba_t pregap, start_lba;
277
278 pregap = p_env->tocent[i_track-p_env->gen.i_first_track].pregap;
279 start_lba = p_env->tocent[i_track-p_env->gen.i_first_track].start_lba;
280
281 /* avoid initializing pregap to CDIO_INVALID_LBA by letting calloc
282 do the work. also, nero files have the pregap set equal
283 to the start of the track when there is no pregap
284 */
285 if (!pregap || pregap == start_lba) {
286 pregap = CDIO_INVALID_LBA;
287 }
288
289 return pregap;
290 }
291
292 /*!
293 Return the International Standard Recording Code (ISRC) for track number
294 i_track in p_cdio. Track numbers start at 1.
295
296 Note: string is malloc'd so caller has to free() the returned
297 string when done with it.
298 */
299 char *
get_track_isrc_image(const void * p_user_data,track_t i_track)300 get_track_isrc_image(const void *p_user_data, track_t i_track)
301 {
302 const _img_private_t *p_env = p_user_data;
303 char *isrc = p_env->tocent[i_track-p_env->gen.i_first_track].isrc;
304
305 if (isrc && isrc[0]) {
306 return strdup(isrc);
307 } else {
308 return NULL;
309 }
310 }
311
312 /*!
313 Read a data sector
314
315 @param p_cdio object to read from
316
317 @param p_buf place to read data into. The caller should make sure
318 this location can store at least ISO_BLOCKSIZE, M2RAW_SECTOR_SIZE,
319 or M2F2_SECTOR_SIZE depending on the kind of sector getting read. If
320 you don't know whether you have a Mode 1/2, Form 1/ Form 2/Formless
321 sector best to reserve space for the maximum, M2RAW_SECTOR_SIZE.
322
323 @param i_lsn sector to read
324
325 @param i_blocksize size of block. Should be either ISO_BLOCKSIZE
326 M2RAW_SECTOR_SIZE, or M2F2_SECTOR_SIZE. See comment above under
327 p_buf.
328 */
329 driver_return_code_t
read_data_sectors_image(void * p_user_data,void * p_buf,lsn_t i_lsn,uint16_t i_blocksize,uint32_t i_blocks)330 read_data_sectors_image ( void *p_user_data, void *p_buf,
331 lsn_t i_lsn, uint16_t i_blocksize,
332 uint32_t i_blocks )
333 {
334 const _img_private_t *p_env = p_user_data;
335
336 if (!p_env || !p_env->gen.cdio) return DRIVER_OP_UNINIT;
337
338 {
339 CdIo_t *p_cdio = p_env->gen.cdio;
340 track_t i_track = cdio_get_track(p_cdio, i_lsn);
341 track_format_t e_track_format = cdio_get_track_format(p_cdio, i_track);
342
343 switch(e_track_format) {
344 case TRACK_FORMAT_PSX:
345 case TRACK_FORMAT_AUDIO:
346 case TRACK_FORMAT_ERROR:
347 return DRIVER_OP_ERROR;
348 case TRACK_FORMAT_DATA:
349 return cdio_read_mode1_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
350 case TRACK_FORMAT_CDI:
351 case TRACK_FORMAT_XA:
352 return cdio_read_mode2_sectors (p_cdio, p_buf, i_lsn, false, i_blocks);
353 }
354 }
355 return DRIVER_OP_ERROR;
356 }
357
358
359 /*!
360 Set the arg "key" with "value" in the source device.
361 Currently "source" to set the source device in I/O operations
362 is the only valid key.
363
364 */
365 driver_return_code_t
_set_arg_image(void * p_user_data,const char key[],const char value[])366 _set_arg_image (void *p_user_data, const char key[], const char value[])
367 {
368 _img_private_t *p_env = p_user_data;
369
370 if (!strcmp (key, "source"))
371 {
372 CDIO_FREE_IF_NOT_NULL(p_env->gen.source_name);
373 if (!value) return DRIVER_OP_ERROR;
374 p_env->gen.source_name = strdup (value);
375 }
376 else if (!strcmp (key, "cue"))
377 {
378 CDIO_FREE_IF_NOT_NULL(p_env->psz_cue_name);
379 if (!value) return DRIVER_OP_ERROR;
380 p_env->psz_cue_name = strdup (value);
381 }
382 else if (!strcmp (key, "access-mode"))
383 {
384 CDIO_FREE_IF_NOT_NULL(p_env->psz_access_mode);
385 if (!value) return DRIVER_OP_ERROR;
386 p_env->psz_access_mode = strdup (value);
387 }
388 else
389 return DRIVER_OP_ERROR;
390
391 return DRIVER_OP_SUCCESS;
392 }
393