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