|
|
|
@ -27,6 +27,7 @@
|
|
|
|
|
#include "file.h" |
|
|
|
|
#include "async.h" |
|
|
|
|
#include "init.h" |
|
|
|
|
#include "util.h" |
|
|
|
|
|
|
|
|
|
#include "libdax_msgs.h" |
|
|
|
|
extern struct libdax_msgs *libdax_messenger; |
|
|
|
@ -919,3 +920,161 @@ struct burn_source *burn_offst_source_new(
|
|
|
|
|
return src; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -------------------- WAVE file extractor ------------------- */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ts B30522 */ |
|
|
|
|
/* API
|
|
|
|
|
@param flag Bitfield for control purposes: |
|
|
|
|
bit0= Report about progress by UPDATE message |
|
|
|
|
bit3= Enable DAP : "flaw obscuring mechanisms like |
|
|
|
|
audio data mute and interpolate" |
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
|
int burn_drive_extract_audio(struct burn_drive *drive, |
|
|
|
|
int start_sector, int sector_count, |
|
|
|
|
char *target_path, int flag) |
|
|
|
|
{ |
|
|
|
|
int fd = -1, ret, todo, sector_no, val, min, sec, fr; |
|
|
|
|
int sectors_done= 0, last_reported = 0; |
|
|
|
|
off_t data_size, data_count = 0; |
|
|
|
|
time_t last_pacified = 0, now; |
|
|
|
|
char *msg = NULL, *buf = NULL; |
|
|
|
|
|
|
|
|
|
BURN_ALLOC_MEM(msg, char, 4096); |
|
|
|
|
BURN_ALLOC_MEM(buf, char, 24 * 2352); |
|
|
|
|
|
|
|
|
|
fd = open(target_path, O_WRONLY | O_CREAT, |
|
|
|
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); |
|
|
|
|
if (fd == -1) { |
|
|
|
|
sprintf(msg, "Cannot open disk file for writing: %.4000s", |
|
|
|
|
target_path); |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x000201a1, |
|
|
|
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
msg, errno, 0); |
|
|
|
|
ret = 0; goto ex; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* WAV header */ |
|
|
|
|
strcpy(buf, "RIFF"); |
|
|
|
|
val = 4 + 8 + 16 + 8 + sector_count * 2352; /* ChunkSize */ |
|
|
|
|
burn_int_to_lsb(val, buf + 4); |
|
|
|
|
strcpy(buf + 8, "WAVE"); |
|
|
|
|
strcpy(buf + 12, "fmt "); |
|
|
|
|
burn_int_to_lsb(16, buf + 16); /* Subchunk1Size */ |
|
|
|
|
buf[20] = 1; /* AudioFormat */ |
|
|
|
|
buf[21] = 0; |
|
|
|
|
buf[22] = 2; /* NumChannels */ |
|
|
|
|
buf[23] = 0; |
|
|
|
|
burn_int_to_lsb(44100, buf + 24); /* SampleRate */ |
|
|
|
|
burn_int_to_lsb(176400, buf + 28); /* ByteRate */ |
|
|
|
|
buf[32] = 4; /* BlockAlign */ |
|
|
|
|
buf[33] = 0; |
|
|
|
|
buf[34] = 16; /* BitsPerSample */ |
|
|
|
|
buf[35] = 0; |
|
|
|
|
strcpy(buf + 36, "data"); |
|
|
|
|
burn_int_to_lsb(sector_count * 2352, buf + 40); /* Subchunk2Size */ |
|
|
|
|
|
|
|
|
|
ret = write(fd, buf, 44); |
|
|
|
|
if (ret == -1) |
|
|
|
|
goto write_error; |
|
|
|
|
|
|
|
|
|
/* Audio data */ |
|
|
|
|
todo = sector_count; |
|
|
|
|
sector_no = start_sector; |
|
|
|
|
while (todo > 0) { |
|
|
|
|
if (todo > 24) |
|
|
|
|
data_size = 24 * 2352; |
|
|
|
|
else |
|
|
|
|
data_size = todo * 2352; |
|
|
|
|
ret = burn_read_audio(drive, sector_no, buf, data_size, |
|
|
|
|
&data_count, flag & 8); |
|
|
|
|
if (ret <= 0) { |
|
|
|
|
sprintf(msg, "Failure to read audio sectors"); |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x000201a4, |
|
|
|
|
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
msg, 0, 0); |
|
|
|
|
goto ex; |
|
|
|
|
} |
|
|
|
|
ret = write(fd, buf, data_count); |
|
|
|
|
if (ret == -1) { |
|
|
|
|
write_error:; |
|
|
|
|
sprintf(msg, |
|
|
|
|
"Error while writing to disk file: %.4000s", |
|
|
|
|
target_path); |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x000201a2, |
|
|
|
|
LIBDAX_MSGS_SEV_FAILURE, |
|
|
|
|
LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
msg, errno, 0); |
|
|
|
|
ret = 0; goto ex; |
|
|
|
|
} |
|
|
|
|
todo -= data_count / 2352; |
|
|
|
|
sectors_done += data_count / 2352; |
|
|
|
|
sector_no += data_count / 2352; |
|
|
|
|
if ((flag & 1) && (now = time(NULL)) - last_pacified >= 1) { |
|
|
|
|
last_pacified = now; |
|
|
|
|
burn_lba_to_msf(sectors_done, &min, &sec, &fr); |
|
|
|
|
sprintf(msg, |
|
|
|
|
"Minutes:seconds of audio data read: %2d:%2.2d (%6.2f MB)", |
|
|
|
|
min, sec, |
|
|
|
|
((double) sectors_done) * 2352.0 / 1048576.0); |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x000201a3, |
|
|
|
|
LIBDAX_MSGS_SEV_UPDATE, |
|
|
|
|
LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
msg, 0, 1); |
|
|
|
|
last_reported = sectors_done; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if ((flag & 1)) { |
|
|
|
|
burn_lba_to_msf(sectors_done, &min, &sec, &fr); |
|
|
|
|
sprintf(msg, |
|
|
|
|
"Minutes:seconds of audio data read: %2d:%2.2d (%6.2f MB)", |
|
|
|
|
min, sec, ((double) sectors_done) * 2352.0 / 1048576.0); |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x000201a3, |
|
|
|
|
LIBDAX_MSGS_SEV_UPDATE, |
|
|
|
|
LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
msg, 0, 0); |
|
|
|
|
last_reported = sectors_done; |
|
|
|
|
} |
|
|
|
|
ret = 1; |
|
|
|
|
ex:; |
|
|
|
|
BURN_FREE_MEM(buf); |
|
|
|
|
BURN_FREE_MEM(msg); |
|
|
|
|
if (fd != -1) |
|
|
|
|
close(fd); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ts B30522 */ |
|
|
|
|
/* API
|
|
|
|
|
@param flag Bitfield for control purposes: |
|
|
|
|
bit0= Report about progress by UPDATE message |
|
|
|
|
bit3= Enable DAP : "flaw obscuring mechanisms like |
|
|
|
|
audio data mute and interpolate" |
|
|
|
|
*/ |
|
|
|
|
int burn_drive_extract_audio_track(struct burn_drive *drive, |
|
|
|
|
struct burn_track *track, |
|
|
|
|
char *target_path, int flag) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
struct burn_toc_entry toc_entry; |
|
|
|
|
|
|
|
|
|
burn_track_get_entry(track, &toc_entry); |
|
|
|
|
if (!(toc_entry.extensions_valid & 1)) { |
|
|
|
|
/* Can only happen if burn_disc_cd_toc_extensions() is skipped
|
|
|
|
|
in mmc_read_toc_al(). |
|
|
|
|
*/ |
|
|
|
|
libdax_msgs_submit(libdax_messenger, -1, 0x00000004, |
|
|
|
|
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, |
|
|
|
|
"Internal libburn error: Outdated burn_toc_entry format encountered", |
|
|
|
|
errno, 0); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
ret = burn_drive_extract_audio(drive, toc_entry.start_lba, |
|
|
|
|
toc_entry.track_blocks, |
|
|
|
|
target_path, flag & (1 | 8)); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|