ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-CD/lib/Convert/CD/Track.pm
Revision: 1.4
Committed: Wed Jun 11 11:53:04 2003 UTC (23 years, 3 months ago) by root
Branch: MAIN
Changes since 1.3: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Convert::CD::Track - desribe track layout and offer data access methods.
4    
5     =head1 SYNOPSIS
6    
7     use Convert::CD::Track;
8    
9     # to be done
10    
11     =head1 DESCRIPTION
12    
13     Kidding?
14    
15     =head2 EXPORTED CONSTANTS
16    
17     FLAG_DCP digital copy permitted
18     FLAG_FCA four channel audio
19     FLAG_PRE track is pre-emphasized
20     FLAG_SCMS protected by serial copy management system (see DCP)
21     FLAG_DATA disk is data track (automatically set for MODE1)
22    
23     MODE_AUDIO
24     MODE_CDG CD+G (Karaoke)
25 root 1.2 MODE_MODE0 MODE 0 (unused, 2336 bps)
26     MODE_MODE1 MODE 1 (standard yellow book, 2048 bps)
27     MODE_MODE2 MODe 2 (CD/XA, 2336 bps)
28 root 1.1 MODE_CDI CD-i, CD Interactive
29    
30     =cut
31    
32     package Convert::CD::Track;
33    
34     use POSIX qw(ceil);
35     use Carp;
36    
37     use base Exporter;
38    
39     $VERSION = 0.01;
40    
41     @EXPORT = qw(
42     FLAG_DCP FLAG_FCA FLAG_PRE FLAG_SCMS FLAG_DATA
43     MODE_AUDIO MODE_CDG MODE_MODE1 MODE_MODE2 MODE_CDI
44     );
45    
46 root 1.2 sub FLAG_DCP () { 0x0001 }
47     sub FLAG_FCA () { 0x0002 }
48     sub FLAG_PRE () { 0x0004 }
49     sub FLAG_DATA () { 0x0008 }
50     sub FLAG_SCMS () { 0x1000 }
51 root 1.1
52 root 1.3 sub MODE_MODE0 () { 0 }
53     sub MODE_MODE1 () { 1 }
54     sub MODE_MODE2 () { 2 }
55     sub MODE_AUDIO () { 3 }
56     sub MODE_CDG () { 4 }
57     sub MODE_CDI () { 5 }
58 root 1.1
59     =head2 Convert::CD::Track METHODS
60    
61     This class is used to repesent single track objects.
62    
63     =over 4
64    
65     =item new param => value...
66    
67     Create a new track object. Parameters that are not given are usually
68     guess, depending on the mode and other parameters.
69    
70     Parameters:
71    
72     path the file that contains the track
73     offset the offste within the file that contains the first sector
74     (may be negative)
75     rawsize the raw size (in bytes) of the track. (guessed if missing)
76     mode a mode string (MODE1, MODE2, AUDIO, CDI, CDG....)
77     datasize size of the data part of the sector (e.g. 2048).
78 root 1.3 dataoffset offset of data part within sector
79 root 1.1 secsize size of a sector in disk image
80     index an array of index times (0 is pregap start, 1 is track start)
81    
82     =cut
83    
84     sub new {
85     my $class = shift;
86     my $self = bless {
87     @_,
88     }, $class;
89    
90     $self->{rawsize} ||= (-s $self->{path}) - $self->{offset};
91    
92     $self->{flags} ||= FLAG_DATA if $self->{mode} == MODE_MODE1;
93     $self->{datasize} ||= $self->{mode} == MODE_MODE1 ? 2048
94     : $self->{mode} == MODE_MODE2 ? 2336
95     : $self->{mode} == MODE_AUDIO ? 2352
96     : $self->{secsize};
97    
98     $self->{datasize} = $self->{secsize}
99     if $self->{secsize} < $self->{datasize};
100    
101 root 1.3 # guess offset by type OR datasize
102    
103 root 1.1 $self;
104     }
105    
106     # create and cache a filehandle of the given mode
107     sub fh {
108     my ($self, $mode) = @_;
109    
110     $self->{fh}{$mode} ||= do {
111     open my $fh, $mode, $self->{path}
112     or croak "$self->{path}: $!";
113     binmode $fh; # *seufz*
114     $fh;
115     };
116     }
117    
118     =item $track->read ($offset, $length)
119    
120     Reads and returns a part of the track. C<$offset> should be a multiple of
121     the datasize.
122    
123     =cut
124    
125     sub read {
126     my ($self, $offset, $length) = @_;
127     my $buf;
128    
129     my $fh = $self->fh ("<");
130    
131     $offset = $offset / $self->{secsize} * $self->{secsize};
132 root 1.4 $offset += $self->{offset} + $self->{dataoffset};
133 root 1.1
134     while ($length > 0) {
135 root 1.3 if ($offset < 0) {
136     $buf .= "\x00" x $self->{datasize};
137     } else {
138     sysseek $fh, $offset, 0
139     or croak "seek($self->{path}): $!";
140     sysread $fh, $buf, ($length < $self->{datasize} ? $length : $self->{datasize}), length $buf
141     or croak "read($self->{path}): $!";
142     }
143 root 1.1
144     $length -= $self->{datasize};
145     $offset += $self->{secsize};
146     }
147    
148     $buf;
149     }
150    
151     =item $track->size
152    
153     Returns the (cooked) size of the track in bytes, i.e. logical size of the
154     track without any ECC etc. information.
155    
156     =cut
157    
158     sub size {
159     my ($self) = @_;
160    
161     ceil ($self->{rawsize} / $self->{secsize}) * $self->{datasize};
162     }
163    
164     =item $track->as_string
165    
166     Returns a single-line, textual description of the track.
167    
168     =cut
169    
170     sub as_string {
171     my ($self) = @_;
172     my %data = %$self;
173    
174     $data{index} = "<" . (join "|", @{$data{index}}) .">";
175    
176     sprintf "%s %08x+%08x %s/%d (%s)",
177     delete @data{qw(path offset rawsize mode secsize)},
178     join " ", %data;
179     }
180    
181     =item $track->to_msf ($offset)
182    
183     Converts the given byte offste into M:S:F format.
184    
185     =cut
186    
187     sub to_msf {
188     my ($self, $offset) = @_;
189    
190     my $frame = $offset / $self->{datasize};
191    
192     sprintf "%02d:%02d:%02d", $frame / (60 * 75),
193     $frame / 75 % 60,
194     $frame % 75;
195     }
196    
197     1;
198    
199     =back
200    
201     =head1 AUTHOR
202    
203     Marc Lehmann <pcg@goof.com>
204    
205     =cut
206