1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25
26 #include <config.h>
27 #include <gmerlin/translation.h>
28
29 #include "cdaudio.h"
30 #define DO_NOT_WANT_PARANOIA_COMPATIBILITY
31 #include <cdio/paranoia/cdda.h>
32 #include <cdio/paranoia/paranoia.h>
33
34 /*
35 * Ripping support
36 * Several versions (cdparanoia, simple linux ripper) can go here
37 */
38
39 typedef struct
40 {
41 cdrom_drive_t *drive;
42 cdrom_paranoia_t *paranoia;
43
44 /* Configuration options (mostly correspond to commandline options) */
45
46 int speed;
47
48 int disable_paranoia; // -Z
49 int disable_extra_paranoia; // -Y
50 int max_retries; // (0: unlimited)
51
52 CdIo_t *cdio;
53 int current_sector;
54 } cdparanoia_priv_t;
55
56
bg_cdaudio_rip_create()57 void * bg_cdaudio_rip_create()
58 {
59 cdparanoia_priv_t * ret;
60 ret = calloc(1, sizeof(*ret));
61 return ret;
62 }
63
bg_cdaudio_rip_init(void * data,CdIo_t * cdio,int start_sector)64 int bg_cdaudio_rip_init(void * data,
65 CdIo_t *cdio, int start_sector)
66 {
67 char * msg = NULL;
68 int paranoia_mode;
69 cdparanoia_priv_t * priv;
70 priv = data;
71
72 priv->cdio = cdio;
73
74 /* cdparanoia */
75 if(!priv->disable_paranoia)
76 {
77 priv->drive = cdio_cddap_identify_cdio(cdio, 1, &msg);
78
79 if(!priv->drive)
80 return 0;
81
82 cdio_cddap_verbose_set(priv->drive,CDDA_MESSAGE_FORGETIT,CDDA_MESSAGE_FORGETIT);
83
84 if(priv->speed != -1)
85 cdio_cddap_speed_set(priv->drive, priv->speed);
86
87 cdio_cddap_open(priv->drive);
88
89 paranoia_mode=PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP;
90
91 if(priv->disable_paranoia)
92 paranoia_mode=PARANOIA_MODE_DISABLE;
93 if(priv->disable_extra_paranoia)
94 {
95 paranoia_mode|=PARANOIA_MODE_OVERLAP; /* cdda2wav style overlap
96 check only */
97 paranoia_mode&=~PARANOIA_MODE_VERIFY;
98 }
99
100 priv->paranoia = cdio_paranoia_init(priv->drive);
101 cdio_paranoia_seek(priv->paranoia, start_sector, SEEK_SET);
102 cdio_paranoia_modeset(priv->paranoia,paranoia_mode);
103 }
104 /* Simple audio reading */
105 else
106 {
107 priv->current_sector = start_sector;
108 }
109
110 return 1;
111 }
112
paranoia_callback(long inpos,paranoia_cb_mode_t function)113 static void paranoia_callback(long inpos, paranoia_cb_mode_t function)
114 {
115
116 }
117
bg_cdaudio_rip_rip(void * data,gavl_audio_frame_t * f)118 int bg_cdaudio_rip_rip(void * data, gavl_audio_frame_t * f)
119 {
120 cdparanoia_priv_t * priv = data;
121
122 if(!priv->disable_paranoia)
123 {
124 int16_t * samples;
125 samples = cdio_paranoia_read(priv->paranoia, paranoia_callback);
126 memcpy(f->samples.s_16, samples, 588 * 4);
127 }
128 else
129 {
130 driver_return_code_t err;
131 // fprintf(stderr, "read sector...");
132 err = cdio_read_audio_sector(priv->cdio, f->samples.s_16, priv->current_sector);
133 if(err != DRIVER_OP_SUCCESS)
134 {
135 // fprintf(stderr, "Failed\n");
136 return 0;
137 }
138 // else
139 // fprintf(stderr, "Ok\n");
140
141 priv->current_sector++;
142 }
143
144 return 1;
145 }
146
147 /* Sector is absolute */
148
bg_cdaudio_rip_seek(void * data,int sector)149 void bg_cdaudio_rip_seek(void * data, int sector)
150 {
151 cdparanoia_priv_t * priv = data;
152
153 if(!priv->disable_paranoia)
154 cdio_paranoia_seek(priv->paranoia, sector, SEEK_SET);
155 else
156 priv->current_sector = sector;
157 }
158
bg_cdaudio_rip_close(void * data)159 void bg_cdaudio_rip_close(void * data)
160 {
161 cdparanoia_priv_t * priv = data;
162
163 if(priv->paranoia)
164 {
165 cdio_paranoia_free(priv->paranoia);
166 priv->paranoia = NULL;
167 }
168 if(priv->drive)
169 {
170 cdio_cddap_close(priv->drive);
171 priv->drive = NULL;
172 }
173 }
174
175
bg_cdaudio_rip_destroy(void * data)176 void bg_cdaudio_rip_destroy(void * data)
177 {
178 cdparanoia_priv_t * priv;
179 priv = data;
180 free(priv);
181 }
182
183 static const bg_parameter_info_t parameters[] =
184 {
185 {
186 .name = "cdparanoia",
187 .long_name = TRS("Cdparanoia"),
188 .type = BG_PARAMETER_SECTION,
189 },
190 {
191 .name = "cdparanoia_speed",
192 .long_name = TRS("Speed"),
193 .type = BG_PARAMETER_STRINGLIST,
194 .val_default = { .val_str = "Auto" },
195 .multi_names = (char const *[]){ TRS("Auto"),
196 "4",
197 "8",
198 "16",
199 "32",
200 NULL },
201 },
202 {
203 .name = "cdparanoia_max_retries",
204 .long_name = TRS("Maximum retries"),
205 .type = BG_PARAMETER_INT,
206 .val_min = { .val_i = 0 },
207 .val_max = { .val_i = 200 },
208 .val_default = { .val_i = 20 },
209 .help_string = TRS("Maximum number of retries, 0 = infinite")
210 },
211 {
212 .name = "cdparanoia_disable_paranoia",
213 .long_name = TRS("Disable paranoia"),
214 .type = BG_PARAMETER_CHECKBUTTON,
215 .val_default = { .val_i = 0 },
216 .help_string = TRS("Disable all data verification and correction features.")
217 },
218 {
219 .name = "cdparanoia_disable_extra_paranoia",
220 .long_name = TRS("Disable extra paranoia"),
221 .type = BG_PARAMETER_CHECKBUTTON,
222 .val_default = { .val_i = 0 },
223 .help_string = TRS("Disables intra-read data verification; only overlap checking at\
224 read boundaries is performed. It can wedge if errors occur in \
225 the attempted overlap area. Not recommended.")
226 },
227 { /* End of parameters */ }
228 };
229
bg_cdaudio_rip_get_parameters()230 const bg_parameter_info_t * bg_cdaudio_rip_get_parameters()
231 {
232 return parameters;
233 }
234
235
236 int
bg_cdaudio_rip_set_parameter(void * data,const char * name,const bg_parameter_value_t * val)237 bg_cdaudio_rip_set_parameter(void * data, const char * name,
238 const bg_parameter_value_t * val)
239 {
240 cdparanoia_priv_t * priv;
241 priv = data;
242
243 if(!name)
244 return 0;
245
246 if(!strcmp(name, "cdparanoia_speed"))
247 {
248 if(!strcmp(val->val_str, "Auto"))
249 priv->speed = -1;
250 else
251 priv->speed = atoi(val->val_str);
252 return 1;
253 }
254 else if(!strcmp(name, "cdparanoia_max_retries"))
255 {
256 priv->max_retries = val->val_i;
257 return 1;
258 }
259 else if(!strcmp(name, "cdparanoia_disable_paranoia"))
260 {
261 priv->disable_paranoia = val->val_i;
262 return 1;
263 }
264 else if(!strcmp(name, "cdparanoia_disable_extra_paranoia"))
265 {
266 priv->disable_extra_paranoia = val->val_i;
267 return 1;
268 }
269 return 0;
270 }
271