ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Convert-CD/lib/Convert/CD/Track.pm
Revision: 1.5
Committed: Thu Mar 3 17:49:58 2005 UTC (21 years, 6 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
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 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 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 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
52 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
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 dataoffset offset of data part within sector
79 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 # guess offset by type OR datasize
102
103 $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 $offset += $self->{offset} + $self->{dataoffset};
133
134 while ($length > 0) {
135 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
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 <schmorp@schmorp.de>
204
205 =cut
206