From 937715fb9c62e758fb09e9d8cbd4062a431831ac Mon Sep 17 00:00:00 2001 From: MrDulfin Date: Sun, 2 Mar 2025 14:14:12 -0500 Subject: [PATCH] Created trait for CDRom --- .gitignore | 3 ++ Cargo.toml | 3 +- src/constants.rs | 2 - src/lib.rs | 93 +++++++++++++++++++++++++++++++++++++++++ src/main.rs | 17 +++----- src/platform/linux.rs | 63 +++++++++------------------- src/platform/windows.rs | 13 ++++++ 7 files changed, 135 insertions(+), 59 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..981691c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /target + +Cargo.lock +.cargo \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 3a97bf2..2bcad67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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. diff --git a/src/constants.rs b/src/constants.rs index ad78ab4..33ff797 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -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 pub const IOC_BYTE: u8 = 0x53; diff --git a/src/lib.rs b/src/lib.rs index e69de29..53dc436 100644 --- a/src/lib.rs +++ b/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; + + /// Get the type of disc currently in the drive + fn disc_type(&mut self) -> Option; + + /// Get the Media Catalog Number of the current disc. + /// + /// Many discs do not contain this information. + fn mcn(&mut self) -> Option; + + fn toc_header(&mut self) -> Result; + + 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; + + /// 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, 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>; +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 23410fe..4eeffb0 100644 --- a/src/main.rs +++ b/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 { diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 2725008..89a9252 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -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 { 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 { + fn status(&mut self) -> Option { 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 { + fn disc_type(&mut self) -> Option { 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 { + fn mcn(&mut self) -> Option { let mut buffer = [0u8; 14]; unsafe { @@ -108,7 +83,7 @@ impl CDRom { Some(string) } - pub fn toc_header(&mut self) -> Result { + fn toc_header(&mut self) -> Result { 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 { + fn subchannel(&mut self) -> Result { 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, CDRomError> { + /// This method is a convenience method around [`CDRomLinux::read_audio_into`]. + fn read_audio(&mut self, address: Addr, frames: usize) -> Result, 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] diff --git a/src/platform/windows.rs b/src/platform/windows.rs index e69de29..443aad3 100644 --- a/src/platform/windows.rs +++ b/src/platform/windows.rs @@ -0,0 +1,13 @@ +use crate::{CDRomError, CDRomTrait}; + +pub struct CDRomWindows {} + +impl CDRomWindows { + pub fn new() -> Result { + Ok(Self { }) + } +} + +impl CDRomTrait for CDRomWindows { + +} \ No newline at end of file