📄 cloneburnerdlg.cpp
字号:
dlg.DestroyWindow();
EnableWindow();
BringWindowToTop();
SetActiveWindow();
m_comboDevices.SelectString(-1, m_arDeviceNames[m_nDevice]);
SetDeviceControls(m_nDevice);
}
void CCloneBurnerDlg::OnCbnSelchangeComboDevices()
{
int nCurSel = m_comboDevices.GetCurSel();
if (-1 != nCurSel)
SetDeviceControls(nCurSel);
}
void CCloneBurnerDlg::OnBnClickedButtonBrowse()
{
TCHAR* szPath=new TCHAR[MAX_PATH];
szPath[0] = _T('\0');
BROWSEINFO bi;
bi.hwndOwner = m_hWnd;
bi.pidlRoot = NULL;
bi.lpszTitle = _T("Select a source folder");
bi.ulFlags = BIF_EDITBOX;
bi.lpfn = NULL;
bi.lParam = NULL;
bi.pszDisplayName = szPath;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
if (NULL == pidl)
{
delete [] szPath;
return;
}
::SHGetPathFromIDList(pidl, szPath);
m_strRootDir = szPath;
m_editRootDir.SetWindowText(m_strRootDir);
delete [] szPath;
}
// Erasing/writing thread...
DWORD CCloneBurnerDlg::ThreadProc(LPVOID pParam)
{
CoInitialize(NULL);
CCloneBurnerDlg* pThis=(CCloneBurnerDlg* )pParam;
return pThis->Process();
}
int CCloneBurnerDlg::GetInternalCacheStatus()
{
int nUsedCachePercent = 0;
if (m_pDevice)
{
double dd = (double) m_pDevice->GetInternalCacheUsedSpace();
dd = dd * 100.0 / (double)m_pDevice->GetInternalCacheCapacity();
nUsedCachePercent = (int)dd;
// ATLTRACE("CACHE USAGE: %d\n", nUsedCachePercent);
}
return nUsedCachePercent;
}
void CCloneBurnerDlg::NotifyProgress(const TCHAR * pszText)
{
EnterCriticalSection(&m_cs);
m_notify.strText = pszText;
m_notify.nUsedCachePercent = GetInternalCacheStatus();
LeaveCriticalSection(&m_cs);
SetEvent(m_hNotifyEvent);
}
void CCloneBurnerDlg::NotifyProgress(int nProgress)
{
EnterCriticalSection(&m_cs);
m_notify.nPercent = nProgress;
m_notify.nUsedCachePercent = GetInternalCacheStatus();
LeaveCriticalSection(&m_cs);
SetEvent(m_hNotifyEvent);
}
DWORD CCloneBurnerDlg::Process()
{
SetEvent(m_hOperationStartedEvent);
IDevice12 * pDevice=(IDevice12 *)m_pEnumerator->GetItem(m_arIndices[m_nDevice]);
m_pDevice = pDevice;
if (!m_pDevice)
return -1;
if (m_ctx.bErasing)
{
pDevice->SetCurrentSpeeds(32, m_ctx.nSpeed);
pDevice->Erase(m_ctx.bQuick);
pDevice->Release();
m_pDevice = NULL;
return 0;
}
m_pDevice->SetCurrentSpeeds(32, m_ctx.nSpeed);
CString strIniFile = m_strRootDir + "/" + "IMAGE.CCD";
CString strDataFile = m_strRootDir + "/" + "IMAGE.IMG";
CString strSubFile = m_strRootDir + "/" + "IMAGE.SUB";
// Load session description from the CCD file
NotifyProgress("Preparing tracks...");
ISession * ps = LoadSessionLayout(strIniFile, strDataFile);
if (!ps)
{
pDevice->Release();
m_pDevice = NULL;
AfxMessageBox("Could not load session layout.");
return 0;
}
if (0 == ps->GetTracksCount() )
{
CString sMessage;
sMessage.Format("Could not load session layout from %s.", strIniFile);
AfxMessageBox(sMessage);
pDevice->Release();
m_pDevice = NULL;
return 0;
}
// Burn the session to the CD
Burn(ps, strDataFile, strSubFile);
pDevice->Release();
m_pDevice = NULL;
return 0;
}
DWORD CCloneBurnerDlg::GetSessionLength(ISession * ps)
{
DWORD dwRet = 0;
dwRet = ps->GetLength();
ISession * pNext = NULL;
if (ps->GetNextSession(&pNext))
{
dwRet += GetSessionLength(pNext);
pNext->Release();
}
return dwRet;
}
int CCloneBurnerDlg::GetDataOffset(ETrackType tt)
{
switch (tt)
{
case TT_AUDIO:
return 0;
case TT_MODE0:
return 16;
case TT_MODE1:
return 16;
case TT_MODE2_FORMLESS:
return 16;
case TT_MODE2_FORM1:
case TT_MODE2_MIXED:
return 24;
break;
case TT_MODE2_FORM2:
return 24;
break;
}
return TRUE;
};
void CCloneBurnerDlg::WriteData(ISession * ps, HANDLE hData, HANDLE hSub, EWriteMethod wm)
{
// Get total length of all sessions
DWORD dwTotalBlocks = GetSessionLength(ps);
// Get data file size and verify it is ok
DWORD dwSize = GetFileSize(hData, NULL);
assert(0 == (dwSize % CDDA_BLOCKSIZE));
assert(dwTotalBlocks == dwSize / CDDA_BLOCKSIZE);
// get subchannel file size and verify it is ok
DWORD dwSubSize = GetFileSize(hSub, NULL);
assert(0 == (dwSubSize % PW_CHANNEL_SIZE));
// if sub-channle file is empty, switch to RAW 2352
// let hpCDE generate the sub-channles
if (0 == dwSubSize && WRITE_METHOD_FULL_RAW_DAO == wm)
wm = WRITE_METHOD_RAW_DAO_2352;
NotifyProgress("Writing lead-in ...");
// start session
if (m_pDevice->StartCDSession(m_ctx.bSimulate, ps, wm))
{
NotifyProgress("Writing session ...");
DWORD dwStartBlock = 0;
while (dwStartBlock < dwTotalBlocks)
{
if (m_ctx.bStopRequest)
break;
DWORD dwBlocksAtOnce = min(BLOCKS_AT_ONCE, dwTotalBlocks - dwStartBlock);
LONG lPrevBlockSize = 0;
BYTE * pBuf1 = NULL, * pBuf2 = NULL;
DWORD dw1 = 0, dw2 = 0;
if (m_pDevice->WriteLockBuffer(dwBlocksAtOnce, &pBuf1, &dw1, &pBuf2, &dw2))
{
if (dw1)
{
for (DWORD dw = 0; dw < dw1; dw++)
{
DWORD dwRead;
if (WRITE_METHOD_FULL_RAW_DAO == wm)
{
ReadFile(hData, pBuf1, CDDA_BLOCKSIZE, &dwRead, NULL);
ReadFile(hSub, pBuf1 + CDDA_BLOCKSIZE, PW_CHANNEL_SIZE, &dwRead, NULL);
pBuf1 += CD_RAW_BLOCKSIZE;
}
else if (WRITE_METHOD_RAW_DAO_2352 == wm)
{
ReadFile(hData, pBuf1, CDDA_BLOCKSIZE, &dwRead, NULL);
pBuf1 += CDDA_BLOCKSIZE;
}
else if (WRITE_METHOD_RAW_DAO == wm)
{
// This is a hack to get the user data in the raw block and is used to
// simulate non RAW blocks to demonstrate RAW burning from non RAW blocks
BYTE pRawBuffer[CDDA_BLOCKSIZE];
ReadFile(hData, pRawBuffer, CDDA_BLOCKSIZE, &dwRead, NULL);
// Get user data block size
ETrackType tt = m_pDevice->GetTrackType(pRawBuffer);
LONG lBlockSize = m_pDevice->GetTrackBlockSize(tt);
if (dw == 0)
lPrevBlockSize = lBlockSize;
if (lPrevBlockSize != lBlockSize)
{
// WriteLockBuffer\WriteUnlockBuffer do not support writing blocks of different size at once
dw1 = dw; dw2 = 0;
// move back one block in the file
SetFilePointer(hData, -CDDA_BLOCKSIZE, NULL, FILE_CURRENT);
}
else
{
// same block size
memcpy(pBuf1, pRawBuffer + GetDataOffset(tt), lBlockSize);
pBuf1 += lBlockSize;
}
}
}
}
if (dw2)
{
for (DWORD dw = 0; dw < dw2; dw++)
{
DWORD dwRead;
if (WRITE_METHOD_FULL_RAW_DAO == wm)
{
ReadFile(hData, pBuf2, CDDA_BLOCKSIZE, &dwRead, NULL);
ReadFile(hSub, pBuf2 + CDDA_BLOCKSIZE, PW_CHANNEL_SIZE, &dwRead, NULL);
pBuf2 += CD_RAW_BLOCKSIZE;
}
else if (WRITE_METHOD_RAW_DAO_2352 == wm)
{
ReadFile(hData, pBuf2, CDDA_BLOCKSIZE, &dwRead, NULL);
pBuf2 += CDDA_BLOCKSIZE;
}
else if (WRITE_METHOD_RAW_DAO == wm)
{
// This is a hack to get the user data in the raw block and is used to
// simulate non RAW blocks to demonstrate RAW burning from non RAW blocks
BYTE pRawBuffer[CDDA_BLOCKSIZE];
ReadFile(hData, pRawBuffer, CDDA_BLOCKSIZE, &dwRead, NULL);
// Get user data block size
ETrackType tt = m_pDevice->GetTrackType(pRawBuffer);
LONG lBlockSize = m_pDevice->GetTrackBlockSize(tt);
if (dw1 == 0 && dw == 0)
lPrevBlockSize = lBlockSize;
if (lPrevBlockSize != lBlockSize)
{
// WriteLockBuffer\WriteUnlockBuffer do not support writing blocks of different size at once
dw2 = dw;
// move back one block in the file
SetFilePointer(hData, -CDDA_BLOCKSIZE, NULL, FILE_CURRENT);
}
else
{
// same block size
memcpy(pBuf2, pRawBuffer + GetDataOffset(tt), lBlockSize);
pBuf2 += lBlockSize;
}
}
}
}
m_pDevice->WriteUnlockBuffer(dw1 + dw2);
dwStartBlock += dw1 + dw2;
NotifyProgress((int) ((double) dwStartBlock * 100. / dwTotalBlocks));
}
}
NotifyProgress("Writing lead-out...");
m_pDevice->EndCDSession();
}
else
{
CString sMessage;
sMessage.Format("Unable to initialize device. Error: 0x%X - %s", m_pDevice->GetLastError(), m_pDevice->GetLastErrorDescription());
AfxMessageBox(sMessage);
}
}
BOOL CCloneBurnerDlg::Burn(ISession * ps, LPCTSTR lpDataFilename, LPCTSTR lpSubFilename)
{
HANDLE hData = CreateFile (lpDataFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hData)
return FALSE;
HANDLE hSub = CreateFile (lpSubFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hSub)
{
CloseHandle(hData);
return FALSE;
}
switch(m_ctx.nRawMode)
{
case 0:
WriteData(ps, hData, hSub, WRITE_METHOD_RAW_DAO);
break;
case 1:
WriteData(ps, hData, hSub, WRITE_METHOD_RAW_DAO_2352);
break;
case 2:
WriteData(ps, hData, hSub, WRITE_METHOD_FULL_RAW_DAO);
break;
}
CloseHandle(hSub);
CloseHandle(hData);
if (m_ctx.bEject)
m_pDevice->Eject(TRUE);
return TRUE;
}
ISession * CCloneBurnerDlg::LoadSessionLayout(LPCTSTR lpIniFilename, LPCTSTR lpDataFilename)
{
CIniFile ini;
ini.Initialize(lpIniFilename);
int nSessions = ini.ReadInt(_T("Sessions"), _T("Disc"));
int nTocEntries = ini.ReadInt(_T("TocEntries"), _T("Disc"));
if (0 == nTocEntries || 0 == nSessions)
return FALSE;
// Get all the entries from the ini file
CTOCEntry * pEntries = new CTOCEntry[nTocEntries];
for (int i = 0; i < nTocEntries; i++)
{
pEntries[i].SetEntryIndex(i);
pEntries[i].Serialize(&ini, FALSE);
}
ISession * pFirstSession = NULL;
ISession * ps = NULL;
// Get the first session only, for now
for (int nSessionNumber = 1; nSessionNumber <= nSessions; nSessionNumber++)
{
ISession * psNew = hpCDE::CreateSession();
// link sessions
if (nSessionNumber > 1)
ps->SetNextSession(psNew);
ps = psNew;
// session must be a RAW session
ps->SetType(ST_RAW);
long lLeadoutLba = 0;
long lSessionStartLba = 0;
BOOL bFirstTrack = TRUE;
for (int nTrack = 0; nTrack < nTocEntries; nTrack++)
{
CTOCEntry & rt = pEntries[nTrack];
if (nSessionNumber == rt.SessionNumber)
{
// skip 1 to 0x63 which is 1 to 99 tracks
if (rt.POINT > 0x63)
{
ps->SetRawPoint((ERawPoint)rt.POINT, &rt);
// 0xA2 is the lead out
if (rt.POINT == 0xA2)
lLeadoutLba = rt.m_lPLBA;
}
else
{
ITrackEntry * pTrack = NULL;
ps->GetTrack(rt.POINT - 1, &pTrack);
if (!pTrack)
{
// Create a track entry and add it to the session object
pTrack = hpCDE::CreateTrackEntry();
ps->AppendTrack(pTrack);
}
// is this the first track
if (bFirstTrack)
{
lSessionStartLba = rt.m_lPLBA;
bFirstTrack = FALSE;
}
// Determine the type of the track from the block data
BYTE pBlockData[CD_RAW_BLOCKSIZE];
HANDLE hData = CreateFile (lpDataFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (INVALID_HANDLE_VALUE == hData)
return FALSE;
// lead out is 6750, lead in is 4500 and first pregap is 150 blocks
// those are not ripped
LONG lTrackStart = rt.m_lPLBA - (6750 + 4500 + 150) * (nSessionNumber - 1);
SetFilePointer(hData, lTrackStart * CDDA_BLOCKSIZE, NULL, FILE_BEGIN);
DWORD dwRead;
ReadFile(hData, pBlockData, CDDA_BLOCKSIZE, &dwRead, NULL);
// Assume the track type is audio if the block type is TT_MODE0
ETrackType tt = m_pDevice->GetTrackType(pBlockData);
pTrack->SetType(TT_MODE0 == tt ? TT_AUDIO : tt);
CloseHandle(hData);
// track lba should be relative to the session start
pTrack->SetPregapStart(rt.m_lPLBA - lSessionStartLba);
pTrack->SetTrackStart(rt.m_lPLBA - lSessionStartLba);
if (nTrack < nTocEntries - 1 && pEntries[nTrack + 1].POINT < 0x63)
{
// track end is the beginning of next track
pTrack->SetTrackEnd(pEntries[nTrack + 1].m_lPLBA - lSessionStartLba);
pTrack->SetPostgapEnd(pEntries[nTrack + 1].m_lPLBA - lSessionStartLba);
}
else
{
// last track ends at lead out start
pTrack->SetTrackEnd(lLeadoutLba - lSessionStartLba);
pTrack->SetPostgapEnd(lLeadoutLba - lSessionStartLba);
}
pTrack->Release();
}
}
}
if (1 == nSessionNumber)
pFirstSession = ps;
}
delete [] pEntries;
return pFirstSession;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -