1 /*  cdrdao - write audio CD-Rs in disc-at-once mode
2  *
3  *  Copyright (C) 1998-2001  Andreas Mueller <andreas@daneb.de>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 #include <config.h>
21 
22 #include <stddef.h>
23 #include <assert.h>
24 #include <ctype.h>
25 #include <string.h>
26 
27 #include "Track.h"
28 #include "util.h"
29 #include "log.h"
30 #include "TrackDataList.h"
31 #include "CdTextItem.h"
32 #include "lec.h"
33 
Track(TrackData::Mode t,TrackData::SubChannelMode st)34 Track::Track(TrackData::Mode t, TrackData::SubChannelMode st)
35   : length_(0), start_(0), end_(0)
36 {
37   type_ = t;
38   subChannelType_ = st;
39   audioCutMode_ = -1;
40 
41   nofSubTracks_ = 0;
42   subTracks_ = lastSubTrack_ = NULL;
43 
44   nofIndices_ = 0;
45   index_ = new Msf[98];
46 
47   isrcValid_ = 0;
48 
49   flags_.copy = 0;         // digital copy not permitted
50   flags_.preEmphasis = 0;  // no pre-emphasis
51   flags_.audioType = 0;    // two channel audio
52 }
53 
Track(const Track & obj)54 Track::Track(const Track &obj)
55   : length_(obj.length_), start_(obj.start_), end_(obj.end_),
56     cdtext_(obj.cdtext_)
57 {
58   int i;
59   SubTrack *run;
60 
61   type_ = obj.type_;
62   subChannelType_ = obj.subChannelType_;
63   audioCutMode_ = obj.audioCutMode_;
64 
65   nofSubTracks_ = obj.nofSubTracks_;
66   subTracks_ = lastSubTrack_ = NULL;
67   for (run = obj.subTracks_; run != NULL; run = run->next_) {
68     if (subTracks_ == NULL) {
69       subTracks_ = lastSubTrack_ = new SubTrack(*run);
70     }
71     else {
72       lastSubTrack_->next_ = new SubTrack(*run);
73       lastSubTrack_->next_->pred_ = lastSubTrack_;
74       lastSubTrack_ = lastSubTrack_->next_;
75     }
76   }
77 
78   nofIndices_ = obj.nofIndices_;
79   index_ = new Msf[98];
80   for (i = 0; i < nofIndices_; i++) {
81     index_[i] = obj.index_[i];
82   }
83 
84   isrcValid_ = obj.isrcValid_;
85   memcpy(isrcCountry_, obj.isrcCountry_, 2);
86   memcpy(isrcOwner_, obj.isrcOwner_, 3);
87   memcpy(isrcYear_, obj.isrcYear_, 2);
88   memcpy(isrcSerial_, obj.isrcSerial_, 5);
89 
90   flags_ = obj.flags_;
91 }
92 
93 
~Track()94 Track::~Track()
95 {
96   SubTrack *run = subTracks_;
97   SubTrack *next = NULL;
98 
99   while (run != NULL) {
100     next = run->next_;
101     delete run;
102     run = next;
103   }
104 
105   delete[] index_;
106 }
107 
108 // Returns first sub-track or 'NULL' if no sub-tracks are defined
firstSubTrack() const109 const SubTrack *Track::firstSubTrack() const
110 {
111   return subTracks_ != NULL ? subTracks_ : NULL;
112 }
113 
114 // Returns last sub-track or 'NULL' if no sub-tracks are defined
lastSubTrack() const115 const SubTrack *Track::lastSubTrack() const
116 {
117   return lastSubTrack_ != NULL ? lastSubTrack_ : NULL;
118 }
119 
120 
121 // Appends given sub-track to list of sub-tracks.
122 // return: 0: OK
123 //         1: tried to append PAD sub-track
124 //         2: tried to append sub-track with different audioCutMode
append(const SubTrack & strack)125 int Track::append(const SubTrack &strack)
126 {
127   if (strack.type() == SubTrack::PAD)
128     return 1;
129 
130   if (audioCutMode_ != -1 && audioCutMode_ != strack.audioCutMode())
131     return 2;
132 
133   if (lastSubTrack_ != NULL && lastSubTrack_->type() == SubTrack::PAD &&
134       lastSubTrack_->mode() == strack.mode() &&
135       lastSubTrack_->subChannelMode() == strack.subChannelMode()) {
136     // remove padding sub track
137     delete removeSubTrack(lastSubTrack_);
138   }
139 
140   // append sub track
141   insertSubTrackAfter(lastSubTrack_, new SubTrack(strack));
142 
143   update();
144 
145   return 0;
146 }
147 
148 
149 // Traverses all sub-tracks to update summary data of track.
update()150 void Track::update()
151 {
152   long lenLba = 0;           // accumulates total length of track in blocks
153   unsigned long slength;     // length of track in samples
154   unsigned long padLen;      // padding length
155   unsigned long blen;        // block length for current data mode
156   SubTrack *run, *next;
157   SubTrack *pad;
158   TrackData::Mode dataMode;
159   TrackData::SubChannelMode subChannelMode;
160 
161   // remove all padding sub-tracks
162   run = subTracks_;
163   while (run != NULL) {
164     next = run->next_;
165 
166     if (run->type() == SubTrack::PAD) {
167       delete removeSubTrack(run);
168     }
169 
170     run = next;
171   }
172 
173   audioCutMode_ = -1;
174 
175   if ((run = subTracks_) != NULL) {
176     do {
177       dataMode = run->mode();
178       subChannelMode = run->subChannelMode();
179 
180       if (audioCutMode_ == -1)
181 	audioCutMode_ = run->audioCutMode();
182       else if (audioCutMode_ != run->audioCutMode())
183 	log_message(-3, "Track::update: mixed audio cut mode.");
184 
185       if (audioCutMode_)
186 	blen = SAMPLES_PER_BLOCK;
187       else
188 	blen = TrackData::dataBlockSize(dataMode, subChannelMode);
189 
190       slength = 0;
191 
192       // find continues range of sub tracks with same data mode
193       do {
194 	slength += run->length();
195 	run = run->next_;
196       } while (run != NULL && run->mode() == dataMode &&
197 	       run->subChannelMode() == subChannelMode);
198 
199       if ((padLen = slength % blen) != 0) {
200 	padLen = blen - padLen;
201 
202 	if (audioCutMode_)
203 	  pad = new SubTrack(SubTrack::PAD, 0, TrackData(padLen));
204 	else
205 	  pad = new SubTrack(SubTrack::PAD, 0,
206 			     TrackData(dataMode, subChannelMode, padLen));
207 
208 	if (run != NULL) {
209 	  insertSubTrackAfter(run->pred_, pad);
210 	}
211 	else {
212 	  insertSubTrackAfter(lastSubTrack_, pad);
213 	}
214 	slength += padLen;
215       }
216 
217       // at this point 'slength' should be a multiple of 'blen'
218       assert(slength % blen == 0);
219 
220       lenLba += slength / blen;
221 
222     } while (run != NULL);
223   }
224 
225   length_ = Msf(lenLba);
226 
227   slength = 0;
228   for (run = subTracks_; run != NULL; run = run->next_) {
229     run->start(slength); // set start position of sub-track
230     slength += run->length();
231   }
232 
233 
234   // reset 'start_' if necessary
235   if (start_.lba() >= length_.lba()) {
236     start_ = Msf(0);
237   }
238 }
239 
240 // Sets logical start of track, everthing before start (if != 0) is taken
241 // as pre-gap. FIXME: Already set index marks are not updated.
242 // return: 0: OK
243 //         1: given start behind track end
start(Msf s)244 int Track::start(Msf s)
245 {
246   // A length of zero gets a pass for this test. The track length is
247   // optional for the last track entry of the TOC file, because the
248   // actual length of the track filename is not necessarily known at
249   // this stage (mp3...). The actual length will be filled in later by
250   // recomputeLength().
251   if (s.lba() >= length_.lba() && (length_.lba() != 0)) {
252     return 1;
253   }
254 
255   start_ = s;
256 
257   return 0;
258 }
259 
260 // Sets end of user area of track which is the start of the post-gap.
261 // An index entry is created at this point. The pre-gap length must be
262 // set with 'start()' before this function can be called.
263 // return: 0: OK
264 //         1: start of post-gap is behind or at track end
265 //         2: post-gap within pre-gap
266 //         3: cannot create index mark, 98 index marks are already defined
end(Msf e)267 int Track::end(Msf e)
268 {
269   if (e.lba() >= length_.lba()) {
270     return 1;
271   }
272 
273   if (e.lba() != 0 && e.lba() <= start_.lba()) {
274     return 2;
275   }
276 
277   if (e.lba() != 0) {
278     // add index mark for post-gap
279     if (addIndex(Msf(e.lba() - start_.lba())) == 1) {
280       // already 98 index increments defined
281       return 3;
282     }
283   }
284 
285   end_ = e;
286 
287   return 0;
288 }
289 
290 
291 // Appends given index to index increment list.
292 // return: 0: OK
293 //         1: > 98 index increments
294 //         2: index at or beyond track end
295 //         3: index at start
appendIndex(const Msf & index)296 int Track::appendIndex(const Msf &index)
297 {
298   if (nofIndices_ == 98) {
299     return 1;
300   }
301 
302   if (index.lba() >= (length_ - start_).lba()) {
303     return 2;
304   }
305 
306   if (index.lba() == 0) {
307     return 3;
308   }
309 
310   index_[nofIndices_] = index;
311   nofIndices_ += 1;
312 
313   return 0;
314 }
315 
316 // Adds index at given position
317 // return: 0: OK
318 //         1: > 98 index increments
319 //         2: cannot add index at specified position
addIndex(const Msf & index)320 int Track::addIndex(const Msf &index)
321 {
322   int i;
323   if (nofIndices_ == 98) {
324     return 1;
325   }
326 
327   if (index.lba() >= (length_ - start_).lba()) {
328     return 2;
329   }
330 
331   if (index.lba() == 0) {
332     return 2;
333   }
334 
335   for (i = 0; i < nofIndices_; i++) {
336     if (index.lba() == index_[i].lba())
337       return 2;
338 
339     if (index.lba() < index_[i].lba())
340       break;
341   }
342 
343   if (i == nofIndices_) {
344     // append index
345     index_[nofIndices_] = index;
346     nofIndices_ += 1;
347   }
348   else {
349     int pos = i;
350     for (i = nofIndices_; i > pos; i--)
351       index_[i] = index_[i - 1];
352 
353     index_[pos] = index;
354     nofIndices_ += 1;
355   }
356 
357   return 0;
358 }
359 
360 // Removes specified index.
361 // return 0: OK
362 //        1: index not found
removeIndex(int index)363 int Track::removeIndex(int index)
364 {
365   int i;
366 
367   if (index < 0 || index >= nofIndices_)
368     return 1;
369 
370 
371   for (i = index; i < nofIndices_ - 1; i++)
372     index_[i] = index_[i + 1];
373 
374   nofIndices_ -= 1;
375 
376   return 0;
377 }
378 
379 // returns index increment
getIndex(int i) const380 Msf Track::getIndex(int i) const
381 {
382   if (i >= nofIndices_ || i < 0) {
383     return Msf(0);
384   }
385   else {
386     return index_[i];
387   }
388 }
389 
check(int trackNr) const390 int Track::check(int trackNr) const
391 {
392   int ret = 0;
393 
394   if (length().lba() - start().lba() < Msf(0, 4, 0).lba()) {
395     log_message(-1, "Track %d: Length is shorter than 4 seconds.", trackNr);
396     ret = 1;
397   }
398 
399   for (SubTrack* st = subTracks_; st; st = st->next_) {
400     ret |= st->check(trackNr);
401   }
402 
403   return ret;
404 }
405 
recomputeLength()406 bool Track::recomputeLength()
407 {
408   for (SubTrack* st = subTracks_; st; st = st->next_) {
409     if (st->length() == 0) {
410       st->determineLength();
411     }
412   }
413 
414   update();
415   return true;
416 }
417 
418 // Sets ISRC code. Expected string: "CCOOOYYSSSSS"
419 //                 C: country code (ASCII)
420 //                 O: owner code (ASCII)
421 //                 Y: year ('0'-'9')
422 //                 S: serial number ('0'-'9')
423 // return: 0: OK
424 //         1: ilegal ISRC string
isrc(const char * isrc)425 int Track::isrc(const char *isrc)
426 {
427   int i;
428 
429   if (isrc == NULL) {
430     isrcValid_ = 0;
431     return 0;
432   }
433 
434   if (strlen(isrc) != 12) {
435     return 1;
436   }
437 
438   for (i=0; i < 5; i++) {
439     if (!(isdigit(isrc[i]) || isupper(isrc[i]))) {
440       return 1;
441     }
442   }
443 
444   for (i = 5; i < 12; i++) {
445     if (!isdigit(isrc[i])) {
446       return 1;
447     }
448   }
449 
450   isrcCountry_[0] = isrc[0];
451   isrcCountry_[1] = isrc[1];
452 
453   isrcOwner_[0] = isrc[2];
454   isrcOwner_[1] = isrc[3];
455   isrcOwner_[2] = isrc[4];
456 
457 
458   // store BCD
459   isrcYear_[0] = isrc[5] - '0';
460   isrcYear_[1] = isrc[6] - '0';
461 
462   isrcSerial_[0] = isrc[7] - '0';
463   isrcSerial_[1] = isrc[8] - '0';
464   isrcSerial_[2] = isrc[9] - '0';
465   isrcSerial_[3] = isrc[10] - '0';
466   isrcSerial_[4] = isrc[11] - '0';
467 
468   isrcValid_ = 1;
469 
470   return 0;
471 }
472 
isrc() const473 const char *Track::isrc() const
474 {
475   static char buf[13];
476 
477   if (!isrcValid_)
478     return NULL;
479 
480   buf[0] = isrcCountry_[0];
481   buf[1] = isrcCountry_[1];
482   buf[2] = isrcOwner_[0];
483   buf[3] = isrcOwner_[1];
484   buf[4] = isrcOwner_[2];
485   buf[5] = isrcYear_[0] + '0';
486   buf[6] = isrcYear_[1] + '0';
487   buf[7] = isrcSerial_[0] + '0';
488   buf[8] = isrcSerial_[1] + '0';
489   buf[9] = isrcSerial_[2] + '0';
490   buf[10] = isrcSerial_[3] + '0';
491   buf[11] = isrcSerial_[4] + '0';
492   buf[12] = 0;
493 
494   return buf;
495 }
496 
isPadded() const497 int Track::isPadded() const
498 {
499   SubTrack *run;
500 
501   for (run = subTracks_; run != NULL; run = run->next_) {
502     if (run->type() == SubTrack::PAD)
503       return 1;
504   }
505 
506   return 0;
507 }
508 
509 // writes out track data in TOC file syntax
print(std::ostream & out,bool conversions) const510 void Track::print(std::ostream &out, bool conversions) const
511 {
512   SubTrack *st;
513   const char *s;
514   int i;
515 
516   out << "TRACK " << TrackData::mode2String(type());
517 
518   s = TrackData::subChannelMode2String(subChannelType());
519 
520   if (*s != 0)
521     out << " " << s;
522 
523   out << std::endl;
524 
525   if (!copyPermitted())
526     out << "NO ";
527   out << "COPY" << std::endl;
528 
529   if (type() == TrackData::AUDIO) {
530     if (!preEmphasis())
531       out << "NO ";
532     out << "PRE_EMPHASIS" << std::endl;
533 
534     if (audioType() == 0)
535       out << "TWO_CHANNEL_AUDIO" << std::endl;
536     else
537       out << "FOUR_CHANNEL_AUDIO" << std::endl;
538 
539     if (isrcValid()) {
540       out << "ISRC \"" << isrcCountry(0) << isrcCountry(1)
541 	  << isrcOwner(0) << isrcOwner(1) << isrcOwner(2)
542 	  << (char)(isrcYear(0) + '0') << (char)(isrcYear(1) + '0')
543 	  << (char)(isrcSerial(0) + '0') << (char)(isrcSerial(1) + '0')
544 	  << (char)(isrcSerial(2) + '0') << (char)(isrcSerial(3) + '0')
545 	  << (char)(isrcSerial(4) + '0') << "\"" << std::endl;
546     }
547 
548     cdtext_.print(1, out);
549   }
550 
551 
552   for (st = subTracks_; st != NULL; st = st->next_) {
553     st->print(out, conversions);
554   }
555 
556   if (start_.lba() != 0) {
557     out << "START " << start_.str() << std::endl;
558   }
559 
560   for (i = 0; i < nofIndices_; i++) {
561     out << "INDEX " << index_[i].str() << std::endl;
562   }
563 }
564 
collectFiles(std::set<std::string> & set)565 void Track::collectFiles(std::set<std::string>& set)
566 {
567   SubTrack* st;
568   for (st = subTracks_; st != NULL; st = st->next_) {
569     const char* f = st->filename();
570     if (f)
571       set.insert(f);
572   }
573 }
574 
markFileConversion(const char * src,const char * dst)575 void Track::markFileConversion(const char* src, const char* dst)
576 {
577   SubTrack* st;
578   for (st = subTracks_; st != NULL; st = st->next_) {
579     const char* f = st->filename();
580     if (f && strcmp(f, src) == 0) {
581       st->effectiveFilename(dst);
582     }
583   }
584 }
585 
resolveFilename(const char * path)586 bool Track::resolveFilename(const char* path)
587 {
588   SubTrack* st;
589   for (st = subTracks_; st != NULL; st = st->next_) {
590     std::string rfilename;
591     const char* f = st->filename();
592 
593     if (f) {
594       // STDIN is a special case (stdin input), don't process it.
595       if (strcmp(f, "STDIN") == 0)
596         continue;
597 
598       if (::resolveFilename(rfilename, f, path)) {
599         st->effectiveFilename(rfilename.c_str());
600       } else {
601         log_message(-2, "Could not find input file \"%s\".", f);
602         return false;
603       }
604     }
605   }
606 
607   return true;
608 }
609 
610 // Locates 'SubTrack' that contains specified sample.
611 // return: found 'SubTrack' or 'NULL' if given sample is out of range
findSubTrack(unsigned long sample) const612 SubTrack *Track::findSubTrack(unsigned long sample) const
613 {
614   SubTrack *run;
615 
616   if (audioCutMode()) {
617     if (sample >= length_.samples())
618       return NULL;
619   }
620   else {
621     if (sample >=
622 	length_.lba() * TrackData::dataBlockSize(type(), subChannelType()))
623       return NULL;
624   }
625 
626   for (run = subTracks_;
627        run != NULL && run->next_ != NULL;
628        run = run->next_) {
629     if (sample < run->next_->start())
630       return run;
631   }
632 
633   return run;
634 }
635 
636 
countSubTracks()637 void Track::countSubTracks()
638 {
639   SubTrack *run;
640 
641   nofSubTracks_ = 0;
642   for (run = subTracks_; run != NULL; run = run->next_)
643     nofSubTracks_++;
644 }
645 
646 // move track start or index increment within track range
647 // return: 0: OK
648 //         1: track length would be shorter than 4 seconds
649 //         2: cannot cross index boundary
moveIndex(int index,long lba)650 int Track::moveIndex(int index, long lba)
651 {
652   int i;
653   long rangeMin;
654   long rangeMax;
655 
656   assert(index > 0 && index - 2 < nofIndices_);
657   assert(lba >= 0 && index < length_.lba());
658 
659   if (index == 1) {
660     if (nofIndices_ > 0 && lba >= start_.lba() + getIndex(0).lba())
661       return 2;
662 
663     if (lba > length_.lba() - 4 * 75)
664       return 1;
665 
666     // adjust index increments to new track start
667     for (i = 0; i < nofIndices_; i++) {
668       index_[i] = Msf(index_[i].lba() + start_.lba() - lba);
669     }
670 
671     start_ = Msf(lba);
672 
673     return 0;
674   }
675 
676   // adjust 'index' for index array access
677   index -= 2;
678 
679   if (lba <= start_.lba())
680     return 2;
681 
682   lba -= start_.lba();
683 
684   rangeMin = (index == 0 ? 0 : index_[index - 1].lba());
685   rangeMax =
686     (index == nofIndices_ - 1 ? length_.lba() - start_.lba() :
687                                 index_[index + 1].lba());
688 
689   if (lba > rangeMin && lba < rangeMax) {
690     index_[index] = Msf(lba);
691     return 0;
692   }
693 
694   return 2;
695 }
696 
removeToEnd(unsigned long sample)697 TrackDataList *Track::removeToEnd(unsigned long sample)
698 {
699   SubTrack *strun;
700   SubTrack *store;
701   int i;
702 
703   assert(sample > 0 && sample < length_.samples());
704 
705   strun = findSubTrack(sample);
706 
707   assert(strun != NULL);
708 
709   TrackDataList *list = new TrackDataList;
710 
711   if (sample == strun->start()) {
712     // we don't have to split the TrackData object
713     list->append(new TrackData(*strun));
714 
715     // cannot be the first SubTrack because 'sample' > 0
716     strun->pred_->next_ = NULL;
717     lastSubTrack_ = strun->pred_;
718 
719     store = strun;
720     strun = strun->next_;
721     delete store;
722   }
723   else {
724     // split audio data object
725     TrackData *part1, *part2;
726 
727     strun->split(sample - strun->start(), &part1, &part2);
728 
729     list->append(part2);
730 
731     store = new SubTrack(strun->type(), *part1);
732     delete part1;
733 
734     if (strun->pred_ == NULL) {
735       subTracks_ = store;
736     }
737     else {
738       strun->pred_->next_ = store;
739       store->pred_ = strun->pred_;
740     }
741     lastSubTrack_ = store;
742 
743     store = strun;
744     strun = strun->next_;
745     delete store;
746   }
747 
748 
749   while (strun != NULL) {
750     list->append(new TrackData(*strun));
751 
752     store = strun;
753     strun = strun->next_;
754     delete store;
755   }
756 
757   countSubTracks();
758   update();
759 
760   checkConsistency();
761 
762   // adjust index increments
763   for (i = 0; i < nofIndices_; i++) {
764     if (index_[i].lba() + start_.lba() >= length_.lba()) {
765       nofIndices_ = i;
766       break;
767     }
768   }
769 
770   return list;
771 }
772 
removeFromStart(unsigned long sample)773 TrackDataList *Track::removeFromStart(unsigned long sample)
774 {
775   SubTrack *strun;
776   SubTrack *store, *start;
777   int i;
778 
779   assert(sample > 0 && sample < length_.samples());
780 
781   TrackDataList *list = new TrackDataList;
782 
783   for (strun = subTracks_;
784        strun != NULL && strun->next_ != NULL;
785        strun = strun->next_) {
786     if (sample < strun->next_->start())
787       break;
788     else
789       list->append(new TrackData(*strun));
790   }
791 
792   assert(strun != NULL);
793 
794   start = subTracks_;
795 
796   if (sample == strun->start()) {
797     // we don't have to split the TrackData object
798     // cannot be the first SubTrack because 'sample' > 0
799 
800     strun->pred_->next_ = NULL;
801     subTracks_ = strun;
802     subTracks_->pred_ = NULL;
803   }
804   else {
805     // split actual sub track
806 
807     TrackData *part1, *part2;
808 
809     strun->split(sample - strun->start(), &part1, &part2);
810 
811     list->append(part1);
812 
813     store = new SubTrack(strun->type(), *part2);
814     delete part2;
815 
816     store->next_ = strun->next_;
817     if (store->next_ != NULL)
818       store->next_->pred_ = store;
819 
820     strun->next_ = NULL;
821     subTracks_ = store;
822 
823     if (strun == lastSubTrack_)
824       lastSubTrack_ = store;
825   }
826 
827   // remove unlinked sub tracks
828   while (start != NULL) {
829     store = start;
830     start = start->next_;
831 
832     delete store;
833   }
834 
835   countSubTracks();
836   update();
837 
838   checkConsistency();
839 
840   // adjust index increments
841   for (i = 0; i < nofIndices_; i++) {
842     if (index_[i].lba() + start_.lba() >= length_.lba()) {
843       nofIndices_ = i;
844       break;
845     }
846   }
847 
848   return list;
849 }
850 
851 
prependTrackData(const TrackDataList * list)852 void Track::prependTrackData(const TrackDataList *list)
853 {
854   SubTrack *start = NULL;
855   SubTrack *last = NULL;
856   SubTrack *ent;
857   const TrackData *run;
858 
859   if (list->count() == 0)
860     return;
861 
862   for (run = list->first(); run != NULL; run = list->next()) {
863     ent = new SubTrack(SubTrack::DATA, *run);
864     if (last == NULL) {
865       start = ent;
866     }
867     else {
868       last->next_ = ent;
869       ent->pred_ = last;
870     }
871     last = ent;
872   }
873 
874   if (subTracks_ == NULL) {
875     subTracks_ = start;
876     lastSubTrack_ = last;
877   }
878   else {
879     last->next_ = subTracks_;
880     subTracks_->pred_ = last;
881     subTracks_ = start;
882   }
883 
884   mergeSubTracks(); // this will also update the sub track counter
885   update();
886 
887   checkConsistency();
888 }
889 
appendTrackData(const TrackDataList * list)890 void Track::appendTrackData(const TrackDataList *list)
891 {
892   SubTrack *start = NULL;
893   SubTrack *last = NULL;
894   SubTrack *ent;
895   const TrackData *run;
896 
897   if (list->count() == 0)
898     return;
899 
900   for (run = list->first(); run != NULL; run = list->next()) {
901     ent = new SubTrack(SubTrack::DATA, *run);
902     if (last == NULL) {
903       start = ent;
904     }
905     else {
906       last->next_ = ent;
907       ent->pred_ = last;
908     }
909     last = ent;
910   }
911 
912   if (lastSubTrack_ != NULL) {
913     if (lastSubTrack_->type() == SubTrack::PAD)
914       lastSubTrack_->type_ = SubTrack::DATA;
915 
916     lastSubTrack_->next_ = start;
917     start->pred_ = lastSubTrack_;
918     lastSubTrack_ = last;
919   }
920   else {
921     subTracks_ = start;
922     lastSubTrack_ = last;
923   }
924 
925   mergeSubTracks(); // this will also update the sub track counter
926   update();
927 
928   checkConsistency();
929 }
930 
appendTrackData(const Track * track)931 void Track::appendTrackData(const Track *track)
932 {
933   SubTrack *run, *ent;
934 
935   for (run = track->subTracks_; run != NULL; run = run->next_) {
936     ent = new SubTrack(*run);
937 
938     if (lastSubTrack_ == NULL) {
939       subTracks_ = ent;
940     }
941     else {
942       lastSubTrack_->next_ = ent;
943       ent->pred_ = lastSubTrack_;
944     }
945     lastSubTrack_ = ent;
946   }
947 
948   mergeSubTracks(); // this will also update the sub track counter
949   update();
950 
951   checkConsistency();
952 }
953 
removeTrackData(unsigned long start,unsigned long end)954 TrackDataList *Track::removeTrackData(unsigned long start, unsigned long end)
955 {
956   SubTrack *run;
957   TrackData *part1, *part2, *part3;
958   unsigned long plen;
959 
960   if (start > end || end >= length_.samples())
961     return NULL;
962 
963   SubTrack *startSt = findSubTrack(start);
964   SubTrack *endSt = findSubTrack(end);
965 
966   assert(startSt != NULL);
967   assert(endSt != NULL);
968 
969   TrackDataList *list = new TrackDataList;
970 
971   if (startSt == endSt) {
972     if (start == startSt->start() &&
973 	end == startSt->start() + startSt->length() - 1) {
974       // remove complete sub track
975       list->append(new TrackData(*startSt));
976     }
977     else if (start == startSt->start()) {
978       // remove first part of sub track
979       startSt->split(end + 1 - startSt->start(), &part1, &part2);
980       list->append(part1);
981       insertSubTrackAfter(startSt, new SubTrack(startSt->type(), *part2));
982       delete part2;
983     }
984     else if (end == startSt->start() + startSt->length() - 1) {
985       // remove last part of sub track
986       startSt->split(start - startSt->start(), &part1, &part2);
987       list->append(part2);
988       insertSubTrackAfter(startSt, new SubTrack(startSt->type(), *part1));
989       delete part1;
990     }
991     else {
992       // remove middle part of sub track
993       startSt->split(start - startSt->start(), &part1, &part2);
994 
995       insertSubTrackAfter(startSt->pred_,
996 			  new SubTrack(startSt->type(), *part1));
997       plen = part1->length();
998       delete part1;
999 
1000       part2->split(end + 1 - startSt->start() - plen, &part1, &part3);
1001       list->append(part1);
1002 
1003       insertSubTrackAfter(startSt, new SubTrack(startSt->type(), *part3));
1004       delete part3;
1005       delete part2;
1006     }
1007 
1008     delete removeSubTrack(startSt);
1009   }
1010   else {
1011     if (start == startSt->start()) {
1012       // remove complete sub track
1013       list->append(new TrackData(*startSt));
1014     }
1015     else {
1016       startSt->split(start - startSt->start(), &part1, &part2);
1017       list->append(part2);
1018       insertSubTrackAfter(startSt->pred_,
1019 			  new SubTrack(startSt->type(), *part1));
1020       delete part1;
1021     }
1022 
1023     for (run = startSt->next_; run != endSt; run = run->next_)
1024       list->append(new TrackData(*(startSt->next_)));
1025 
1026     if (end == endSt->start() + endSt->length() - 1) {
1027       // remove complete sub track
1028       list->append(new TrackData(*endSt));
1029     }
1030     else {
1031       endSt->split(end + 1 - endSt->start(), &part1, &part2);
1032       list->append(part1);
1033       insertSubTrackAfter(endSt, new SubTrack(endSt->type(), *part2));
1034       delete part2;
1035     }
1036 
1037     while (startSt->next_ != endSt)
1038       delete removeSubTrack(startSt->next_);
1039 
1040     delete removeSubTrack(startSt);
1041     delete removeSubTrack(endSt);
1042   }
1043 
1044 
1045   // adjust index marks
1046   unsigned long len;
1047   long preGapAdj = 0;
1048   long slba = 0;
1049   long elba = 0;
1050   long indexMove = 0;
1051   long indexAdj = 0;
1052   int i;
1053 
1054   if (start < start_.samples()) {
1055     if (end < start_.samples()) {
1056       len = end - start + 1;
1057       slba = -1;
1058       elba = -1;
1059     }
1060     else {
1061       len = start_.samples() - start;
1062       elba = (end - start_.samples()) / SAMPLES_PER_BLOCK;
1063       slba = 0;
1064       indexMove = (end - start_.samples() + 1) / SAMPLES_PER_BLOCK;
1065       if (((end - start_.samples() + 1) % SAMPLES_PER_BLOCK) != 0)
1066 	indexMove += 1;
1067     }
1068 
1069     preGapAdj = len / SAMPLES_PER_BLOCK;
1070 
1071     if ((len % SAMPLES_PER_BLOCK) != 0)
1072       indexAdj = 1;
1073   }
1074   else {
1075     slba = (start - start_.samples()) / SAMPLES_PER_BLOCK;
1076     if (((start - start_.samples()) % SAMPLES_PER_BLOCK) != 0)
1077       slba += 1;
1078 
1079     elba = (end - start_.samples()) / SAMPLES_PER_BLOCK;
1080 
1081     indexMove = (end - start + 1) / SAMPLES_PER_BLOCK;
1082     if (((end - start + 1) % SAMPLES_PER_BLOCK) != 0)
1083       indexMove += 1;
1084   }
1085 
1086 
1087   i = 0;
1088 
1089   while (i < nofIndices_) {
1090     if (index_[i].lba() >= slba && index_[i].lba() <= elba) {
1091       removeIndex(i);
1092       continue;
1093     }
1094     else if (index_[i].lba() > elba) {
1095       if (index_[i].lba() - indexMove <= 0) {
1096 	removeIndex(i);
1097 	continue;
1098       }
1099       else {
1100 	index_[i] = Msf(index_[i].lba() - indexMove);
1101       }
1102 
1103       if (i > 0 && index_[i - 1].lba() == index_[i].lba()) {
1104 	removeIndex(i);
1105 	continue;
1106       }
1107     }
1108 
1109     if (index_[i].lba() - indexAdj <= 0) {
1110       removeIndex(i);
1111       continue;
1112     }
1113     else {
1114       index_[i] = Msf(index_[i].lba() - indexAdj);
1115     }
1116 
1117     i++;
1118   }
1119 
1120   // adjust pre-gap length
1121   start_ = Msf(start_.lba() - preGapAdj);
1122 
1123 
1124   mergeSubTracks(); // this will also update the sub track counter
1125   update();
1126 
1127   checkConsistency();
1128 
1129   return list;
1130 }
1131 
1132 
insertTrackData(unsigned long pos,const TrackDataList * list)1133 void Track::insertTrackData(unsigned long pos, const TrackDataList *list)
1134 {
1135   const TrackData *run;
1136   TrackData *part1, *part2;
1137   SubTrack *st;
1138   unsigned long len;
1139   long blen;
1140   int i;
1141 
1142   if (list == NULL || list->first() == NULL || list->length() == 0)
1143     return;
1144 
1145 
1146   if (pos >= length_.samples()) {
1147     // append data
1148     for (run = list->first(); run != NULL; run = list->next()) {
1149       insertSubTrackAfter(lastSubTrack_, new SubTrack(SubTrack::DATA, *run));
1150     }
1151   }
1152   else {
1153     st = findSubTrack(pos);
1154 
1155     assert(st != NULL);
1156 
1157     len = list->length();
1158 
1159     if (pos == st->start()) {
1160       for (run = list->first(); run != NULL; run = list->next()) {
1161 	insertSubTrackAfter(st->pred_, new SubTrack(SubTrack::DATA, *run));
1162       }
1163     }
1164     else {
1165       st->split(pos - st->start(), &part1, &part2);
1166 
1167       insertSubTrackAfter(st->pred_, new SubTrack(SubTrack::DATA, *part1));
1168       insertSubTrackAfter(st, new SubTrack(st->type(), *part2));
1169       delete part1;
1170       delete part2;
1171 
1172       for (run = list->first(); run != NULL; run = list->next()) {
1173 	insertSubTrackAfter(st->pred_, new SubTrack(SubTrack::DATA, *run));
1174       }
1175 
1176       delete removeSubTrack(st);
1177     }
1178 
1179     blen = len / SAMPLES_PER_BLOCK;
1180 
1181     if (pos <= start_.samples()) {
1182       start_ = Msf(start_.lba() + blen);
1183     }
1184     else {
1185       for (i = 0; i < nofIndices_; i++) {
1186 	if (index_[i].samples() >= pos)
1187 	  index_[i] = Msf(index_[i].lba() + blen);
1188       }
1189     }
1190   }
1191 
1192   mergeSubTracks(); // this will also update the sub track counter
1193   update();
1194 
1195   checkConsistency();
1196 
1197   return;
1198 }
1199 
mergeSubTracks()1200 void Track::mergeSubTracks()
1201 {
1202   SubTrack *run = subTracks_;
1203   SubTrack *newSubTrack;
1204   TrackData *mergedData;
1205 
1206 
1207   while (run != NULL && run->next_ != NULL) {
1208     if (run->type() == run->next_->type() &&
1209 	(mergedData = run->merge(run->next_)) != NULL) {
1210       newSubTrack = new SubTrack(run->type(), *mergedData);
1211       delete mergedData;
1212 
1213       newSubTrack->next_ =  run->next_->next_;
1214       if (newSubTrack->next_ != NULL)
1215 	newSubTrack->next_->pred_ = newSubTrack;
1216 
1217       if (run->pred_ == NULL) {
1218 	subTracks_ = newSubTrack;
1219       }
1220       else {
1221 	run->pred_->next_ = newSubTrack;
1222 	newSubTrack->pred_ = run->pred_;
1223       }
1224 
1225       if (run->next_ == lastSubTrack_)
1226 	lastSubTrack_ = newSubTrack;
1227 
1228       delete run->next_;
1229       delete run;
1230       run = newSubTrack;
1231     }
1232     else {
1233       run = run->next_;
1234     }
1235   }
1236 
1237   countSubTracks();
1238 }
1239 
1240 
checkConsistency()1241 void Track::checkConsistency()
1242 {
1243   SubTrack *run, *last = NULL;
1244   long cnt = 0;
1245 
1246   for (run = subTracks_; run != NULL; last = run, run = run->next_) {
1247     cnt++;
1248     if (run->pred_ != last)
1249       log_message(-3, "Track::checkConsistency: wrong pred pointer.");
1250   }
1251 
1252   if (last != lastSubTrack_)
1253     log_message(-3, "Track::checkConsistency: wrong last pointer.");
1254 
1255   if (cnt != nofSubTracks_)
1256     log_message(-3, "Track::checkConsistency: wrong sub track counter.");
1257 }
1258 
1259 // Inserts 'newSubTrack' after existing sub track 'subTrack'. If 'subTrack'
1260 // is NULL it will be prepended.
insertSubTrackAfter(SubTrack * subTrack,SubTrack * newSubTrack)1261 void Track::insertSubTrackAfter(SubTrack *subTrack, SubTrack *newSubTrack)
1262 {
1263   if (subTrack == NULL) {
1264     if (subTracks_ == NULL) {
1265       subTracks_ = lastSubTrack_ = newSubTrack;
1266       newSubTrack->next_ = newSubTrack->pred_ = NULL;
1267     }
1268     else {
1269       newSubTrack->next_ = subTracks_;
1270       subTracks_->pred_ = newSubTrack;
1271 
1272       newSubTrack->pred_ = NULL;
1273       subTracks_ = newSubTrack;
1274     }
1275   }
1276   else {
1277     newSubTrack->next_ = subTrack->next_;
1278     if (newSubTrack->next_ != NULL) {
1279       newSubTrack->next_->pred_ = newSubTrack;
1280     }
1281     else {
1282       lastSubTrack_ = newSubTrack;
1283     }
1284 
1285     subTrack->next_ = newSubTrack;
1286     newSubTrack->pred_ = subTrack;
1287   }
1288 
1289   nofSubTracks_ += 1;
1290 
1291   checkConsistency();
1292 }
1293 
1294 // Removes given sub track from list. Returns the removed sub track.
removeSubTrack(SubTrack * subTrack)1295 SubTrack *Track::removeSubTrack(SubTrack *subTrack)
1296 {
1297   if (subTrack->pred_ == NULL) {
1298     assert(subTrack == subTracks_);
1299 
1300     subTracks_ = subTrack->next_;
1301 
1302     if (subTracks_ != NULL) {
1303       subTracks_->pred_ = NULL;
1304     }
1305     else {
1306       lastSubTrack_ = NULL;
1307     }
1308   }
1309   else {
1310     subTrack->pred_->next_ = subTrack->next_;
1311 
1312     if (subTrack->next_ != NULL) {
1313       subTrack->next_->pred_ = subTrack->pred_;
1314     }
1315     else {
1316       lastSubTrack_ = subTrack->pred_;
1317     }
1318   }
1319 
1320   nofSubTracks_ -= 1;
1321 
1322   subTrack->next_ = subTrack->pred_ = NULL;
1323 
1324   checkConsistency();
1325 
1326   return subTrack;
1327 }
1328 
1329 
1330 // Fills provided buffer with an audio block that contains zero data
1331 // encoded with given mode.
1332 // encMode: encoding mode, see 'TrackReader::readBlock()'
1333 // mode: sector mode
1334 // smode: sub-channel mode
1335 // lba : absolute address of sector
1336 // buf : caller provided buffer that is filled with at most 2448 bytes
1337 
encodeZeroData(int encMode,TrackData::Mode mode,TrackData::SubChannelMode smode,long lba,unsigned char * buf)1338 void Track::encodeZeroData(int encMode, TrackData::Mode mode,
1339 			   TrackData::SubChannelMode smode,
1340 			   long lba, unsigned char *buf)
1341 {
1342   long subChanLen = TrackData::subChannelSize(smode);
1343 
1344   // we won't have to calculate P and Q parity for zero R-W sub-channels
1345   // because 0s have no impact on the parity
1346 
1347   if (encMode == 0) {
1348     memset(buf, 0, AUDIO_BLOCK_LEN + subChanLen);
1349 
1350     switch (mode) {
1351     case TrackData::AUDIO:
1352       break;
1353     case TrackData::MODE0:
1354       lec_encode_mode0_sector(lba, buf);
1355       lec_scramble(buf);
1356       break;
1357     case TrackData::MODE1:
1358     case TrackData::MODE1_RAW:
1359       lec_encode_mode1_sector(lba, (u_int8_t *)buf);
1360       lec_scramble(buf);
1361       break;
1362     case TrackData::MODE2:
1363     case TrackData::MODE2_RAW:
1364       lec_encode_mode2_sector(lba, (u_int8_t *)buf);
1365       lec_scramble(buf);
1366       break;
1367     case TrackData::MODE2_FORM1:
1368     case TrackData::MODE2_FORM_MIX: // encode as form 1
1369       lec_encode_mode2_form1_sector(lba, (u_int8_t *)buf);
1370       lec_scramble(buf);
1371       break;
1372     case TrackData::MODE2_FORM2:
1373       // setup sub header
1374       buf[16+2] = 0x20;
1375       buf[16+6] = 0x20;
1376       lec_encode_mode2_form2_sector(lba, (u_int8_t *)buf);
1377       lec_scramble(buf);
1378       break;
1379     }
1380   }
1381   else if (encMode == 1) {
1382     switch (mode) {
1383     case TrackData::AUDIO:
1384       memset(buf, 0, AUDIO_BLOCK_LEN + subChanLen);
1385       break;
1386     case TrackData::MODE0:
1387       memset(buf, 0, MODE0_BLOCK_LEN + subChanLen);
1388       break;
1389     case TrackData::MODE1:
1390     case TrackData::MODE1_RAW:
1391       memset(buf, 0, MODE1_BLOCK_LEN + subChanLen);
1392       break;
1393     case TrackData::MODE2:
1394     case TrackData::MODE2_RAW:
1395     case TrackData::MODE2_FORM_MIX:
1396       memset(buf, 0, MODE2_BLOCK_LEN + subChanLen);
1397       break;
1398     case TrackData::MODE2_FORM1:
1399       memset(buf, 0, MODE2_BLOCK_LEN + subChanLen);
1400       break;
1401     case TrackData::MODE2_FORM2:
1402       memset(buf, 0, MODE2_BLOCK_LEN + subChanLen);
1403       // setup sub header
1404       buf[2] = 0x20;
1405       buf[6] = 0x20;
1406       break;
1407     }
1408   }
1409   else {
1410     log_message(-3, "Illegal sector encoding mode in 'Track::encodeZeroData()'.");
1411   }
1412 }
1413 
addCdTextItem(CdTextItem * item)1414 void Track::addCdTextItem(CdTextItem *item)
1415 {
1416   assert(CdTextItem::isTrackPack(item->packType()));
1417 
1418   cdtext_.add(item);
1419 }
1420 
removeCdTextItem(CdTextItem::PackType type,int blockNr)1421 void Track::removeCdTextItem(CdTextItem::PackType type, int blockNr)
1422 {
1423   cdtext_.remove(type, blockNr);
1424 }
1425 
TrackReader(const Track * t)1426 TrackReader::TrackReader(const Track *t) : reader(NULL)
1427 {
1428   track_ = t;
1429 
1430   readPos_ = 0;
1431   readPosSample_ = 0;
1432   readSubTrack_ = NULL;
1433   open_ = 0;
1434 
1435   subChanDelayLineIndex_ = 0;
1436 }
1437 
~TrackReader()1438 TrackReader::~TrackReader()
1439 {
1440   if (open_) {
1441     closeData();
1442   }
1443 
1444   track_ = NULL;
1445   readSubTrack_ = NULL;
1446 }
1447 
init(const Track * t)1448 void TrackReader::init(const Track *t)
1449 {
1450   if (open_) {
1451     closeData();
1452   }
1453 
1454   track_ = t;
1455   readSubTrack_ = NULL;
1456 }
1457 
1458 // initiates reading track
1459 // return: 0: OK
1460 //         1: data file could not be opened
1461 //         2: could not seek to start position
openData()1462 int TrackReader::openData()
1463 {
1464   assert(open_ == 0);
1465   assert(track_ != NULL);
1466 
1467   int ret = 0;
1468   //int i;
1469 
1470   open_ = 1;
1471   readPos_ = 0;
1472   readPosSample_ = 0;
1473 
1474   readSubTrack_ = track_->subTracks_;
1475 
1476   reader.init(readSubTrack_);
1477 
1478   subChanDelayLineIndex_ = 0;
1479   /*
1480   for(i = 0; i < MAX_SUB_DEL; i++)
1481     memset(subChanDelayLine_[i], 0, 24);
1482   */
1483 
1484   if (readSubTrack_ != NULL) {
1485     ret = reader.openData();
1486   }
1487 
1488   return ret;
1489 }
1490 
closeData()1491 void TrackReader::closeData()
1492 {
1493   if (open_) {
1494     open_ = 0;
1495     readPos_ = 0;
1496     readPosSample_ = 0;
1497     readSubTrack_ = NULL;
1498 
1499     reader.closeData();
1500   }
1501 }
1502 
1503 
readData(int encodingMode,int subChanEncodingMode,long lba,char * buf,long len)1504 long TrackReader::readData(int encodingMode, int subChanEncodingMode,
1505 			   long lba, char *buf, long len)
1506 {
1507   long err = 0;
1508   long b;
1509   long offset;
1510 
1511   assert(open_ != 0);
1512 
1513   if (readPos_ + len > track_->length_.lba()) {
1514     if ((len = track_->length_.lba() - readPos_) <= 0) {
1515       return 0;
1516     }
1517   }
1518 
1519   for (b = 0; b < len; b++) {
1520     if ((offset = readBlock(encodingMode, subChanEncodingMode, lba,
1521 			    (Sample*)buf)) == 0) {
1522       err = 1;
1523       break;
1524     }
1525     buf += offset;
1526     lba++;
1527   }
1528 
1529   readPos_ += b;
1530 
1531   return err == 0 ? b : -1;
1532 }
1533 
1534 // Reads one block from sub-tracks and performs the data encoding for the
1535 // block.
1536 // encodingMode: conrols how the sector data is encoded
1537 //               0: returned data is always an audio block (2352 bytes),
1538 //                  data blocks are completely encoded
1539 //               1: data is returned mostly unencoded, the block size
1540 //                  depends on the actual sub-track mode, MODE2_FORM1 and
1541 //                  MODE2_FORM2 blocks are extended by the sub header and
1542 //                  filled with 0 bytes to match the MODE2 block size
1543 //                  (2336 bytes).
1544 // subChanEncodingMode: conrols how the R-W sub-channel data is encoded
1545 //                      0: plain R-W data
1546 //                      1: generate Q and P parity and interleave
1547 // lba: Logical block address that must be encoded into header of data blocks
1548 // Return: 0 if error occured, else length of block that has been filled
1549 //
readBlock(int encodingMode,int subChanEncodingMode,long lba,Sample * buf)1550 int TrackReader::readBlock(int encodingMode, int subChanEncodingMode,
1551 			   long lba, Sample *buf)
1552 {
1553   TrackData::Mode dataMode; // current data mode of sub-track
1554   TrackData::SubChannelMode subChanMode; // current sub-channel mode of sub-track
1555   long actLen;
1556   long count; // amount of data the must be read from sub track
1557   long blen;
1558   long nread = 0;
1559   long offset = 0; // block length of returned data
1560   long subChannelDataLen;
1561   char subChanData[MAX_SUBCHANNEL_LEN];
1562 
1563 
1564   while (reader.readLeft() == 0) {
1565     // skip to next sub track with available data
1566     readSubTrack_ = readSubTrack_->next_;
1567     // next sub-track must exist since requested length matches available data
1568     assert(readSubTrack_ != NULL);
1569 
1570     reader.init(readSubTrack_);
1571     if (reader.openData() != 0) {
1572       return 0;
1573     }
1574   }
1575 
1576   dataMode = readSubTrack_->mode(); // current data mode
1577   subChanMode = readSubTrack_->subChannelMode(); // current sub-channel mode
1578 
1579   if (track_->audioCutMode()) {
1580     count = SAMPLES_PER_BLOCK;
1581     blen = AUDIO_BLOCK_LEN;
1582   }
1583   else {
1584     count = TrackData::dataBlockSize(dataMode, subChanMode);
1585     blen = count;
1586   }
1587 
1588   subChannelDataLen = TrackData::subChannelSize(subChanMode);
1589 
1590   char *dataBuf = (char *)buf;
1591 
1592   if (encodingMode == 0) {
1593     offset = AUDIO_BLOCK_LEN;
1594 
1595     switch (dataMode) {
1596     case TrackData::AUDIO:
1597     case TrackData::MODE1_RAW:
1598     case TrackData::MODE2_RAW:
1599       break;
1600     case TrackData::MODE0:
1601     case TrackData::MODE1:
1602     case TrackData::MODE2:
1603     case TrackData::MODE2_FORM_MIX:
1604       dataBuf += 16;
1605       break;
1606     case TrackData::MODE2_FORM1:
1607       memset(dataBuf + 16, 0, 8); // clear sub-header
1608       dataBuf += 24;
1609       break;
1610     case TrackData::MODE2_FORM2:
1611       memset(dataBuf + 16, 0, 8); // clear sub-header
1612       dataBuf[16+2] = 0x20;
1613       dataBuf[16+6] = 0x20;
1614       dataBuf += 24;
1615       break;
1616     }
1617   }
1618   else if (encodingMode == 1) {
1619     switch (dataMode) {
1620     case TrackData::AUDIO:
1621       offset = AUDIO_BLOCK_LEN;
1622       break;
1623     case TrackData::MODE0:
1624       offset = MODE0_BLOCK_LEN;
1625       break;
1626     case TrackData::MODE1:
1627       offset = MODE1_BLOCK_LEN;
1628       break;
1629     case TrackData::MODE1_RAW:
1630       offset = MODE1_BLOCK_LEN;
1631       break;
1632     case TrackData::MODE2:
1633     case TrackData::MODE2_FORM_MIX:
1634       offset = MODE2_BLOCK_LEN;
1635       break;
1636     case TrackData::MODE2_FORM1:
1637     case TrackData::MODE2_FORM2:
1638       offset = MODE2_BLOCK_LEN;
1639       memset(dataBuf, 0, MODE2_BLOCK_LEN);
1640       dataBuf += 8; // reserve space for sub-header
1641       break;
1642     case TrackData::MODE2_RAW:
1643       offset = MODE2_BLOCK_LEN;
1644       break;
1645     }
1646   }
1647 
1648   // gather one block of data, block length depends on 'dataMode'
1649   while (count > 0) {
1650     if (track_->audioCutMode())
1651       actLen = reader.readData(buf + nread, count);
1652     else
1653       actLen = reader.readData((Sample *)(dataBuf + nread), count);
1654 
1655     if (actLen < 0) // indicates read error
1656       return 0;
1657 
1658     if (actLen != count) {
1659       // end of data in sub-track reached, skip to next sub-track
1660       readSubTrack_ = readSubTrack_->next_;
1661 
1662       // next sub-track must exist since requested length match available data
1663       assert(readSubTrack_ != NULL);
1664 
1665       // mode of next sub-track must match, this is ensured in 'update()'.
1666       assert(readSubTrack_->mode() == dataMode);
1667       assert(readSubTrack_->subChannelMode() == subChanMode);
1668 
1669       reader.init(readSubTrack_);
1670       if (reader.openData() != 0) {
1671 	return 0;
1672       }
1673     }
1674 
1675     count -= actLen;
1676     nread += actLen;
1677   }
1678 
1679   if (subChannelDataLen > 0) {
1680     char *subChannelSourceBuf = dataBuf + blen - subChannelDataLen;
1681 
1682     // save sub-channel data for later processing
1683     memcpy(subChanData, subChannelSourceBuf, subChannelDataLen);
1684     memset(subChannelSourceBuf, 0, subChannelDataLen);
1685   }
1686 
1687   unsigned char *encBuf = (unsigned char *)buf;
1688 
1689   if (encodingMode == 0) {
1690     // encode data block according to 'dataMode'
1691 
1692     switch (dataMode) {
1693     case TrackData::AUDIO:
1694       break;
1695     case TrackData::MODE0:
1696       lec_encode_mode0_sector(lba, encBuf);
1697       lec_scramble(encBuf);
1698       break;
1699     case TrackData::MODE1:
1700       lec_encode_mode1_sector(lba, encBuf);
1701       lec_scramble(encBuf);
1702       break;
1703     case TrackData::MODE1_RAW:
1704       {
1705 	Msf m(lba);
1706 
1707 	if (int2bcd(m.min()) != encBuf[12] ||
1708 	    int2bcd(m.sec()) != encBuf[13] ||
1709 	    int2bcd(m.frac()) != encBuf[14]) {
1710 	  // sector address mismatch -> rebuild L-EC since it covers the header
1711 	  lec_encode_mode1_sector(lba, encBuf);
1712 	}
1713 
1714 	lec_scramble(encBuf);
1715       }
1716       break;
1717     case TrackData::MODE2:
1718       lec_encode_mode2_sector(lba, encBuf);
1719       lec_scramble(encBuf);
1720       break;
1721     case TrackData::MODE2_FORM1:
1722       lec_encode_mode2_form1_sector(lba, encBuf);
1723       lec_scramble(encBuf);
1724       break;
1725     case TrackData::MODE2_FORM2:
1726       lec_encode_mode2_form2_sector(lba, encBuf);
1727       lec_scramble(encBuf);
1728       break;
1729     case TrackData::MODE2_FORM_MIX:
1730       if ((encBuf[16+2] & 0x20) != 0)
1731 	lec_encode_mode2_form2_sector(lba, encBuf);
1732       else
1733 	lec_encode_mode2_form1_sector(lba, encBuf);
1734 
1735       lec_scramble(encBuf);
1736       break;
1737     case TrackData::MODE2_RAW:
1738       {
1739 	Msf m(lba);
1740 
1741 	// L-EC does not cover sector header so it is relocatable
1742 	// just update the sector address in the header
1743 	encBuf[12] = int2bcd(m.min());
1744 	encBuf[13] = int2bcd(m.sec());
1745 	encBuf[14] = int2bcd(m.frac());
1746 
1747 	lec_scramble(encBuf);
1748       }
1749       break;
1750     }
1751   }
1752   else if (encodingMode == 1) {
1753     switch (dataMode) {
1754     case TrackData::MODE2_FORM2:
1755       // add sub header for data form 2 sectors
1756       encBuf[2] = 0x20;
1757       encBuf[6] = 0x20;
1758       break;
1759     case TrackData::MODE1_RAW:
1760       // strip off sync and header
1761       memmove(encBuf, encBuf + 16, MODE1_BLOCK_LEN);
1762       break;
1763     case TrackData::MODE2_RAW:
1764       // strip off sync and header
1765       memmove(encBuf, encBuf + 16, MODE2_BLOCK_LEN);
1766       break;
1767 
1768     default:
1769       break;
1770     }
1771   }
1772 
1773   // encode R-W sub-channel data
1774   switch (subChanMode) {
1775   case TrackData::SUBCHAN_NONE:
1776     break;
1777   case TrackData::SUBCHAN_RW:
1778     if (subChanEncodingMode == 1) {
1779       /*do_encode_sub((unsigned char*)subChanData, 1, 1,
1780 		    &subChanDelayLineIndex_, subChanDelayLine_);
1781       */
1782     }
1783     break;
1784 
1785   case TrackData::SUBCHAN_RW_RAW:
1786     if (subChanEncodingMode == 0) {
1787       // to be done
1788     }
1789     break;
1790   }
1791 
1792   if (subChannelDataLen > 0) {
1793     char *subChannelTargetBuf = (char *)buf + offset;
1794 
1795     memcpy(subChannelTargetBuf, subChanData, subChannelDataLen);
1796   }
1797 
1798   return (offset + subChannelDataLen);
1799 }
1800 
readTrackData(Sample * buf,long len)1801 long TrackReader::readTrackData(Sample *buf, long len)
1802 {
1803   long actLen;
1804   long count = len;
1805   long nread = 0;
1806 
1807   while (count > 0) {
1808     actLen = reader.readData(buf + nread, count);
1809 
1810     if (actLen < 0) {
1811       return -1;
1812     }
1813 
1814     if (actLen != count) {
1815       // end of audio data in sub-track reached, skip to next sub-track
1816       readSubTrack_ = readSubTrack_->next_;
1817 
1818       // next sub-track must exists since requested length match available data
1819       assert(readSubTrack_ != NULL);
1820 
1821       reader.init(readSubTrack_);
1822       if (reader.openData() != 0) {
1823 	return -1;
1824       }
1825     }
1826 
1827     count -= actLen;
1828 
1829     if (track_->audioCutMode())
1830       nread += actLen;
1831     else
1832       nread += actLen / SAMPLE_LEN;
1833   }
1834 
1835   return len;
1836 }
1837 
1838 // Seeks to specified sample.
1839 // return: 0: OK
1840 //        10: sample out of range
1841 //        return code of 'TrackData::openData()'
seekSample(unsigned long sample)1842 int TrackReader::seekSample(unsigned long sample)
1843 {
1844   int ret;
1845   unsigned long offset;
1846 
1847   assert(open_ != 0);
1848 
1849   if (track_->audioCutMode() == 0) {
1850     // all lengths are in byte units -> convert requested sample to a byte
1851     // offset
1852 
1853     // first determine the block which contains the requested sample
1854     unsigned long block = sample / SAMPLES_PER_BLOCK;
1855 
1856     // byte offset into block
1857     unsigned long boffset = (sample % SAMPLES_PER_BLOCK) * SAMPLE_LEN;
1858 
1859 
1860     unsigned long blen = TrackData::dataBlockSize(track_->type(),
1861 						  track_->subChannelType());
1862 
1863     offset = block * blen + boffset;
1864   }
1865   else {
1866     offset = sample;
1867   }
1868 
1869   // find sub track containing 'sample'
1870   SubTrack *st = track_->findSubTrack(offset);
1871 
1872   if (st == NULL)
1873     return 10;
1874 
1875   // open sub track if necessary
1876   if (readSubTrack_ != st) {
1877     readSubTrack_ = st;
1878     reader.init(readSubTrack_);
1879 
1880     if ((ret = reader.openData()) != 0)
1881       return ret;
1882   }
1883 
1884   assert(offset >= readSubTrack_->start());
1885 
1886   unsigned long stOffset = offset - readSubTrack_->start();
1887 
1888   // seek in sub track
1889   if ((ret = reader.seekSample(stOffset)) != 0)
1890     return ret;
1891 
1892   readPosSample_ = sample;
1893 
1894   return 0;
1895 }
1896 
readSamples(Sample * buf,long len)1897 long TrackReader::readSamples(Sample *buf, long len)
1898 {
1899   long ret;
1900   long i;
1901   assert(open_ != 0);
1902 
1903   if (readPosSample_ + (unsigned long)len > track_->length_.samples()) {
1904     if ((len = track_->length_.samples() - readPosSample_) <= 0) {
1905       return 0;
1906     }
1907   }
1908 
1909   if (track_->type() == TrackData::AUDIO) {
1910     if (track_->audioCutMode() == 1) {
1911       if ((ret = readTrackData(buf, len)) > 0) {
1912 	readPosSample_ += ret;
1913       }
1914     }
1915     else {
1916       long subChanLen = TrackData::subChannelSize(track_->subChannelType());
1917       char subChanBuf[MAX_SUBCHANNEL_LEN];
1918       ret = 0;
1919 
1920       while (len > 0) {
1921 	long burst =
1922 	  SAMPLES_PER_BLOCK - (readPosSample_ % SAMPLES_PER_BLOCK);
1923 	int fullBurst = 0;
1924 
1925 	if (burst > len)
1926 	  burst = len;
1927 	else
1928 	  fullBurst = 1;
1929 
1930 	if (readTrackData(buf, burst * SAMPLE_LEN) <= 0)
1931 	  return -1;
1932 
1933 	buf += burst;
1934 
1935 	len -= burst;
1936 	readPosSample_ += burst;
1937 	ret += burst;
1938 
1939 	if (subChanLen > 0 && fullBurst &&
1940 	    (unsigned long)readPosSample_ < track_->length_.samples()) {
1941 	  if (readTrackData((Sample*)subChanBuf, subChanLen) < 0)
1942 	    return -1;
1943 	}
1944       }
1945     }
1946   }
1947   else {
1948     for (i = 0; i < len; i++) {
1949       buf[i].left(16000);
1950       buf[i].right(16000);
1951     }
1952     readPosSample_ += len;
1953     ret = len;
1954   }
1955 
1956   return ret;
1957 }
1958 
curFilename()1959 const char* TrackReader::curFilename()
1960 {
1961   const TrackData* td = reader.trackData();
1962 
1963   if (td)
1964     return td->filename();
1965   else
1966     return NULL;
1967 }
1968 
SubTrackIterator(const Track * t)1969 SubTrackIterator::SubTrackIterator(const Track *t)
1970 {
1971   track_ = t;
1972   iterator_ = NULL;
1973 }
1974 
1975 
~SubTrackIterator()1976 SubTrackIterator::~SubTrackIterator()
1977 {
1978   track_ = NULL;
1979   iterator_ = NULL;
1980 }
1981 
first()1982 const SubTrack *SubTrackIterator::first()
1983 {
1984   iterator_ = track_->subTracks_;
1985 
1986   return next();
1987 }
1988 
next()1989 const SubTrack *SubTrackIterator::next()
1990 {
1991   if (iterator_ != NULL) {
1992     SubTrack *s = iterator_;
1993 
1994     iterator_ = iterator_->next_;
1995     return s;
1996   }
1997   else {
1998     return NULL;
1999   }
2000 }
2001 
2002