-
Notifications
You must be signed in to change notification settings - Fork 2
Add read speed option for macOS and Linux #60
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
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
35c4516
Add an option to requesting read speed into ReadOptions (working at m…
strict-flower 32b1457
Fix typo and change the type of multiplier to u8
strict-flower b6367f4
Fix rustdoc
strict-flower 29b3e74
Add a speed change request feature for Linux
strict-flower 255147b
Improve an error handling flow of request_cd_read_speed
strict-flower 7f3f5ce
Fix rustdoc
strict-flower aa38e58
Merge branch 'main' into dev-speed-option
strict-flower df6b9b2
Add an example for ReadSpeed
strict-flower 08d48c8
Update rustdoc
strict-flower 003bc85
Fix for review
strict-flower 68b824b
Add a stub for a Windows backend
strict-flower 64afa23
Apply cargo fmt
strict-flower File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| /// Read the first audio track at 10x speed, and read the second audio track at `Optimal` | ||
| /// speed. | ||
| mod common; | ||
|
|
||
| use cd_da_reader::{CdReader, ReadOptions, ReadSpeed, Track}; | ||
|
|
||
| fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
| let output_dir = common::fresh_output_dir("read_speed")?; | ||
| let reader = CdReader::open_default()?; | ||
| let toc = reader.read_toc()?; | ||
|
|
||
| let audio_tracks: Vec<&Track> = toc.tracks.iter().filter(|t| t.is_audio).collect(); | ||
|
|
||
| if audio_tracks.len() < 2 { | ||
| panic!("This example requires at least two audio tracks"); | ||
| } | ||
|
|
||
| let first_track = audio_tracks[0]; | ||
| let second_track = audio_tracks[1]; | ||
|
|
||
| // Read the first track with 10x speed | ||
| { | ||
| let options_10x = ReadOptions::default().with_read_speed(ReadSpeed::CustomMultiplier(10)); | ||
|
|
||
| println!("Reading track {} with 10x speed...", first_track.number); | ||
| let data = reader.read_track_with_options(&toc, first_track.number, &options_10x)?; | ||
|
|
||
| let wav = CdReader::create_wav(data); | ||
| let output_path = output_dir.join(format!("track{:02}.wav", first_track.number)); | ||
| std::fs::write(&output_path, wav)?; | ||
| println!("Saved {}", output_path.display()); | ||
| } | ||
|
|
||
| // Read the second track with "optimal" speed | ||
| { | ||
| let options_optimal = ReadOptions::default().with_read_speed(ReadSpeed::Optimal); | ||
| println!( | ||
| "Reading track {} with optimal speed...", | ||
| second_track.number | ||
| ); | ||
| let data = reader.read_track_with_options(&toc, second_track.number, &options_optimal)?; | ||
|
|
||
| let wav = CdReader::create_wav(data); | ||
| let output_path = output_dir.join(format!("track{:02}.wav", second_track.number)); | ||
| std::fs::write(&output_path, wav)?; | ||
| println!("Saved {}", output_path.display()); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /// Representation of read speed requested by the `SET CD SPEED` (0xBB) command. | ||
| /// | ||
| /// # Note | ||
| /// | ||
| /// According to the MMC-3 specification, the requested speed doesn't necessarily | ||
| /// match the actual read speed. The drive may select the specified read speed | ||
| /// or any higher rate. | ||
| /// | ||
| /// Therefore, this enum represents a requested speed, not a guaranteed actual | ||
| /// read speed. The actual behaviour is drive-dependent. | ||
| #[derive(Debug, Clone, Copy)] | ||
| pub enum ReadSpeed { | ||
| /// Don't change the speed | ||
| /// | ||
| /// The speed depends on the OS, previous configuration, and other factors. | ||
| Unchanged, | ||
|
|
||
| /// Request the drive-selected/optimal speed. | ||
| /// | ||
| /// According to the MMC-3 specification, the drive can select its optimal | ||
| /// speed when the `SET CD SPEED` command is executed with the read | ||
| /// speed (KB/s) set to 0xFFFF. | ||
| /// | ||
| /// On macOS, this variant requests `SET CD SPEED` with 0xFFFF. | ||
| /// | ||
| /// On Linux, the read speed is selected by the `CDROM_SELECT_SPEED` | ||
| /// ioctl with speed = 0. It requests automatic speed selection. | ||
| Optimal, | ||
|
|
||
| /// Use a custom speed with the specified multiplier. | ||
| /// | ||
| /// Although the CD-DA read speed should be requested in KB/s according to | ||
| /// the specification, this variant uses a multiplier for simplicity. | ||
| /// | ||
| /// For example, `ReadSpeed::CustomMultiplier(1)` represents the nominal | ||
| /// CD-DA 1x read rate (176.4 KB/s). The exact conversion is | ||
| /// platform-dependent. | ||
| /// | ||
| /// Another example: `ReadSpeed::CustomMultiplier(10)` represents 10x speed. | ||
| /// | ||
| /// `ReadSpeed::CustomMultiplier(0)` is equivalent to `ReadSpeed::Optimal`. | ||
| /// The value 0 is used as a sentinel. | ||
| CustomMultiplier(u8), | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| use super::device::Drive; | ||
| use crate::CdReaderError; | ||
| use crate::data_reader::ReadSpeed; | ||
| use std::os::fd::RawFd; | ||
|
|
||
| // From linux/include/uapi/linux/cdrom.h | ||
| const CDROM_SELECT_SPEED: libc::c_ulong = 0x5322; | ||
|
|
||
| pub(super) fn request_read_speed( | ||
| drive: &Drive, | ||
| target_read_speed: ReadSpeed, | ||
| ) -> Result<(), CdReaderError> { | ||
| let multiplier = match target_read_speed { | ||
| ReadSpeed::Unchanged => return Ok(()), | ||
| ReadSpeed::Optimal => 0, | ||
| ReadSpeed::CustomMultiplier(x) => x, | ||
| }; | ||
|
|
||
| execute_request_read_speed(drive.fd(), multiplier) | ||
| } | ||
|
|
||
| fn execute_request_read_speed(fd: RawFd, multiplier: u8) -> Result<(), CdReaderError> { | ||
| let result = unsafe { libc::ioctl(fd, CDROM_SELECT_SPEED, multiplier as libc::c_ulong) }; | ||
| if result < 0 { | ||
| Err(CdReaderError::Io(std::io::Error::last_os_error())) | ||
| } else { | ||
| Ok(()) | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #include "shim_common.h" | ||
| #include <IOKit/storage/IOCDMediaBSDClient.h> | ||
|
|
||
| Boolean request_cd_read_speed(int fd, uint16_t target_speed_kbs) { | ||
| int ret = ioctl(fd, DKIOCCDSETSPEED, &target_speed_kbs); | ||
| if (ret < 0) { | ||
| fprintf(stderr, "[SPEED] DKIOCCDSETSPEED failed (errno=%d)\n", errno); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| use super::device::Drive; | ||
| use crate::CdReaderError; | ||
| use crate::data_reader::ReadSpeed; | ||
|
|
||
| pub(super) fn request_read_speed( | ||
| drive: &Drive, | ||
| target_read_speed: ReadSpeed, | ||
| ) -> Result<(), CdReaderError> { | ||
| let multiplier = match target_read_speed { | ||
| ReadSpeed::Unchanged => return Ok(()), | ||
| ReadSpeed::Optimal => 0, | ||
| ReadSpeed::CustomMultiplier(x) => x as u32, | ||
| }; | ||
| let target_speed_kbs = if multiplier == 0 { | ||
| 0xffff | ||
| } else { | ||
| multiplier * 176400 / 1000 | ||
| }; | ||
| let response = | ||
| unsafe { super::ffi::request_cd_read_speed(drive.fd(), target_speed_kbs as u16) }; | ||
|
|
||
| if !response { | ||
| return Err(CdReaderError::Io(std::io::Error::last_os_error())); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| use super::device::Drive; | ||
| use crate::CdReaderError; | ||
| use crate::data_reader::ReadSpeed; | ||
|
|
||
| pub(super) fn request_read_speed( | ||
| drive: &Drive, | ||
| target_read_speed: ReadSpeed, | ||
| ) -> Result<(), CdReaderError> { | ||
| // stub | ||
| /* | ||
| let multiplier = match target_read_speed { | ||
| ReadSpeed::Unchanged => return Ok(()), | ||
| ReadSpeed::Optimal => 0, | ||
| ReadSpeed::CustomMultiplier(x) => x, | ||
| }; | ||
| */ | ||
| Ok(()) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.