-
Notifications
You must be signed in to change notification settings - Fork 17
Add pregap detection for physical CDs. #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Related issue and pull request I opened with libcdio so that the macOS implementation doesn't have to use libcdio private structs: |
|
I was struggling with why everything seemed fine except for the track 1 pregap lengths. Apparently it's standard practice to count the 2 second lead-in towards the track 1 pregap length even though the lead-in doesn't usually get included when the track 1 pregap is dumped as an HTOA. For example, XLD hard-codes in 2 bonus seconds for track 1 pregap here: I suspect EAC is doing the same but I don't have any way of confirming that. I've similarly adjusted the log writer to give track 1 a fixed 2 seconds extra pre-gap duration. I've been told that https://github.com/superg/redumper has a more rigorous solution that can read into the lead-in and search for non-zero audio data or account for rare cases of extended lead-in if we ever want to go that route. |
| #ifdef __APPLE__ | ||
| #include <IOKit/storage/IOCDTypes.h> | ||
| #include <IOKit/storage/IOCDMediaBSDClient.h> | ||
| #endif | ||
|
|
||
|
|
||
| // TODO The implementation for macOS requires access to private internal cdio | ||
| // data, namely p_cdio->env.fd. Right now we just copy-paste some struct | ||
| // definitions to work around this. Is there a less brittle way to do do this? :-/ | ||
|
|
||
| #ifdef __APPLE__ | ||
|
|
||
| // lib/driver/mmc/mmc_private.h | ||
| typedef driver_return_code_t (*mmc_run_cmd_fn_t) | ||
| ( void *p_user_data, | ||
| unsigned int i_timeout_ms, | ||
| unsigned int i_cdb, | ||
| const mmc_cdb_t *p_cdb, | ||
| cdio_mmc_direction_t e_direction, | ||
| unsigned int i_buf, void *p_buf); | ||
|
|
||
| // lib/driver/cdio_private.h | ||
| typedef struct { | ||
| driver_return_code_t (*audio_get_volume) | ||
| (void *p_env, /*out*/ cdio_audio_volume_t *p_volume); | ||
| driver_return_code_t (*audio_pause) (void *p_env); | ||
| driver_return_code_t (*audio_play_msf) ( void *p_env, | ||
| msf_t *p_start_msf, | ||
| msf_t *p_end_msf ); | ||
| driver_return_code_t (*audio_play_track_index) | ||
| ( void *p_env, cdio_track_index_t *p_track_index ); | ||
| driver_return_code_t (*audio_read_subchannel) | ||
| ( void *p_env, cdio_subchannel_t *subchannel ); | ||
| driver_return_code_t (*audio_resume) ( void *p_env ); | ||
| driver_return_code_t (*audio_set_volume) | ||
| ( void *p_env, cdio_audio_volume_t *p_volume ); | ||
| driver_return_code_t (*audio_stop) ( void *p_env ); | ||
| driver_return_code_t (*eject_media) ( void *p_env ); | ||
| void (*free) (void *p_env); | ||
| const char * (*get_arg) (void *p_env, const char key[]); | ||
| int (*get_blocksize) ( void *p_env ); | ||
| cdtext_t * (*get_cdtext) ( void *p_env ); | ||
| uint8_t * (*get_cdtext_raw) ( void *p_env ); | ||
| char ** (*get_devices) ( void ); | ||
| char * (*get_default_device) ( void ); | ||
| lsn_t (*get_disc_last_lsn) ( void *p_env ); | ||
| discmode_t (*get_discmode) ( void *p_env ); | ||
| void (*get_drive_cap) (const void *p_env, | ||
| cdio_drive_read_cap_t *p_read_cap, | ||
| cdio_drive_write_cap_t *p_write_cap, | ||
| cdio_drive_misc_cap_t *p_misc_cap); | ||
| track_t (*get_first_track_num) ( void *p_env ); | ||
| bool (*get_hwinfo) | ||
| ( const CdIo_t *p_cdio, /* out*/ cdio_hwinfo_t *p_hw_info ); | ||
| driver_return_code_t (*get_last_session) | ||
| ( void *p_env, /*out*/ lsn_t *i_last_session ); | ||
| int (*get_media_changed) ( const void *p_env ); | ||
| char * (*get_mcn) ( const void *p_env ); | ||
| track_t (*get_num_tracks) ( void *p_env ); | ||
| int (*get_track_channels) ( const void *p_env, track_t i_track ); | ||
| track_flag_t (*get_track_copy_permit) ( void *p_env, track_t i_track ); | ||
| lba_t (*get_track_lba) ( void *p_env, track_t i_track ); | ||
| lba_t (*get_track_pregap_lba) ( const void *p_env, track_t i_track ); | ||
| char * (*get_track_isrc) ( const void *p_env, track_t i_track ); | ||
| track_format_t (*get_track_format) ( void *p_env, track_t i_track ); | ||
| bool (*get_track_green) ( void *p_env, track_t i_track ); | ||
| bool (*get_track_msf) ( void *p_env, track_t i_track, msf_t *p_msf ); | ||
| track_flag_t (*get_track_preemphasis) | ||
| ( const void *p_env, track_t i_track ); | ||
| off_t (*lseek) ( void *p_env, off_t offset, int whence ); | ||
| ssize_t (*read) ( void *p_env, void *p_buf, size_t i_size ); | ||
| int (*read_audio_sectors) ( void *p_env, void *p_buf, lsn_t i_lsn, | ||
| unsigned int i_blocks ); | ||
| driver_return_code_t (*read_data_sectors) | ||
| ( void *p_env, void *p_buf, lsn_t i_lsn, uint16_t i_blocksize, | ||
| uint32_t i_blocks ); | ||
| int (*read_mode2_sector) | ||
| ( void *p_env, void *p_buf, lsn_t i_lsn, bool b_mode2_form2 ); | ||
| int (*read_mode2_sectors) | ||
| ( void *p_env, void *p_buf, lsn_t i_lsn, bool b_mode2_form2, | ||
| unsigned int i_blocks ); | ||
| int (*read_mode1_sector) | ||
| ( void *p_env, void *p_buf, lsn_t i_lsn, bool mode1_form2 ); | ||
| int (*read_mode1_sectors) | ||
| ( void *p_env, void *p_buf, lsn_t i_lsn, bool mode1_form2, | ||
| unsigned int i_blocks ); | ||
| bool (*read_toc) ( void *p_env ) ; | ||
| mmc_run_cmd_fn_t run_mmc_cmd; | ||
| int (*set_arg) ( void *p_env, const char key[], const char value[] ); | ||
| driver_return_code_t (*set_blocksize) ( void *p_env, | ||
| uint16_t i_blocksize ); | ||
| int (*set_speed) ( void *p_env, int i_speed ); | ||
| } cdio_funcs_t; | ||
|
|
||
| // lib/driver/cdio_private.h | ||
| typedef struct { | ||
| uint16_t u_type; | ||
| uint16_t u_flags; | ||
| } cdio_header_t; | ||
|
|
||
| // lib/driver/cdio_private.h | ||
| struct _CdIo { | ||
| cdio_header_t header; | ||
| driver_id_t driver_id; | ||
| cdio_funcs_t op; | ||
| void* env; | ||
| }; | ||
|
|
||
| // lib/driver/generic.h | ||
| typedef struct { | ||
| char *source_name; | ||
| bool init; | ||
| bool toc_init; | ||
| bool b_cdtext_error; | ||
| int ioctls_debugged; | ||
| void *data_source; | ||
| int fd; | ||
| track_t i_first_track; | ||
| track_t i_tracks; | ||
| uint8_t u_joliet_level; | ||
| iso9660_pvd_t pvd; | ||
| iso9660_svd_t svd; | ||
| CdIo_t *cdio; | ||
| cdtext_t *cdtext; | ||
| track_flags_t track_flags[CDIO_CD_MAX_TRACKS+1]; | ||
| unsigned char scsi_mmc_sense[263]; | ||
| int scsi_mmc_sense_valid; | ||
| char *scsi_tuple; | ||
| } generic_img_private_t; | ||
|
|
||
| #endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you move everything under the APPLE ifdef into pregap_internal_osx.c, and everything else into pregap_internal_mmc.c. Then add a pregap_internal.h which provides the signature for a generic get_lba_index(). pregap.c can just retain the cyanrip_get_track_pregap_lba() function.
There's so little code shared. Just make meson switch between which version to compile based on the platform.
9bba1a1 to
8ad62fe
Compare
|
Just a quick note that libcdio accepted my pull request that will allow us to avoid the hacky part of the macOS implementation. They say they want to do a new release by the end of the year. If it ends up that the new libcdio release with that fix comes out before we put out a new release then I'd say we could just ditch the hacky part of the macOS implementation. I don't think there's much need for us to support old versions of libcdio on macOS when we don't even currently have a cyanrip macOS package. |
98c9e2a to
f22c3d3
Compare
This one still needs a little more time in the oven so that I can add error checking with the Q subchannel CRC16s but I wanted to get the ball rolling on the pull request.
I wrapped the cdio internal structs needed on macOS in an ifdef like we discussed.
Also, libcdio says they'll accept a pull request for a function to get the underlying file descriptor from a CdIo_t which would eventually allow the macOS implementation to be hack-free (libcdio/libcdio#35). How do you want to handle that? Can we go ahead for now with the hacky macOS implementation? Or would you prefer to wait for me to submit a pull request with libcdio and get it merged?