1 /*
2  * This file is part of cyanrip.
3  *
4  * cyanrip is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * cyanrip is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with cyanrip; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #pragma once
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <math.h>
26 #include "../config.h"
27 #include "version.h"
28 
29 #include <cdio/paranoia/paranoia.h>
30 #include <libavutil/mem.h>
31 #include <libavutil/dict.h>
32 #include <libavutil/avstring.h>
33 #include <libavutil/intreadwrite.h>
34 #include <libavcodec/avcodec.h>
35 
36 enum cyanrip_output_formats {
37     CYANRIP_FORMAT_FLAC = 0,
38     CYANRIP_FORMAT_TTA,
39     CYANRIP_FORMAT_OPUS,
40     CYANRIP_FORMAT_AAC,
41     CYANRIP_FORMAT_WAVPACK,
42     CYANRIP_FORMAT_ALAC,
43     CYANRIP_FORMAT_MP3,
44     CYANRIP_FORMAT_VORBIS,
45     CYANRIP_FORMAT_WAV,
46     CYANRIP_FORMAT_AAC_MP4,
47     CYANRIP_FORMAT_OPUS_MP4,
48     CYANRIP_FORMAT_PCM,
49 
50     CYANRIP_FORMATS_NB,
51 };
52 
53 enum cyanrip_pregap_action {
54     CYANRIP_PREGAP_DEFAULT = 0,
55     CYANRIP_PREGAP_DROP,
56     CYANRIP_PREGAP_MERGE,
57     CYANRIP_PREGAP_TRACK,
58 };
59 
60 enum CRIPAccuDBStatus {
61     CYANRIP_ACCUDB_DISABLED = 0,
62     CYANRIP_ACCUDB_NOT_FOUND,
63     CYANRIP_ACCUDB_ERROR,
64     CYANRIP_ACCUDB_MISMATCH,
65     CYANRIP_ACCUDB_FOUND,
66 };
67 
68 enum CRIPPathType {
69     CRIP_PATH_COVERART, /* arg must be a CRIPArt * */
70     CRIP_PATH_TRACK, /* arg must be a cyanrip_track * */
71     CRIP_PATH_LOG, /* arg must be NULL */
72 };
73 
74 enum CRIPSanitize {
75     CRIP_SANITIZE_SIMPLE, /* Replace unacceptable symbols with _ */
76     CRIP_SANITIZE_OS_SIMPLE, /* Same as above, but only replaces symbols not allowed on current OS */
77     CRIP_SANITIZE_UNICODE, /* Replace unacceptable symbols with visually identical unicode equivalents */
78     CRIP_SANITIZE_OS_UNICODE, /* Same as above, but only replaces symbols not allowed on current OS */
79 };
80 
81 typedef struct cyanrip_settings {
82     char *dev_path;
83     char *folder_name_scheme;
84     char *track_name_scheme;
85     char *log_name_scheme;
86     enum CRIPSanitize sanitize_method;
87     int speed;
88     int frame_max_retries;
89     int offset;
90     int over_under_read_frames;
91     int print_info_only;
92     int disable_mb;
93     float bitrate;
94     int decode_hdcd;
95     int disable_accurip;
96     int disable_coverart_db;
97     int overread_leadinout;
98     int eject_on_success_rip;
99     enum cyanrip_pregap_action pregap_action[99];
100     int rip_indices_count;
101     int rip_indices[99];
102     int paranoia_level;
103 
104     enum cyanrip_output_formats outputs[CYANRIP_FORMATS_NB];
105     int outputs_num;
106 } cyanrip_settings;
107 
108 typedef struct CRIPAccuDBEntry {
109     int confidence;
110     uint32_t checksum; /* We don't know which version it is */
111     uint32_t checksum_450;
112 } CRIPAccuDBEntry;
113 
114 typedef struct CRIPArt {
115     AVDictionary *meta;
116     char *source_url;
117     char *title; /* Temporary, used during parsing only, copied to meta, do not free */
118 
119     AVPacket *pkt;
120     AVCodecParameters *params;
121 
122     uint8_t *data;
123     size_t size;
124     char *extension;
125 } CRIPArt;
126 
127 typedef struct cyanrip_track {
128     int number; /* Human readable track number, may be 0 */
129     int cd_track_number; /* Actual track on the CD, may be 0 */
130     AVDictionary *meta; /* Disc's AVDictionary gets copied here */
131 
132     int track_is_data;
133     int preemphasis;
134 
135     size_t nb_samples; /* Track duration in samples */
136 
137     int frames_before_disc_start;
138     lsn_t frames; /* Actual number of frames to read, != samples */
139     int frames_after_disc_end;
140 
141     lsn_t pregap_lsn;
142     lsn_t start_lsn;
143     lsn_t start_lsn_sig;
144     lsn_t end_lsn;
145     lsn_t end_lsn_sig;
146 
147     ptrdiff_t partial_frame_byte_offs;
148 
149     CRIPArt art; /* One cover art, will not be saved */
150 
151     int computed_crcs;
152     uint32_t eac_crc;
153     uint32_t acurip_checksum_v1;
154     uint32_t acurip_checksum_v1_450;
155     uint32_t acurip_checksum_v2;
156     int acurip_track_is_first;
157     int acurip_track_is_last;
158 
159     enum CRIPAccuDBStatus ar_db_status;
160     CRIPAccuDBEntry *ar_db_entries;
161     int ar_db_nb_entries;
162     int ar_db_max_confidence;
163 } cyanrip_track;
164 
165 typedef struct cyanrip_ctx {
166     cdrom_drive_t     *drive;
167     cdrom_paranoia_t  *paranoia;
168     CdIo_t            *cdio;
169     FILE              *logfile[CYANRIP_FORMATS_NB];
170     cyanrip_settings   settings;
171 
172     cyanrip_track tracks[198];
173     int nb_tracks; /* Total number of output tracks */
174     int nb_cd_tracks; /* Total tracks the CD signals */
175     int disregard_cd_isrc; /* If one track doesn't have ISRC, universally the rest won't */
176 
177     char *mb_submission_url;
178 
179     /* Non-track bound cover art */
180     CRIPArt cover_arts[32];
181     int nb_cover_arts;
182 
183     /* Drive caps */
184     cdio_drive_read_cap_t  rcap;
185     cdio_drive_write_cap_t wcap;
186     cdio_drive_misc_cap_t  mcap;
187 
188     /* Metadata */
189     AVDictionary *meta;
190     enum CRIPAccuDBStatus ar_db_status;
191 
192     /* Destination folder */
193     const char *base_dst_folder;
194 
195     int success;
196     int total_error_count;
197     lsn_t start_lsn;
198     lsn_t end_lsn;
199     lsn_t duration_frames;
200 } cyanrip_ctx;
201 
202 typedef struct cyanrip_out_fmt {
203     const char *name;
204     const char *folder_suffix;
205     const char *ext;
206     const char *lavf_name;
207     int coverart_supported;
208     int compression_level;
209     int lossless;
210     enum AVCodecID codec;
211 } cyanrip_out_fmt;
212 
213 extern const cyanrip_out_fmt crip_fmt_info[];
214 
215 char *crip_get_path(cyanrip_ctx *ctx, enum CRIPPathType type, int create_dirs,
216                     const cyanrip_out_fmt *fmt, void *arg);
217 
dict_get(AVDictionary * dict,const char * key)218 static inline const char *dict_get(AVDictionary *dict, const char *key)
219 {
220     AVDictionaryEntry *e = av_dict_get(dict, key, NULL, 0);
221     return e ? e->value : NULL;
222 }
223 
cyanrip_frames_to_duration(uint32_t frames,char * str)224 static inline void cyanrip_frames_to_duration(uint32_t frames, char *str)
225 {
226     if (!str)
227         return;
228     const double tot = frames/75.0; /* 75 frames per second */
229     const int hr    = tot/3600.0;
230     const int min   = (tot/60.0) - (hr * 60.0);
231     const int sec   = tot - ((hr * 3600.0) + min * 60.0);
232     const int msec  = tot - sec;
233     snprintf(str, 13, "%02i:%02i:%02i.%03i", hr, min, sec, msec);
234 }
235 
cyanrip_samples_to_duration(uint32_t samples,char * str)236 static inline void cyanrip_samples_to_duration(uint32_t samples, char *str)
237 {
238     if (!str)
239         return;
240     const double tot = samples/44100.0; /* 44100 samples per second */
241     const int hr    = tot/3600.0;
242     const int min   = (tot/60.0) - (hr * 60.0);
243     const int sec   = tot - ((hr * 3600.0) + min * 60.0);
244     const int msec  = tot - sec;
245     snprintf(str, 13, "%02i:%02i:%02i.%03i", hr, min, sec, msec);
246 }
247 
cmp_numbers(const void * a,const void * b)248 static inline int cmp_numbers(const void *a, const void *b)
249 {
250     return *((int *)a) > *((int *)b);
251 }
252 
253 extern uint64_t paranoia_status[PARANOIA_CB_FINISHED + 1];
254 extern const int crip_max_paranoia_level;
255