Skip to content

Commit

Permalink
Added support for track-relative MSF
Browse files Browse the repository at this point in the history
  • Loading branch information
simias committed Jun 22, 2016
1 parent 88a2a5f commit 3140ff5
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 10 deletions.
11 changes: 8 additions & 3 deletions src/cue/mod.rs
Expand Up @@ -16,6 +16,7 @@ use Image;
use internal::IndexCache;
use sector::{Sector, SectorBuilder, Metadata};
use msf::Msf;
use bcd::Bcd;

use self::parser::CueParser;

Expand Down Expand Up @@ -72,11 +73,11 @@ impl Image for Cue {
index
} else {
match self.indices
.find_index1_for_track(index.track()) {
Some((_, i)) => i,
.find_index01_for_track(index.track()) {
Ok((_, i)) => i,
// Shouldn't be reached, should be
// caught by IndexCache's constructor
None =>
Err(_) =>
panic!("Missing index 1 for track {}",
index.track()),
}
Expand Down Expand Up @@ -130,6 +131,10 @@ impl Image for Cue {

Ok(())
}

fn track_msf(&self, track: Bcd, track_msf: Msf) -> Result<Msf, CdError> {
self.indices.track_msf(track, track_msf)
}
}

/// Possible types for a CUE track.
Expand Down
60 changes: 55 additions & 5 deletions src/internal.rs
Expand Up @@ -200,23 +200,73 @@ impl<T> IndexCache<T> {
/// a reference to the `Index` struct.
pub fn find_index_for_track(&self,
track: Bcd,
index: Bcd) -> Option<(usize, &Index<T>)> {
index: Bcd) -> Result<(usize, &Index<T>),
CdError> {
match self.indices.binary_search_by(
|idx| match idx.track().cmp(&track) {
cmp::Ordering::Equal => idx.index().cmp(&index),
o => o,
}) {
Ok(i) => Some((i, &self.indices[i])),
Err(_) => None,
Ok(i) => Ok((i, &self.indices[i])),
Err(_) => Err(CdError::BadTrack),
}
}

/// Locate index1 for `track` and return its position along with a
/// reference to the `Index` struct.
pub fn find_index1_for_track(&self,
track: Bcd) -> Option<(usize, &Index<T>)> {
pub fn find_index01_for_track(&self,
track: Bcd) -> Result<(usize, &Index<T>),
CdError> {
self.find_index_for_track(track, Bcd::one())
}

/// Return the length of the given track starting at INDEX 01, not
/// counting the pregap. Also returns the position and a reference
/// to the INDEX 01 for this track.
pub fn track_length(&self, track: Bcd) -> Result<(Msf, usize, &Index<T>),
CdError> {
let (pos01, index01) =
try!(self.find_index01_for_track(track));

// Iterate over the remaining indices to find the beginning of
// the next track

let next_track =
self.indices[pos01 + 1..].iter().find(|i| i.track() != track);

let end =
match next_track {
// We found the next track, the previous sector is the
// last one in our track.
Some(next) => next.sector_index(),
// Seems like we got the last track
None => self.lead_out,
};

let len =
Msf::from_sector_index(end - index01.sector_index()).unwrap();

Ok((len, pos01, index01))
}

/// Return the absolute Msf for the position `track_msf` in
/// `track`. Will return an error if the `track_msf` is outside of
/// the track or if `track` doesn't exist.
pub fn track_msf(&self,
track: Bcd,
track_msf: Msf) -> Result<Msf, CdError> {

// We need to make sure that `track_msf` is not bigger than
// this tracks' length.
let (len, _, index01) =
try!(self.track_length(track));

if track_msf < len {
Ok(index01.msf() + track_msf)
} else {
Err(CdError::EndOfTrack)
}
}
}

impl<T> fmt::Debug for IndexCache<T> {
Expand Down
14 changes: 12 additions & 2 deletions src/lib.rs
Expand Up @@ -16,6 +16,7 @@ use std::io;
use std::fmt;
use sector::Sector;
use msf::Msf;
use bcd::Bcd;

pub mod bcd;
pub mod msf;
Expand All @@ -34,6 +35,11 @@ pub trait Image {

/// Read a single sector at the given MSF
fn read_sector(&mut self, &mut Sector, Msf) -> Result<(), CdError>;

/// Return the absolute Msf for the position `track_msf` in
/// `track`. Will return an error if the `track_msf` is outside of
/// the track or if `track` doesn't exist.
fn track_msf(&self, track: Bcd, track_msf: Msf) -> Result<Msf, CdError>;
}

/// Possible session formats.
Expand Down Expand Up @@ -68,6 +74,8 @@ pub enum TrackFormat {
/// Error type for disc operations.
#[derive(Debug)]
pub enum CdError {
/// Generic I/O error
IoError(io::Error),
/// Format missmatch. For instance when one attempts to retrieve
/// CD-ROM payloads on an audio track.
BadFormat,
Expand All @@ -81,8 +89,10 @@ pub enum CdError {
/// track, absurd index etc...). Contains the path of the file and
/// a `String` describing the problem.
BadImage(PathBuf, String),
/// Generic I/O error
IoError(io::Error),
/// Attempted to access an invalid track number
BadTrack,
/// Attempted to access a track past its end
EndOfTrack,
}

impl fmt::Display for CdError {
Expand Down

0 comments on commit 3140ff5

Please sign in to comment.