mirror of
https://github.com/Dangoware/cd_reader.git
synced 2025-04-19 18:02:55 -05:00
Compare commits
2 commits
ee7c529eda
...
16bd8dc62a
Author | SHA1 | Date | |
---|---|---|---|
|
16bd8dc62a | ||
|
937715fb9c |
8 changed files with 135 additions and 196 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1 +1,4 @@
|
|||
/target
|
||||
|
||||
Cargo.lock
|
||||
.cargo
|
137
Cargo.lock
generated
137
Cargo.lock
generated
|
@ -1,137 +0,0 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
|
||||
[[package]]
|
||||
name = "cd_read"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"md5",
|
||||
"nix",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "cd_read"
|
||||
name = "sunny_milk"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
@ -10,6 +10,7 @@ nix = { version = "0.29.0", features = ["ioctl"] }
|
|||
num-derive = "0.4.2"
|
||||
num-traits = "0.2.19"
|
||||
thiserror = "2.0.11"
|
||||
windows = "0.60.0"
|
||||
|
||||
[profile.release]
|
||||
strip = true # Automatically strip symbols from the binary.
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
use num_traits::ToPrimitive;
|
||||
|
||||
pub const EDRIVE_CANT_DO_THIS: i32 = nix::errno::Errno::EOPNOTSUPP as i32;
|
||||
|
||||
/// CDROM ioctl byte, from <linux/cdrom.h>
|
||||
pub const IOC_BYTE: u8 = 0x53;
|
||||
|
||||
|
|
93
src/lib.rs
93
src/lib.rs
|
@ -0,0 +1,93 @@
|
|||
use constants::AddressType;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{constants::{DiscType, Status}, structures::{Addr, SubChannel, TocEntry, TocHeader}};
|
||||
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
|
||||
pub mod constants;
|
||||
pub mod structures;
|
||||
pub mod platform;
|
||||
|
||||
#[cfg(target_os="linux")]
|
||||
pub type CDRom = platform::linux::CDRomLinux;
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
pub type CDRom = platform::windows::CDRomWindows;
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum CDRomError {
|
||||
#[cfg(target_os="linux")]
|
||||
#[error("internal system error")]
|
||||
Errno(#[from] nix::errno::Errno),
|
||||
|
||||
#[error("no disc in drive to read")]
|
||||
NoDisc,
|
||||
|
||||
#[error("the CD does not contain cd-audio")]
|
||||
NotAudioCD,
|
||||
|
||||
#[error("the drive's door is locked for some reason")]
|
||||
DoorLocked,
|
||||
|
||||
#[error("this drive does not support the function")]
|
||||
Unsupported,
|
||||
|
||||
#[error("the drive is in use by another user")]
|
||||
Busy,
|
||||
|
||||
#[error("the address specified was invalid")]
|
||||
InvalidAddress,
|
||||
|
||||
#[error("the buffer size was too small; needed at least {0} bytes, got {1} bytes")]
|
||||
InvalidBufferSize(usize, usize),
|
||||
}
|
||||
|
||||
|
||||
pub trait CDRomTrait {
|
||||
/// Get the currently reported status of the drive.
|
||||
fn status(&mut self) -> Option<Status>;
|
||||
|
||||
/// Get the type of disc currently in the drive
|
||||
fn disc_type(&mut self) -> Option<DiscType>;
|
||||
|
||||
/// Get the Media Catalog Number of the current disc.
|
||||
///
|
||||
/// Many discs do not contain this information.
|
||||
fn mcn(&mut self) -> Option<String>;
|
||||
|
||||
fn toc_header(&mut self) -> Result<TocHeader, CDRomError>;
|
||||
|
||||
fn toc_entry(&mut self, index: u8, address_type: AddressType) -> TocEntry;
|
||||
|
||||
fn set_lock(&mut self, locked: bool) -> Result<(), CDRomError>;
|
||||
|
||||
fn eject(&mut self) -> Result<(), CDRomError>;
|
||||
|
||||
fn close(&mut self) -> Result<(), CDRomError>;
|
||||
|
||||
fn subchannel(&mut self) -> Result<SubChannel, CDRomError>;
|
||||
|
||||
/// Read audio from the CD.
|
||||
///
|
||||
/// This method is a convenience method around [`CDRom::read_audio_into`].
|
||||
fn read_audio(&mut self, address: Addr, frames: usize) -> Result<Vec<i16>, CDRomError>;
|
||||
|
||||
/// Read audio from the CD into a preallocated buffer.
|
||||
///
|
||||
/// The buffer must be large enough to hold the audio for all the frames you want to read.
|
||||
/// Since the values are [`i16`]s, the equation for the buffer size is `(n_frames * 2352) / 2`
|
||||
fn read_audio_into(
|
||||
&mut self,
|
||||
address: Addr,
|
||||
frames: usize,
|
||||
buf: &mut [i16]
|
||||
) -> Result<(), CDRomError>;
|
||||
|
||||
fn read_raw_into(
|
||||
&mut self,
|
||||
address: Addr,
|
||||
buf: &mut [u8]
|
||||
) -> Result<(), CDRomError>;
|
||||
}
|
17
src/main.rs
17
src/main.rs
|
@ -1,20 +1,13 @@
|
|||
mod constants;
|
||||
mod structures;
|
||||
mod platform;
|
||||
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use constants::{AddressType, DiscType, Status};
|
||||
use structures::{Addr, Msf};
|
||||
|
||||
|
||||
#[macro_use]
|
||||
extern crate num_derive;
|
||||
use sunny_milk::constants::{AddressType, DiscType, Status, CD_FRAMESIZE_RAW};
|
||||
use sunny_milk::structures::{Addr, Msf};
|
||||
use sunny_milk::{CDRom, CDRomTrait};
|
||||
|
||||
fn main() {
|
||||
let mut cd_rom = CDRom::new().unwrap();
|
||||
cd_rom.set_lock(true).unwrap();
|
||||
// cd_rom.set_lock(true).unwrap();
|
||||
|
||||
println!("Getting drive status...");
|
||||
let mut status = cd_rom.status().unwrap();
|
||||
|
@ -80,7 +73,7 @@ fn rip_cd() {
|
|||
println!("Disc status: {:?}", cd_rom.disc_type().unwrap());
|
||||
|
||||
let mut raw_output = std::fs::File::create("raw_cd").unwrap();
|
||||
let mut buffer = vec![32u8; constants::CD_FRAMESIZE_RAW as usize];
|
||||
let mut buffer = vec![32u8; CD_FRAMESIZE_RAW as usize];
|
||||
|
||||
let mut frame = 0i32;
|
||||
loop {
|
||||
|
|
|
@ -13,40 +13,14 @@ use num_traits::FromPrimitive as _;
|
|||
|
||||
use crate::constants::{op_to_ioctl, AddressType, DiscType, Operation, Status, CD_FRAMESIZE_RAW};
|
||||
use crate::structures::{Addr, AddrUnion, Msf, MsfLong, ReadAudio, SubChannel, TocEntry, TocHeader, _SubChannel, _TocEntry};
|
||||
use thiserror::Error;
|
||||
use crate::{CDRomError, CDRomTrait};
|
||||
|
||||
pub const EDRIVE_CANT_DO_THIS: i32 = nix::errno::Errno::EOPNOTSUPP as i32;
|
||||
|
||||
pub struct CDRom {
|
||||
pub struct CDRomLinux {
|
||||
drive_fd: RawFd,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone)]
|
||||
pub enum CDRomError {
|
||||
#[error("internal system error")]
|
||||
Errno(#[from] nix::errno::Errno),
|
||||
|
||||
#[error("no disc in drive to read")]
|
||||
NoDisc,
|
||||
|
||||
#[error("the CD does not contain cd-audio")]
|
||||
NotAudioCD,
|
||||
|
||||
#[error("the drive's door is locked for some reason")]
|
||||
DoorLocked,
|
||||
|
||||
#[error("this drive does not support the function")]
|
||||
Unsupported,
|
||||
|
||||
#[error("the drive is in use by another user")]
|
||||
Busy,
|
||||
|
||||
#[error("the address specified was invalid")]
|
||||
InvalidAddress,
|
||||
|
||||
#[error("the buffer size was too small; needed at least {0} bytes, got {1} bytes")]
|
||||
InvalidBufferSize(usize, usize),
|
||||
}
|
||||
|
||||
ioctl_none_bad!(cdrom_stop, op_to_ioctl(Operation::Stop));
|
||||
ioctl_none_bad!(cdrom_start, op_to_ioctl(Operation::Start));
|
||||
ioctl_none_bad!(cdrom_eject, op_to_ioctl(Operation::Eject));
|
||||
|
@ -62,7 +36,7 @@ ioctl_read_bad!(cdrom_read_toc_entry, op_to_ioctl(Operation::ReadTocEntry), _Toc
|
|||
ioctl_readwrite_bad!(cdrom_subchannel, op_to_ioctl(Operation::SubChannel), _SubChannel);
|
||||
ioctl_read_bad!(cdrom_seek, op_to_ioctl(Operation::Seek), MsfLong);
|
||||
|
||||
impl CDRom {
|
||||
impl CDRomLinux {
|
||||
/// Creates a new interface to a system CD-ROM drive.
|
||||
pub fn new() -> Option<Self> {
|
||||
let drive_file = OpenOptions::new()
|
||||
|
@ -75,9 +49,10 @@ impl CDRom {
|
|||
drive_fd: drive_file.into_raw_fd(),
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
impl CDRomTrait for CDRomLinux {
|
||||
/// Get the currently reported status of the drive.
|
||||
pub fn status(&mut self) -> Option<Status> {
|
||||
fn status(&mut self) -> Option<Status> {
|
||||
let status = unsafe {
|
||||
cdrom_status(self.drive_fd).unwrap()
|
||||
};
|
||||
|
@ -86,7 +61,7 @@ impl CDRom {
|
|||
}
|
||||
|
||||
/// Get the type of disc currently in the drive
|
||||
pub fn disc_type(&mut self) -> Option<DiscType> {
|
||||
fn disc_type(&mut self) -> Option<DiscType> {
|
||||
let status = unsafe {
|
||||
cdrom_disc_status(self.drive_fd).ok()?
|
||||
};
|
||||
|
@ -97,7 +72,7 @@ impl CDRom {
|
|||
/// Get the Media Catalog Number of the current disc.
|
||||
///
|
||||
/// Many discs do not contain this information.
|
||||
pub fn mcn(&mut self) -> Option<String> {
|
||||
fn mcn(&mut self) -> Option<String> {
|
||||
let mut buffer = [0u8; 14];
|
||||
|
||||
unsafe {
|
||||
|
@ -108,7 +83,7 @@ impl CDRom {
|
|||
Some(string)
|
||||
}
|
||||
|
||||
pub fn toc_header(&mut self) -> Result<TocHeader, CDRomError> {
|
||||
fn toc_header(&mut self) -> Result<TocHeader, CDRomError> {
|
||||
let mut header = TocHeader::default();
|
||||
|
||||
if unsafe {
|
||||
|
@ -120,7 +95,7 @@ impl CDRom {
|
|||
Ok(header)
|
||||
}
|
||||
|
||||
pub fn toc_entry(&mut self, index: u8, address_type: AddressType) -> TocEntry {
|
||||
fn toc_entry(&mut self, index: u8, address_type: AddressType) -> TocEntry {
|
||||
let mut entry = _TocEntry::default();
|
||||
entry.track = index;
|
||||
entry.format = address_type as u8;
|
||||
|
@ -145,7 +120,7 @@ impl CDRom {
|
|||
entry
|
||||
}
|
||||
|
||||
pub fn set_lock(&mut self, locked: bool) -> Result<(), CDRomError> {
|
||||
fn set_lock(&mut self, locked: bool) -> Result<(), CDRomError> {
|
||||
let result = match unsafe {
|
||||
cdrom_lock_door(self.drive_fd, locked as i32)
|
||||
} {
|
||||
|
@ -162,7 +137,7 @@ impl CDRom {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn eject(&mut self) -> Result<(), CDRomError> {
|
||||
fn eject(&mut self) -> Result<(), CDRomError> {
|
||||
let status = unsafe {
|
||||
cdrom_eject(self.drive_fd).unwrap()
|
||||
};
|
||||
|
@ -174,7 +149,7 @@ impl CDRom {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn close(&mut self) -> Result<(), CDRomError> {
|
||||
fn close(&mut self) -> Result<(), CDRomError> {
|
||||
let status = unsafe {
|
||||
cdrom_close_tray(self.drive_fd).unwrap()
|
||||
};
|
||||
|
@ -186,7 +161,7 @@ impl CDRom {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn subchannel(&mut self) -> Result<SubChannel, CDRomError> {
|
||||
fn subchannel(&mut self) -> Result<SubChannel, CDRomError> {
|
||||
let mut argument = _SubChannel::default();
|
||||
|
||||
unsafe {
|
||||
|
@ -218,8 +193,8 @@ impl CDRom {
|
|||
|
||||
/// Read audio from the CD.
|
||||
///
|
||||
/// This method is a convenience method around [`CDRom::read_audio_into`].
|
||||
pub fn read_audio(&mut self, address: Addr, frames: usize) -> Result<Vec<i16>, CDRomError> {
|
||||
/// This method is a convenience method around [`CDRomLinux::read_audio_into`].
|
||||
fn read_audio(&mut self, address: Addr, frames: usize) -> Result<Vec<i16>, CDRomError> {
|
||||
let mut buf = vec![0i16; (frames * CD_FRAMESIZE_RAW as usize) / 2];
|
||||
|
||||
self.read_audio_into(address, frames, &mut buf)?;
|
||||
|
@ -231,7 +206,7 @@ impl CDRom {
|
|||
///
|
||||
/// The buffer must be large enough to hold the audio for all the frames you want to read.
|
||||
/// Since the values are [`i16`]s, the equation for the buffer size is `(n_frames * 2352) / 2`
|
||||
pub fn read_audio_into(&mut self, address: Addr, frames: usize, buf: &mut [i16]) -> Result<(), CDRomError> {
|
||||
fn read_audio_into(&mut self, address: Addr, frames: usize, buf: &mut [i16]) -> Result<(), CDRomError> {
|
||||
let (addr, addr_format) = match address {
|
||||
Addr::Lba(lba) => (AddrUnion { lba }, AddressType::Lba),
|
||||
Addr::Msf(msf) => {
|
||||
|
@ -269,7 +244,7 @@ impl CDRom {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_raw_into(
|
||||
fn read_raw_into(
|
||||
&mut self,
|
||||
address: Addr,
|
||||
buf: &mut [u8]
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
use crate::{CDRomError, CDRomTrait};
|
||||
|
||||
pub struct CDRomWindows {}
|
||||
|
||||
impl CDRomWindows {
|
||||
pub fn new() -> Result<Self, CDRomError> {
|
||||
Ok(Self { })
|
||||
}
|
||||
}
|
||||
|
||||
impl CDRomTrait for CDRomWindows {
|
||||
|
||||
}
|
Loading…
Reference in a new issue