Wno-implicit-function-declaration no longer needed
[AROS-Contrib.git] / FryingPan / DTLib / rNRGSession.cpp
blob7a19fae08d687fd5995a1c1b6b6ada55be2e0082
1 /*
2 * FryingPan - Amiga CD/DVD Recording Software (User Interface and supporting Libraries only)
3 * Copyright (C) 2001-2011 Tomasz Wiszkowski Tomasz.Wiszkowski at gmail.com
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 2.1
8 * of the License, or (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 Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "rNRGSession.h"
21 #include <Generic/LibrarySpool.h>
22 #include <libclass/dos.h>
23 #include <Optical/IOptItem.h>
24 #include "Main.h"
26 #ifndef MAKE_ID
27 #define MAKE_ID(a,b,c,d) ((((ULONG)(a)) << 24) | \
28 (((ULONG)(b)) << 16) | \
29 (((ULONG)(c)) << 8) | \
30 (((ULONG)(d)) << 0))
31 #endif
33 class file
35 public:
36 enum filetype
38 Type_Unknown,
39 Type_Intel,
40 Type_Motorola,
41 Type_Wave,
42 Type_AIFF,
43 Type_MP3
46 protected:
47 String filename;
48 BPTR fileptr;
50 private:
51 file()
53 fileptr = 0;
54 filename = "";
57 file(const file&) {};
59 public:
61 static file *newFile(const String &filename)
63 BPTR fileptr;
64 file *f;
66 fileptr = DOS->Open(filename.Data(), MODE_OLDFILE);
67 if (fileptr == 0)
68 return 0;
70 f = new file;
71 f->filename = filename;
72 f->fileptr = fileptr;
74 return f;
77 ~file()
79 if (fileptr != 0)
80 DOS->Close(fileptr);
81 fileptr = 0;
84 const String& getFileName() const
86 return filename;
89 void seek(uint32 offset) const
91 DOS->Seek(fileptr, offset, OFFSET_BEGINNING);
94 uint32 read(void* mem, uint32 len) const
96 return DOS->Read(fileptr, mem, len);
99 BPTR getBPTR() const
101 return fileptr;
105 class index
107 uint16 num; // index number
108 uint32 loc; // boundary: start
109 uint32 cnt; // and count
111 index()
113 num = 0;
114 loc = 0;
115 cnt = 0;
117 public:
119 static index *newIndex(uint16 number, uint32 location)
121 index *i = new index();
123 i->num = (number >> 4) * 10 + (number & 15);
124 i->loc = location;
125 i->cnt = 0xffffffff;
127 return i;
130 void setEndAddress(uint32 scnt)
132 cnt = scnt - loc;
135 uint32 getSecCnt() const
137 return cnt;
140 uint32 getLocation() const
142 return loc;
145 void setLocation(uint32 l)
147 loc = l;
150 uint32 getNumber() const
152 return num;
155 void fillItem(IOptItem* item)
157 item->setStartAddress(loc);
158 item->setItemNumber(num);
159 item->setDataBlockCount(cnt);
162 bool isValid() const
164 return (cnt != 0);
168 class track
170 EDataType type; // type of data
171 uint32 flags; // additional flags (like "RAW")
172 uint16 secsize; // resulting from the two above fields
173 uint16 pregap; // in sectors
174 String isrc; // ISRC number
175 int16 number; // track number
176 VectorT<index*> indices; // indices
178 String arranger; // CDText
179 String composer;
180 String performer;
181 String message;
182 String title;
183 String songwriter;
185 uint64 filepos;
186 uint64 length;
187 int64 currpos;
189 file *f;
191 track()
193 type = Data_Unknown;
194 flags = 0;
195 secsize = 2352;
196 pregap = 0;
197 number = 0;
200 public:
201 static track* newTrack(file *f, int32 num)
203 track *nt = new track;
204 nt->f = f;
205 nt->number = (num >> 4) * 10 + (num & 15);
206 return nt;
209 const file *getFile() const
211 return f;
214 void setType(EDataType dt)
216 type = dt;
219 void setSectorSize(uint16 size)
221 secsize = size;
224 void setDataStart(uint64 pos)
226 filepos = pos;
229 void setDataEnd(uint64 pos)
231 length = pos - filepos;
234 void setDataMode2(uint8 mode)
238 EDataType getType() const
240 return type;
243 void debug(DbgHandler *__dbg)
245 if (__dbg == 0)
246 return;
248 _D(Lvl_Info, "Number: %ld", number);
249 _D(Lvl_Info, "File type: %ld", type);
250 _D(Lvl_Info, "Flags: %ld", flags);
251 _D(Lvl_Info, "Sector Size: %ld", secsize);
252 _D(Lvl_Info, "PreGap: %ld", pregap);
253 _D(Lvl_Info, "ISRC: %s", (int32)isrc.Data());
254 _D(Lvl_Info, "Arranger: %s", (int32)arranger.Data());
255 _D(Lvl_Info, "Composer: %s", (int32)composer.Data());
256 _D(Lvl_Info, "Performer: %s", (int32)performer.Data());
257 _D(Lvl_Info, "Message: %s", (int32)message.Data());
258 _D(Lvl_Info, "Title: %s", (int32)title.Data());
259 _D(Lvl_Info, "Song Writer: %s", (int32)songwriter.Data());
261 _D(Lvl_Info, "===");
264 void setArranger(const String &s)
266 arranger = s;
269 void setComposer(const String &s)
271 composer = s;
274 void setPerformer(const String &s)
276 performer = s;
279 void setMessage(const String &s)
281 message = s;
284 void setTitle(const String &s)
286 title = s;
289 void setSongWriter(const String &s)
291 songwriter = s;
294 void setPreGap(int32 gap)
296 pregap = gap;
299 int32 getPreGap() const
301 return pregap;
304 int32 getNumber() const
306 return number;
309 void setISRC(const String &s)
311 isrc = s;
314 void addIndex(index *i)
316 indices << i;
319 index *getIndex(int32 i)
321 return indices[i];
324 int32 getIndexCount()
326 return indices.Count();
329 int32 getSectorSize() const
331 return secsize;
334 void fillItem(IOptItem *item)
336 uint32 len = 0;
338 item->setCDTDirector(arranger);
339 item->setCDTComposer(composer);
340 item->setCDTArtist(performer);
341 item->setCDTMessage(message);
342 item->setCDTTitle(title);
343 item->setCDTLyrics(songwriter);
344 item->setFlags(flags);
345 item->setSectorSize(secsize);
346 item->setPreGapSize(pregap);
347 item->setItemNumber(number);
348 item->setDataType(type);
349 item->setSectorSize(secsize);
351 item->setStartAddress(indices[0]->getLocation() - pregap);
352 for (int32 i=0; i<indices.Count(); i++)
354 if (indices[i]->isValid() == false)
355 continue;
357 IOptItem *indx = item->addChild();
359 indices[i]->fillItem(indx);
360 len += indices[i]->getSecCnt();
362 item->setDataBlockCount(len);
365 void setUp()
367 currpos = -1;
370 uint32 read(void* &mem, uint32 len)
372 len *= secsize;
374 if (currpos == -1)
376 f->seek(filepos);
377 currpos = 0;
379 else if ((uint64)currpos >= length)
380 return 0;
382 len = len < (length - currpos) ? len : (length - currpos);
383 f->read(mem, len);
384 mem = &((char*)mem)[len];
385 currpos += len;
387 return len / secsize;
393 struct nrg_etnf
395 uint32 start;
396 uint32 length;
397 uint32 type; // 0 = mode1, 1 = ?, 2 = mode2form1, 3 = mixed mode2
398 uint32 secpos; // without pregaps
399 uint32 dummy; // whatever.
402 struct nrg_etn2
404 uint64 start;
405 uint64 length;
406 uint32 type;
407 uint32 secpos; // as above
408 uint64 dummy;
411 struct nrg_cuex
413 uint8 adr_ctl; //
414 uint8 track; // BCD track number
415 uint8 index; // index (bcd?)
416 uint8 res; // ???
417 uint32 sector; // ...
420 struct nrg_daoi
422 uint32 dummy;
423 uint8 mcn[14];
424 uint8 disc_mode;
425 uint8 one1;
426 uint8 first_track;
427 uint8 last_track;
428 struct dao_track
430 uint8 pad[12];
431 uint16 secsize;
432 uint8 mode;
433 uint8 zero1;
434 uint8 zero2;
435 uint8 type;
436 uint32 pregap;
437 uint32 offset;
438 uint32 end;
439 } track[0];
442 struct nrg_daox
444 uint32 dummy;
445 uint8 mcn[14];
446 uint8 disc_mode;
447 uint8 one1;
448 uint8 first_track;
449 uint8 last_track;
450 struct dao_track
452 uint8 pad[12];
453 uint16 secsize;
454 uint8 mode;
455 uint8 zero1;
456 uint8 zero2;
457 uint8 type;
458 uint64 pregap; // pregap data start
459 uint64 offset; // normal data start
460 uint64 end; // normal data end
461 } track[0];
465 rNRGSession::rNRGSession(const char* sFileName, EDtError &rc)
467 _createDebug(true, "rNRGSession");
468 name = sFileName;
469 f = 0;
470 analyse(sFileName, rc);
473 rNRGSession::~rNRGSession()
475 tracks.ForEach(&freeTrack);
477 if (f != 0)
478 delete f;
479 f = 0;
481 _destroyDebug();
484 bool rNRGSession::freeTrack(track* const& t)
486 delete t;
487 return true;
490 IFileReader* rNRGSession::openRead(const char* sFile, EDtError &rc)
492 IFileReader *out = 0;
494 checkFile(sFile, rc);
495 if (rc == DT_OK)
497 out = new rNRGSession(sFile, rc);
498 if (rc != DT_OK)
500 out->dispose();
501 out = 0;
504 return out;
507 const char* rNRGSession::getName()
509 return static_getName();
512 bool rNRGSession::readData(const IOptItem* item, void* mem, int len)
514 _d(Lvl_Info, "%s: reading -> %08lx, %ld, curr trk: %ld; bptr=%lx", (int)__PRETTY_FUNCTION__, (int)mem, len, currtrk, (int)tracks[currtrk]->getFile()->getBPTR());
516 if (item->getItemType() != Item_Track)
518 int32 ret;
520 if (currtrk == tracks.Count())
521 return false;
523 ret = tracks[currtrk]->read(mem, len);
524 if (ret == len)
525 return true;
527 currtrk++;
528 ret += readData(item, mem, len-ret);
530 return true;
532 else
534 ASSERTS(false, "Functionality not yet implemented, sorry.");
535 return false;
539 bool rNRGSession::setUp()
541 _d(Lvl_Info, "%s: seeking all items to the start position...", (int)__PRETTY_FUNCTION__);
543 for (int i=0; i<tracks.Count(); i++)
544 tracks[i]->setUp();
547 f->seek(0);
549 currtrk = 0;
551 return true;
554 bool rNRGSession::analyse(const char* name, EDtError &rc)
556 BPTR fh;
557 bool res=true;
558 uint32 data;
559 uint32 size;
560 nrg_cuex *cue1 = 0;
561 nrg_daoi *dao1 = 0;
562 nrg_daox *dao2 = 0;
564 rc = DT_UnableToOpenFile;
566 fh = DOS->Open(name, MODE_OLDFILE);
567 if (fh == 0)
568 return false;
570 f = file::newFile(name);
572 rc = DT_OK;
574 DOS->Seek(fh, -4, OFFSET_END);
575 DOS->Read(fh, &data, 4);
577 data = L2BE(data);
578 DOS->Seek(fh, data, OFFSET_BEGINNING);
582 DOS->Read(fh, &data, 4);
583 DOS->Read(fh, &size, 4);
584 data = L2BE(data);
585 size = L2BE(size);
586 if (data == MAKE_ID('C','D','T','X'))
588 _d(Lvl_Info, "%s: CDTX Tag", (int)__PRETTY_FUNCTION__);
589 DOS->Seek(fh, size, OFFSET_CURRENT);
591 else if (data == MAKE_ID('C','U','E','X'))
593 _d(Lvl_Info, "%s: CUEX Tag", (int)__PRETTY_FUNCTION__);
594 cue1 = (nrg_cuex*)new char[size];
595 DOS->Read(fh, cue1, size);
597 else if (data == MAKE_ID('C','U','E','S'))
599 _d(Lvl_Info, "%s: CUES Tag", (int)__PRETTY_FUNCTION__);
600 DOS->Seek(fh, size, OFFSET_CURRENT);
602 else if (data == MAKE_ID('D','A','O','X'))
604 _d(Lvl_Info, "%s: DAOX Tag", (int)__PRETTY_FUNCTION__);
605 dao2 = (nrg_daox*)new char[size];
606 DOS->Read(fh, dao2, size);
608 else if (data == MAKE_ID('D','A','O','I'))
610 _d(Lvl_Info, "%s: DAOI Tag", (int)__PRETTY_FUNCTION__);
611 dao1 = (nrg_daoi*)new char[size];
612 DOS->Read(fh, dao1, size);
614 _d(Lvl_Info, "%s: DAOI: ftrk=%ld, ltrk=%ld", (int)__PRETTY_FUNCTION__, dao1->first_track, dao1->last_track);
615 _d(Lvl_Info, "%s: DAOI: MCN=%02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx", (int)__PRETTY_FUNCTION__, dao1->mcn[0], dao1->mcn[1], dao1->mcn[2], dao1->mcn[3], dao1->mcn[4], dao1->mcn[5], dao1->mcn[6], dao1->mcn[7], dao1->mcn[8], dao1->mcn[9], dao1->mcn[10], dao1->mcn[11], dao1->mcn[12], dao1->mcn[13]);
617 for (int i=0; i<=(dao1->last_track-dao1->first_track); i++)
619 _d(Lvl_Info, "%s: DAOI: track=%ld secsize=%ld mode=%ld type=%ld pregap=%lx data=%lx end=%lx",
620 (int)__PRETTY_FUNCTION__,
621 i+dao1->first_track,
622 dao1->track[i].secsize,
623 dao1->track[i].mode,
624 dao1->track[i].type,
625 dao1->track[i].pregap,
626 dao1->track[i].offset,
627 dao1->track[i].end);
630 else if (data == MAKE_ID('E','T','N','F'))
632 _d(Lvl_Info, "%s: ETNF Tag", (int)__PRETTY_FUNCTION__);
633 int32 num = (size / sizeof(nrg_etnf));
634 nrg_etnf *etnf = (nrg_etnf*)new char[size];
635 DOS->Read(fh, etnf, size);
637 for (int i=0; i<num; i++)
639 _d(Lvl_Info, "%s: ETNF: start=%ld length=%ld type=%ld sector=%ld other=%lx", (int)__PRETTY_FUNCTION__, etnf[i].start, etnf[i].length, etnf[i].type, etnf[i].secpos, etnf[i].dummy);
642 delete etnf;
644 else if (data == MAKE_ID('E','T','N','2'))
646 _d(Lvl_Info, "%s: ETN2 Tag", (int)__PRETTY_FUNCTION__);
647 int32 num = (size / sizeof(nrg_etn2));
648 nrg_etn2 *etnf = (nrg_etn2*)new char[size];
649 DOS->Read(fh, etnf, size);
651 for (int i=0; i<num; i++)
653 _d(Lvl_Info, "%s: ETN2: start=%ld length=%ld type=%ld sector=%ld other=%lx", (int)__PRETTY_FUNCTION__, etnf[i].start, etnf[i].length, etnf[i].type, etnf[i].secpos, etnf[i].dummy);
656 delete etnf;
658 else if (data == MAKE_ID('N','E','R','O'))
660 _d(Lvl_Info, "%s: NERO Tag", (int)__PRETTY_FUNCTION__);
661 DOS->Seek(fh, size, OFFSET_CURRENT);
663 else if (data == MAKE_ID('N','E','R','5'))
665 _d(Lvl_Info, "%s: NER5 Tag", (int)__PRETTY_FUNCTION__);
666 DOS->Seek(fh, size, OFFSET_CURRENT);
668 else if (data == MAKE_ID('S','I','N','F'))
670 _d(Lvl_Info, "%s: SINF Tag", (int)__PRETTY_FUNCTION__);
671 DOS->Seek(fh, size, OFFSET_CURRENT);
673 else if (data == MAKE_ID('M','T','Y','P'))
675 _d(Lvl_Info, "%s: MTYP Tag", (int)__PRETTY_FUNCTION__);
676 DOS->Seek(fh, size, OFFSET_CURRENT);
678 else if (data == MAKE_ID('E','N','D','!'))
680 _d(Lvl_Info, "%s: END! Tag", (int)__PRETTY_FUNCTION__);
681 break;
685 while (true);
687 if (res == true)
688 res = buildTrackList(cue1, rc);
689 if ((dao2 != 0) && (res == true))
690 res = updateTrackData(dao2, rc);
691 if ((dao1 != 0) && (res == true))
692 res = updateTrackData(dao2, rc);
694 if (0 != cue1)
695 delete cue1;
696 if (0 != dao1)
697 delete dao1;
698 if (0 != dao2)
699 delete dao2;
701 DOS->Close(fh);
702 return res;
705 bool rNRGSession::buildTrackList(nrg_cuex *cue, EDtError &rc)
707 if (cue == 0)
709 rc = DT_FileFormatNotSupported;
710 return false;
713 for (int i=0;; i++)
715 track *t = 0;
716 index *x = 0;
718 _d(Lvl_Info, "%s: CUEX: type=%02lx track=%02lx adrctl=%02lx res=%02lx sector=%08lx", (int)__PRETTY_FUNCTION__, cue[i].adr_ctl, cue[i].track, cue[i].index, cue[i].res, cue[i].sector);
720 if (cue[i].track == 0)
721 continue;
723 if (tracks.Count() > 0)
724 tracks[-1]->getIndex(-1)->setEndAddress(cue[i].sector);
726 if (cue[i].track == 0xaa)
727 break;
729 for (int j=0; j<tracks.Count(); j++)
731 if (tracks[j]->getNumber() == ((cue[i].track >> 4) * 10 + (cue[i].track & 15)))
733 t = tracks[j];
734 break;
738 if (t == 0)
740 t = track::newTrack(f, cue[i].track);
741 tracks << t;
743 switch (cue[i].adr_ctl & 0xc0)
745 case 0x40:
746 t->setType(Data_Mode1);
747 break;
748 case 0x00:
749 t->setType(Data_Audio);
750 break;
751 default:
752 rc = DT_FileFormatNotSupported;
753 return false;
757 x = index::newIndex(cue[i].index, cue[i].sector);
758 t->addIndex(x);
762 return true;
765 bool rNRGSession::updateTrackData(struct nrg_daox* dao, EDtError &rc)
767 if (dao == 0)
769 rc = DT_FileFormatNotSupported;
770 return false;
773 _d(Lvl_Info, "%s: DAO: ftrk=%ld, ltrk=%ld", (int)__PRETTY_FUNCTION__, dao->first_track, dao->last_track);
774 _d(Lvl_Info, "%s: DAO: MCN=%02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx", (int)__PRETTY_FUNCTION__, dao->mcn[0], dao->mcn[1], dao->mcn[2], dao->mcn[3], dao->mcn[4], dao->mcn[5], dao->mcn[6], dao->mcn[7], dao->mcn[8], dao->mcn[9], dao->mcn[10], dao->mcn[11], dao->mcn[12], dao->mcn[13]);
776 for (int i=0; i<=(dao->last_track-dao->first_track); i++)
778 track *t = 0;
780 _d(Lvl_Info, "%s: DAO: track=%ld secsize=%ld mode=%ld type=%ld pregap=%lx data=%lx end=%lx",
781 (int)__PRETTY_FUNCTION__,
782 i+dao->first_track,
783 dao->track[i].secsize,
784 dao->track[i].mode,
785 dao->track[i].type,
786 dao->track[i].pregap,
787 dao->track[i].offset,
788 dao->track[i].end);
790 for (int j=0; j<tracks.Count(); j++)
792 if (tracks[j]->getNumber() == (i + dao->first_track))
794 t = tracks[j];
795 break;
799 if (t == 0)
801 rc = DT_FileMalformed;
802 return false;
805 t->setSectorSize(dao->track[i].secsize);
806 switch (dao->track[i].mode)
808 case 0:
809 t->setType(Data_Mode1);
810 break;
811 case 1:
812 t->setType(Data_Mode2Form1);
813 break;
814 case 2:
815 t->setType(Data_Mode2Form2);
816 break;
817 case 3:
818 case 6:
819 t->setType(Data_Mode2);
820 break;
821 case 7:
822 t->setType(Data_Audio);
823 break;
824 default:
825 rc = DT_FileFormatNotSupported;
826 return false;
828 t->setDataStart(dao->track[i].pregap);
829 t->setDataEnd(dao->track[i].end);
830 t->setDataMode2(dao->track[i].mode);
832 _d(Lvl_Info, "%s: Track %ld: %ld - %ld, mode %ld", (int)__PRETTY_FUNCTION__, i, dao->track[i].pregap, dao->track[i].end, dao->track[i].mode);
834 return true;
837 bool rNRGSession::updateTrackData(struct nrg_daoi* dao, EDtError &rc)
839 if (dao == 0)
841 rc = DT_FileFormatNotSupported;
842 return false;
845 _d(Lvl_Info, "%s: DAO: ftrk=%ld, ltrk=%ld", (int)__PRETTY_FUNCTION__, dao->first_track, dao->last_track);
846 _d(Lvl_Info, "%s: DAO: MCN=%02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx", (int)__PRETTY_FUNCTION__, dao->mcn[0], dao->mcn[1], dao->mcn[2], dao->mcn[3], dao->mcn[4], dao->mcn[5], dao->mcn[6], dao->mcn[7], dao->mcn[8], dao->mcn[9], dao->mcn[10], dao->mcn[11], dao->mcn[12], dao->mcn[13]);
848 for (int i=0; i<=(dao->last_track-dao->first_track); i++)
850 track *t = 0;
852 _d(Lvl_Info, "%s: DAO: track=%ld secsize=%ld mode=%ld type=%ld pregap=%lx data=%lx end=%lx",
853 (int)__PRETTY_FUNCTION__,
854 i+dao->first_track,
855 dao->track[i].secsize,
856 dao->track[i].mode,
857 dao->track[i].type,
858 dao->track[i].pregap,
859 dao->track[i].offset,
860 dao->track[i].end);
862 for (int j=0; j<tracks.Count(); j++)
864 if (tracks[j]->getNumber() == (i + dao->first_track))
866 t = tracks[j];
867 break;
871 if (t == 0)
873 rc = DT_FileMalformed;
874 return false;
877 t->setSectorSize(dao->track[i].secsize);
878 switch (dao->track[i].mode)
880 case 0:
881 t->setType(Data_Mode1);
882 break;
883 case 1:
884 t->setType(Data_Mode2Form1);
885 break;
886 case 2:
887 t->setType(Data_Mode2Form2);
888 break;
889 case 3:
890 case 6:
891 t->setType(Data_Mode2);
892 break;
893 case 7:
894 t->setType(Data_Audio);
895 break;
896 default:
897 rc = DT_FileFormatNotSupported;
898 return false;
900 t->setDataStart(dao->track[i].pregap);
901 t->setDataEnd(dao->track[i].end);
902 t->setDataMode2(dao->track[i].mode);
904 return true;
907 void rNRGSession::cleanUp()
911 void rNRGSession::dispose()
913 delete this;
916 bool rNRGSession::isAudio()
918 return static_isAudio();
921 bool rNRGSession::isData()
923 return static_isData();
926 bool rNRGSession::fillOptItem(IOptItem *disc)
929 if (disc->getItemType() != Item_Disc)
930 return false;
932 disc->setFlags(DIF_Disc_MasterizeCD | DIF_Disc_CloseDisc);
933 IOptItem *sess = disc->addChild();
935 sess->setCDTDirector(arranger);
936 sess->setCDTComposer(composer);
937 sess->setCDTArtist(performer);
938 sess->setCDTMessage(message);
939 sess->setCDTTitle(title);
940 sess->setCDTLyrics(songwriter);
942 for (int i=0; i<tracks.Count(); i++)
944 IOptItem *trak = sess->addChild();
945 tracks[i]->fillItem(trak);
947 return true;
950 const char *rNRGSession::getTrackName()
952 return static_getName();
955 uint32 rNRGSession::getBlockCount()
957 return blockCount;
960 uint16 rNRGSession::getBlockSize()
962 return blockSize;
965 const char *rNRGSession::static_getName()
967 return "Nero Burning ROM Image";
970 bool rNRGSession::static_isAudio()
972 return false;
975 bool rNRGSession::static_isData()
977 return false;
980 bool rNRGSession::static_isSession()
982 return true;
985 bool rNRGSession::checkFile(const char* file, EDtError &rc)
987 BPTR fh;
988 uint32 data;
989 uint32 size;
990 int res = true;
992 rc = DT_UnableToOpenFile;
994 fh = DOS->Open(const_cast<char*>(file), MODE_OLDFILE);
995 if (0 == fh)
996 return false;
998 rc = DT_OK;
1000 DOS->Seek(fh, -4, OFFSET_END);
1001 size = DOS->Seek(fh, 0, OFFSET_CURRENT) + 4; // fancy, innit
1003 DOS->Read(fh, &data, 4);
1004 data = L2BE(data);
1005 if ((size - data) > 4096)
1006 return false;
1008 DOS->Seek(fh, data, OFFSET_BEGINNING);
1012 DOS->Read(fh, &data, 4);
1013 data = L2BE(data);
1014 if ((data == MAKE_ID('C','D','T','X')) ||
1015 (data == MAKE_ID('C','U','E','X')) ||
1016 (data == MAKE_ID('C','U','E','S')) ||
1017 (data == MAKE_ID('D','A','O','X')) ||
1018 (data == MAKE_ID('D','A','O','I')) ||
1019 (data == MAKE_ID('E','T','N','F')) ||
1020 (data == MAKE_ID('E','T','N','2')) ||
1021 (data == MAKE_ID('N','E','R','O')) ||
1022 (data == MAKE_ID('N','E','R','5')) ||
1023 (data == MAKE_ID('S','I','N','F')) ||
1024 (data == MAKE_ID('M','T','Y','P')))
1026 DOS->Read(fh, &data, 4);
1027 data = L2BE(data);
1028 DOS->Seek(fh, data, OFFSET_CURRENT);
1030 else if (data == MAKE_ID('E','N','D','!'))
1032 break;
1034 else
1036 res = false;
1037 break;
1040 while (true);
1042 DOS->Close(fh);
1043 return res;
1046 DbgHandler* rNRGSession::getDebug()
1048 return dbg;
1051 void rNRGSession::setDebug(DbgHandler* nd)
1053 dbg = nd;