Compare commits

..

2 commits

Author SHA1 Message Date
MrDulfin
16bd8dc62a
Delete Cargo.lock 2025-03-02 14:19:39 -05:00
MrDulfin
937715fb9c Created trait for CDRom 2025-03-02 14:17:27 -05:00
8 changed files with 135 additions and 196 deletions

3
.gitignore vendored
View file

@ -1 +1,4 @@
/target
Cargo.lock
.cargo

137
Cargo.lock generated
View file

@ -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"

View file

@ -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.

View file

@ -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;

View file

@ -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>;
}

View file

@ -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 {

View file

@ -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]

View file

@ -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 {
}