diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index cd67de3..42ccd84 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2013.05.21.081819" +#define Cdrskin_timestamP "2013.05.23.154249" diff --git a/libburn/file.c b/libburn/file.c index 2baee15..75c32b2 100644 --- a/libburn/file.c +++ b/libburn/file.c @@ -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; +} + diff --git a/libburn/libburn.h b/libburn/libburn.h index 44173db..1270955 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -2273,7 +2273,7 @@ int burn_cdtext_from_session(struct burn_session *s, array of packs shall be removed. @param num_packs The number of 18 byte packs in text_packs. @param start_tno The start number of track counting, if known from - CD table-of-content or orther sources. + CD table-of-content or other sources. Submit 0 to enable the attempt to read it and the track_count from pack type 0x8f. @param track_count The number of tracks, if known from CD table-of-content @@ -3922,6 +3922,49 @@ int burn_read_audio(struct burn_drive *d, int sector_no, char data[], off_t data_size, off_t *data_count, int flag); +/* ts B30522 */ +/** Extract an interval of audio sectors from CD and store it as a WAVE + audio file on hard disk. + + @param drive The drive from which to read. + @param start_sector The logical block address of the first audio sector + which shall be read. + @param sector_count The number of audio sectors to be read. + Each sector consists of 2352 bytes. + @param target_path The address of the file where to store the extracted + audio data. Will be opened O_WRONLY | O_CREAT. + The file name should have suffix ".wav". + @param flag Bitfield for control purposes: + bit0= Report about progress by UPDATE messages + bit3= Enable DAP : "flaw obscuring mechanisms like + audio data mute and interpolate" + @since 1.3.2 +*/ +int burn_drive_extract_audio(struct burn_drive *drive, + int start_sector, int sector_count, + char *target_path, int flag); + + +/* ts B30522 */ +/** Extract all audio sectors of a track from CD and store them as a WAVE + audio file on hard disk. + + @param drive The drive from which to read. + @param track The track which shall be extracted. + @param target_path The address of the file where to store the extracted + audio data. Will be opened O_WRONLY | O_CREAT. + The file name should have suffix ".wav". + @param flag Bitfield for control purposes: + bit0= Report about progress by UPDATE messages + bit3= Enable DAP : "flaw obscuring mechanisms like + audio data mute and interpolate" + @since 1.3.2 +*/ +int burn_drive_extract_audio_track(struct burn_drive *drive, + struct burn_track *track, + char *target_path, int flag); + + /* ts A70904 */ /** Inquire whether the drive object is a real MMC drive or a pseudo-drive created by a stdio: address. @@ -4080,7 +4123,7 @@ int libdax_audioxtr_read(struct libdax_audioxtr *xtr, /** Try to obtain a file descriptor which will deliver extracted data to normal calls of read(2). This may fail because the format is - unsuitable for that, but ".wav" is ok. If this call succeeds the xtr + unsuitable for that, but WAVE (.wav) is ok. If this call succeeds the xtr object will have forgotten its file descriptor and libdax_audioxtr_read() will return a usage error. One may use *fd after libdax_audioxtr_destroy() and will have to close it via close(2) when done with it. diff --git a/libburn/libburn.ver b/libburn/libburn.ver index ff5cc85..e7d2370 100644 --- a/libburn/libburn.ver +++ b/libburn/libburn.ver @@ -44,6 +44,8 @@ burn_drive_convert_fs_adr; burn_drive_convert_scsi_adr; burn_drive_d_get_adr; burn_drive_equals_adr; +burn_drive_extract_audio; +burn_drive_extract_audio_track; burn_drive_free_speedlist; burn_drive_get_adr; burn_drive_get_all_profiles; diff --git a/libburn/libdax_msgs.c b/libburn/libdax_msgs.c index 7bfbeee..5b16d1f 100644 --- a/libburn/libdax_msgs.c +++ b/libburn/libdax_msgs.c @@ -327,6 +327,11 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name, } +/* + @param flag Bitfield for control purposes + bit0= If direct output to stderr: + CarriageReturn rather than LineFeed +*/ int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag) @@ -345,7 +350,8 @@ int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, if(ret>0) sprintf(sev_text,"%s : ",sev_name); - fprintf(stderr,"%s%s%s\n",m->print_id,sev_text,textpt); + fprintf(stderr, "%s%s%s%c", m->print_id, sev_text, textpt, + (flag & 1) ? '\r' : '\n'); if(os_errno!=0) { ret= libdax_msgs_lock(m,0); if(ret<=0) diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index ff50056..e7837e6 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -302,7 +302,9 @@ int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *o, int flag); @param priority The LIBDAX_MSGS_PRIO_* number of the event. @param msg_text Printable and human readable message text. @param os_errno Eventual error code from operating system (0 if none) - @param flag Bitfield for control purposes (unused yet, submit 0) + @param flag Bitfield for control purposes + bit0= If direct output to stderr: + CarriageReturn rather than LineFeed @return 1 on success, 0 on rejection, <0 for severe errors */ int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, @@ -600,6 +602,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 0x0002019e (NOTE,HIGH) = Drive does not support media certification 0x0002019f (FAILURE,HIGH) = CD-TEXT binary pack array faulty 0x000201a0 (WARNING,HIGH) = Maximum number of CD-TEXT blocks exceeded + 0x000201a1 (FAILURE,HIGH) = Cannot open disk file for writing + 0x000201a2 (FAILURE,HIGH) = Error while writing to disk file + 0x000201a3 (UPDATE,HIGH) = Progress message of burn_drive_extract_audio() + 0x000201a4 (FAILURE,HIGH) = Failure to read audio sectors libdax_audioxtr: diff --git a/libburn/util.c b/libburn/util.c index a54b20c..8584de9 100644 --- a/libburn/util.c +++ b/libburn/util.c @@ -328,3 +328,17 @@ char *burn_printify(char *msg) return msg; } + +/* ts B30521 */ +void burn_int_to_lsb(int val, char *target) +{ + unsigned char *buf; + + buf = (unsigned char *) target; + buf[0] = val & 0xff; + buf[1] = (val >> 8) & 0xff; + buf[2] = (val >> 16) & 0xff; + buf[3] = (val >> 24) & 0xff; +} + + diff --git a/libburn/util.h b/libburn/util.h index 6f5db67..c498d35 100644 --- a/libburn/util.h +++ b/libburn/util.h @@ -8,4 +8,7 @@ int burn_util_make_printable_word(char **text, int flag); char *burn_sfile_fgets(char *line, int maxl, FILE *fp); char *burn_printify(char *msg); +/* ts B30521 */ +void burn_int_to_lsb(int val, char *target); + #endif