Bringing ChocolateCaste-0.7 into the main branch.
[AROS-Contrib.git] / FryingPan / Optical / CDText.cpp
blob3310379edae13c1e5a0a8670292b54e27095caaf
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 "CDText.h"
21 #include <LibC/LibC.h>
22 #include <Generic/Debug.h>
24 CDText::CDText(const IOptItem* i) :
25 crc(SumCRC::CRC_16_CCITT)
27 currentBlock = Blk_Unknown;
28 cdText = false;
29 currentPackNo = 0;
30 currentOffset = 0;
31 currentTrack = 0;
32 currentByte = 0;
34 memset(&size, 0, sizeof(size));
36 if (i->getItemType() != Item_Disc)
37 return;
39 if (i->getChildCount() == 0)
40 return;
42 cdText |= i->getChild(0)->hasCDText();
44 addBlockData(Blk_Title, (uint8*)i->getChild(0)->getCDTTitle(), strlen(i->getChild(0)->getCDTTitle())+1);
45 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
47 cdText |= i->getChild(0)->getChild(tno)->hasCDText();
49 addBlockData(Blk_Title,
50 (uint8*)i->getChild(0)->getChild(tno)->getCDTTitle(),
51 strlen(i->getChild(0)->getChild(tno)->getCDTTitle())+1);
54 addBlockData(Blk_Performer, (uint8*)i->getChild(0)->getCDTArtist(), strlen(i->getChild(0)->getCDTArtist())+1);
55 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
57 addBlockData(Blk_Performer,
58 (uint8*)i->getChild(0)->getChild(tno)->getCDTArtist(),
59 strlen(i->getChild(0)->getChild(tno)->getCDTArtist())+1);
62 addBlockData(Blk_SongWriter, (uint8*)i->getChild(0)->getCDTLyrics(), strlen(i->getChild(0)->getCDTLyrics())+1);
63 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
65 addBlockData(Blk_SongWriter,
66 (uint8*)i->getChild(0)->getChild(tno)->getCDTLyrics(),
67 strlen(i->getChild(0)->getChild(tno)->getCDTLyrics())+1);
70 addBlockData(Blk_Composer, (uint8*)i->getChild(0)->getCDTComposer(), strlen(i->getChild(0)->getCDTComposer())+1);
71 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
73 addBlockData(Blk_Composer,
74 (uint8*)i->getChild(0)->getChild(tno)->getCDTComposer(),
75 strlen(i->getChild(0)->getChild(tno)->getCDTComposer())+1);
78 addBlockData(Blk_Arranger, (uint8*)i->getChild(0)->getCDTDirector(), strlen(i->getChild(0)->getCDTDirector())+1);
79 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
81 addBlockData(Blk_Arranger,
82 (uint8*)i->getChild(0)->getChild(tno)->getCDTDirector(),
83 strlen(i->getChild(0)->getChild(tno)->getCDTDirector())+1);
86 addBlockData(Blk_Message, (uint8*)i->getChild(0)->getCDTMessage(), strlen(i->getChild(0)->getCDTMessage())+1);
87 for (int tno=0; tno<i->getChild(0)->getChildCount(); tno++)
89 addBlockData(Blk_Message,
90 (uint8*)i->getChild(0)->getChild(tno)->getCDTMessage(),
91 strlen(i->getChild(0)->getChild(tno)->getCDTMessage())+1);
94 closePack();
97 * we want to build size info here. now some rules:
98 * - the total size of cdtext block is what-we-got-so-far + 2 (= id of the last block).
99 * - size info always goes last because it's easier to compute :P
100 * - we fill in some table (initially filled with 0s) and push it to cdtext.
101 * the resulting array can be written almost directly to cd. we need to make
102 * the buffer n*96 bytes big and copy our data there (it's easy), then just tell drive
103 * to generate the pad data for us. that's it %]
106 size.charCode = Chr_ISO8859_1;
107 size.firstTrack = i->getChild(0)->getChild(0)->getItemNumber();
108 size.lastTrack = i->getChild(0)->getChild(-1)->getItemNumber();
109 size.copyright = 0;
110 size.lastSeqNum[0] = currentPackNo+2;
111 size.languages[0] = Lng_English;
112 addBlockData(Blk_Size, (uint8*)&size, sizeof(size));
115 CDText::~CDText()
119 void CDText::addBlockData(Block b, uint8 *data, int16 size)
121 if (b != currentBlock)
123 closePack();
124 currentTrack = 0;
125 currentByte = 0;
126 currentOffset = 0;
127 currentBlock = b;
130 ASSERT(currentOffset <= 12);
132 if (currentOffset == 12)
134 currentOffset = 0;
137 if (currentOffset == 0)
139 currentPack.block = b;
140 currentPack.blockTrack = currentTrack;
141 currentPack.totalPack = currentPackNo++;
142 currentPack.charPos = currentByte;
145 while ((currentOffset < 12) && (size--))
147 currentPack.data[currentOffset++] = *data++;
148 if ((b >= Blk_Title) && (b <= Blk_Message))
149 currentByte++;
152 if (currentOffset == 12)
154 closePack();
157 if (size > 0)
159 if (b >= Blk_DiscID)
160 currentTrack++;
161 addBlockData(b, data, size);
163 else
165 currentTrack++;
166 currentByte = 0;
170 void CDText::closePack()
172 if (currentOffset == 0)
173 return;
175 while (currentOffset < 12)
176 currentPack.data[currentOffset++] = 0;
178 crc.Initialize();
179 crc.Update((uint8*)&currentPack, 16);
180 crc.Finalize();
181 currentPack.crc16[0] = ~((crc.GetSum() & 0xff00) >> 8);
182 currentPack.crc16[1] = ~(crc.GetSum() & 0xff);
183 packs << currentPack;
185 if (currentBlock == Blk_Size)
187 size.packsCount[Blk_Size - 0x80] = 3;
189 else
191 size.packsCount[currentBlock - 0x80]++;
194 currentOffset = 0;
197 void CDText::printReport(DbgHandler* __dbg)
199 for (int i=0; i<packs.Count(); i++)
201 _D(Lvl_Info, "%08ld: %02lx %02lx %02lx %02lx: %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx %02lx | %02lx %02lx",
203 packs[i].block,
204 packs[i].blockTrack,
205 packs[i].totalPack,
206 packs[i].charPos,
207 packs[i].data[0], packs[i].data[1], packs[i].data[2], packs[i].data[3], packs[i].data[4], packs[i].data[5],
208 packs[i].data[6], packs[i].data[7], packs[i].data[8], packs[i].data[9], packs[i].data[10], packs[i].data[11],
209 packs[i].crc16[0], packs[i].crc16[1]);
213 bool CDText::hasCDText()
215 return cdText;
218 bool CDText::getDataBuffer(uint8*& tgt, int32& size)
220 int32 off = 0;
221 uint8 *dat = 0;
223 if (hasCDText() == false)
224 return false;
226 size = 24 * packs.Count() + 95;
227 size = (size / 96)*96;
229 tgt = new uint8[size];
230 for (int i=0; i<packs.Count(); i++)
232 dat = (uint8*)&packs[i];
233 for (int j=0; j<6; j++)
235 tgt[off++] = (dat[3*j] >> 2) & 0x3f;
236 tgt[off++] = ((dat[3*j]<< 4) | (dat[3*j+1] >> 4)) & 0x3f;
237 tgt[off++] = ((dat[3*j+1]<< 2) | (dat[3*j+2] >> 6)) & 0x3f;
238 tgt[off++] = (dat[3*j+2]) & 0x3f;
242 while (off < size)
243 tgt[off++] = 0;
245 return true;