winamp/Src/burnlib/playlist.cpp
2024-09-24 14:54:57 +02:00

686 lines
No EOL
22 KiB
C++

#include "./playlist.h"
#include "../Agave/DecodeFile/ifc_audiostream.h"
#include <strsafe.h>
#include "../winamp/wa_ipc.h"
BurnerPlaylist::BurnerPlaylist()
{
evntCancel = NULL;
}
BurnerPlaylist::~BurnerPlaylist()
{
if (manager.GetDecodeAPI())
{
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
factory->releaseInterface(manager.GetDecodeAPI());
manager.SetDecodeAPI(NULL);
}
clear();
}
HRESULT BurnerPlaylist::Load(const wchar_t *filename)
{
if (!WASABI_API_SVC) return PLAYLISTMANAGER_FAILED;
waServiceFactory *plmFactory = WASABI_API_SVC->service_getServiceByGuid(api_playlistmanagerGUID);
if (!plmFactory) return 0;
api_playlistmanager *plManager = (api_playlistmanager*)plmFactory->getInterface();
if (!plManager) return 0;
length = 0;
int retCode = plManager->Load(filename, this);
return (PLAYLISTMANAGER_SUCCESS == retCode);
}
DWORD BurnerPlaylist::GetTotalSectors(void)
{
DWORD ts = 0;
for(size_t i = 0; i < GetCount(); i++)
{
ts += BurnerVector::at(i)->GetSizeInSectors();
}
return ts;
}
DWORD BurnerPlaylist::GetStatus(DWORD *retCode)
{
if(retCode) *retCode = errorCode;
return statusCode;
}
size_t BurnerPlaylist::GetStateCount(DWORD state, DWORD code)
{
size_t count = 0;
for (size_t i = 0; i < GetCount(); i++)
{
if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) count++;
}
return count;
}
DWORD BurnerPlaylist::GetStateLengthMS(DWORD state, DWORD code)
{
DWORD len = 0;
for (size_t i = 0; i < GetCount(); i++)
{
if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) len += BurnerVector::at(i)->GetLength();
}
return len;
}
DWORD BurnerPlaylist::GetStateSectors(DWORD state, DWORD code)
{
DWORD ts = 0;
for(size_t i = 0; i < GetCount(); i++)
{
if (BurnerVector::at(i)->itemStatus == state && BurnerVector::at(i)->errorCode == code) ts += BurnerVector::at(i)->GetSizeInSectors();
}
return ts;
}
HRESULT BurnerPlaylist::CheckLicense(BURNERPLAYLISTCALLBACK notifyCB, void *userparam)
{
this->notifyCB = notifyCB;
this->userparam = userparam;
statusCode = BURNERPLAYLIST_LICENSINGSTARTING;
errorCode = BURNERPLAYLIST_SUCCESS;
OnNotify(statusCode, errorCode, 0);
size_t count = BurnerVector::size();
size_t realCount = 0;
manager.CancelBurn(); // ha-ha
wchar_t **filenames = (count) ? (wchar_t**)malloc(count*sizeof(wchar_t*)) : NULL;
DWORD nc, ec;
for (size_t i = 0; i < count; i++)
{
nc = BurnerVector::at(i)->GetStatus(&ec);
if (nc == BURNERITEM_READY ||
((nc == BURNERITEM_LICENSED || nc == BURNERITEM_DECODED) && ec == BURNERITEM_SUCCESS))
{
filenames[realCount] = (wchar_t*)BurnerVector::at(i)->GetFullName();
BurnerVector::at(i)->itemStatus = BURNERITEM_LICENSING;
errorCode = BURNERPLAYLIST_ITEMADDED;
realCount++;
}
else
{
BurnerVector::at(i)->itemStatus = BURNERITEM_SKIPPED;
errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
}
OnNotify(statusCode, errorCode, i);
}
if (realCount == 0)
{
statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
errorCode = BURNERPLAYLIST_NOFILES;
OnNotify(statusCode, errorCode, 0);
if (filenames) free(filenames);
return statusCode;
}
if (!manager.GetDecodeAPI())
{
api_decodefile *decoder = NULL;
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
if (factory) decoder = (api_decodefile *)factory->getInterface();
if (!factory || !decoder)
{
statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
errorCode = BURNERPLAYLIST_DECODESERVICEFAILED;
OnNotify(statusCode, errorCode, 0);
free(filenames);
return statusCode;
}
manager.SetDecodeAPI(decoder);
}
manager.SetFiles(realCount, (const wchar_t**)filenames, this);
free(filenames);
return statusCode;
}
HRESULT BurnerPlaylist::Decode(void* hFile, BURNERPLAYLISTCALLBACK notifyCB, void *userparam, BOOL block)
{
this->notifyCB = notifyCB;
this->userparam = userparam;
this->hFile = hFile;
hThread = NULL;
statusCode = BURNERPLAYLIST_DECODESTARTING;
errorCode = BURNERPLAYLIST_SUCCESS;
OnNotify(statusCode, errorCode, 0);
if (!manager.GetDecodeAPI())
{
api_decodefile *decoder = NULL;
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
if (factory) decoder = (api_decodefile *)factory->getInterface();
if (!factory || !decoder)
{
statusCode = BURNERPLAYLIST_DECODEFINISHED;
errorCode = BURNERPLAYLIST_DECODESERVICEFAILED;
OnNotify(statusCode, errorCode, 0);
return statusCode;
}
manager.SetDecodeAPI(decoder);
}
if (block)
{
statusCode = DecodeWorker(this);
OnNotify(statusCode, errorCode, 100);
if (manager.GetDecodeAPI())
{
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
factory->releaseInterface(manager.GetDecodeAPI());
manager.SetDecodeAPI(NULL);
}
}
else
{
DWORD id;
hThread = CreateThread(NULL, 0, DecodeWorker, this, 0, &id);
if (NULL == hThread)
{
statusCode = BURNERPLAYLIST_DECODEFINISHED;
errorCode = BURNERPLAYLIST_THREADCREATEFAILED;
OnNotify(statusCode, errorCode, 0);
}
}
return statusCode;
}
HRESULT BurnerPlaylist::Burn(obj_primo *primoSDK, DWORD drive, DWORD maxspeed, DWORD burnFlags, void* hFile,
BURNERPLAYLISTCALLBACK notifyCB, void *userparam, BOOL block)
{
this->primoSDK = primoSDK;
this->drive = drive;
this->hFile = hFile;
this->maxspeed = maxspeed;
this->burnFlags = burnFlags;
this->notifyCB = notifyCB;
this->userparam = userparam;
statusCode = BURNERPLAYLIST_BURNSTARTING;
errorCode = BURNERPLAYLIST_SUCCESS;
evntCancel = CreateEvent(NULL, FALSE, FALSE, NULL);
OnNotify(statusCode, errorCode, 0); // here we go
DWORD retCode;
DWORD dwUnits[2];
dwUnits[0] = drive;
dwUnits[1] = 0xFFFFFFFF;
retCode = primoSDK->NewAudio(dwUnits);
if (PRIMOSDK_OK != retCode)
{
statusCode = BURNERPLAYLIST_BURNFINISHED;
errorCode = BURNERPLAYLIST_NEWAUDIOFAILED;
OnNotify(statusCode, errorCode, retCode);
return statusCode;
}
if (BurnerVector::size() == 0)
{
statusCode = BURNERPLAYLIST_BURNFINISHED;
errorCode = BURNERPLAYLIST_NOFILES;
OnNotify(statusCode, errorCode, retCode);
return statusCode;
}
size_t i;
for(i = 0; i < BurnerVector::size(); i++)
{
DWORD ec;
if (BURNERITEM_DECODED == BurnerVector::at(i)->GetStatus(&ec) && BURNERITEM_SUCCESS == ec)
{
BurnerVector::at(i)->itemStatus = BURNERITEM_READY;
retCode = BurnerVector::at(i)->AddStream(primoSDK, hFile);
if (PRIMOSDK_OK != retCode)
{
BurnerVector::at(i)->itemStatus = BURNERITEM_BURNED;
BurnerVector::at(i)->errorCode = BURNERITEM_FAILED;
errorCode = BURNERPLAYLIST_ADDITEMFAILED;
break;
}
else errorCode = BURNERPLAYLIST_ITEMADDED;
}
else
{
errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
BurnerVector::at(i)->itemStatus = BURNERITEM_SKIPPED;
}
OnNotify(statusCode, errorCode, i);
}
if (PRIMOSDK_OK != retCode || (WAIT_OBJECT_0 == WaitForSingleObject(evntCancel, 0)))
{
statusCode = (PRIMOSDK_OK == retCode) ? BURNERPLAYLIST_BURNCANCELING : BURNERPLAYLIST_BURNFINISHING;
errorCode = (PRIMOSDK_OK == retCode) ? BURNERPLAYLIST_ABORTED : BURNERPLAYLIST_ADDITEMFAILED;
BPLRUNSTATUS burnStatus;
for(i = 0; i < BurnerVector::size(); i++)
{
burnStatus.iIndex = (int)i;
if (BURNERITEM_SKIPPED == BurnerVector::at(burnStatus.iIndex)->itemStatus) continue;
BurnerVector::at(burnStatus.iIndex)->itemStatus = (PRIMOSDK_OK == retCode) ? BURNERITEM_ABORTED : BURNERITEM_FAILED;
OnNotify(statusCode, errorCode, (ULONG_PTR)&burnStatus);
}
CloseHandle(evntCancel);
evntCancel = NULL;
primoSDK->CloseAudio();
statusCode = BURNERPLAYLIST_BURNFINISHED;
OnNotify(statusCode, errorCode, i);
return statusCode;
}
if (block)
{
DWORD notifyCode = BurnerWorker(this);
OnNotify(BURNERPLAYLIST_BURNFINISHED, notifyCode, errorCode);
}
else
{
DWORD id;
hThread = CreateThread(NULL, 0, BurnerWorker, this, 0, &id);
if (NULL == hThread)
{
statusCode = BURNERPLAYLIST_BURNFINISHED;
errorCode = BURNERPLAYLIST_THREADCREATEFAILED;
OnNotify(statusCode, errorCode, i);
}
}
return statusCode;
}
DWORD BurnerPlaylist::AddCompilationToCDDB(void)
{
wchar_t buf[64] = {0};
wchar_t albumbuf[256]= L"Mix CD ";
wchar_t dateString[128] = {0};
GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER, NULL, NULL, dateString, 128);
StringCchCatW(albumbuf, 256, dateString);
StringCchPrintfW(buf, 64, L"cda://%c.cda", (char)drive);
extendedFileInfoStructW efis = { buf, L"album", albumbuf, 256, };
if (SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW))
{
efis.metadata = L"albumartist";
efis.ret = L"Various Artists";
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
efis.metadata = L"genre";
efis.ret = L"Mix";
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
SYSTEMTIME syst;
GetLocalTime(&syst);
if (syst.wYear)
{
wchar_t yearbuf[64] = {0};
StringCchPrintfW(yearbuf, 64, L"%04d", syst.wYear);
efis.metadata = L"year";
efis.ret = yearbuf;
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
}
wchar_t buf2[32] = {0};
int index = 1;
for (size_t i = 0;i < GetCount();i++)
{
DWORD is, ec;
is = BurnerVector::at(i)->GetStatus(&ec);
if (BURNERITEM_BURNED == is && BURNERITEM_SUCCESS == ec)
{
StringCchPrintfW(buf, 64, L"cda://%c,%d.cda", (char)drive, i);
lstrcpynW(buf2, L"title", 32);
efis.metadata = buf2;
efis.ret = const_cast<wchar_t*>(BurnerVector::at(i)->GetTitle());
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
lstrcpynW(buf2, L"artist", 32);
efis.ret=L"Various Artists"; // TODO: use actual track artist
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)&efis, IPC_SET_EXTENDED_FILE_INFOW);
index++;
}
}
SendMessageW(winampWnd, WM_WA_IPC, (WPARAM)0, IPC_WRITE_EXTENDED_FILE_INFO);
}
return 1;
}
DWORD WINAPI BurnerPlaylist::DecodeWorker(void* param)
{
DWORD retCode;
BurnerPlaylist *playlist = (BurnerPlaylist*)param;
playlist->percentStep = (float)(1.f / ((double)playlist->GetCount()));
playlist->activeDecode = NULL;
DWORD itemError = BURNERITEM_SUCCESS;
// for nice ui reason lets do it twice
playlist->statusCode = BURNERPLAYLIST_DECODESTARTING;
for(size_t i = 0; i < playlist->GetCount(); i++)
{
DWORD ec;
if (BURNERITEM_LICENSED == playlist->at(i)->GetStatus(&ec) && BURN_OK == ec)
{
playlist->errorCode = BURNERPLAYLIST_ITEMADDED;
playlist->at(i)->itemStatus = BURNERITEM_READY;
}
else
{
playlist->errorCode = BURNERPLAYLIST_ADDITEMSKIPPED;
playlist->at(i)->itemStatus = BURNERITEM_SKIPPED;
}
playlist->OnNotify(playlist->statusCode, playlist->errorCode, i);
}
// actual work
for(size_t i = 0; i < playlist->GetCount(); i++)
{
if (BURNERITEM_READY == playlist->at(i)->GetStatus(NULL))
{
BPLDECODEINFO info;
info.iInstance = playlist->at(i);
info.iIndex = (int)i;
info.iNotifyCode = 0;
info.iErrorCode = 0;
info.percentCompleted = (playlist->activeDecode) ? playlist->percentStep*i*100.0f : 0;
playlist->activeDecode = &info;
playlist->statusCode = BURNERPLAYLIST_DECODEPROGRESS;
playlist->errorCode = BURNERPLAYLIST_DECODENEXTITEM;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)playlist->activeDecode);
retCode = playlist->at(i)->Decode(&playlist->manager, playlist->hFile, OnItemDecode, playlist);
if (BURNERITEM_SUCCESS != retCode)
{
itemError = retCode;
}
if (BURNERITEM_ABORTED == retCode)
{
playlist->statusCode = BURNERPLAYLIST_DECODECANCELING;
playlist->errorCode = BURNERPLAYLIST_ABORTED;
DWORD notifyCode = BURNERITEM_DECODEFINISHED;
for(size_t k = i; k < playlist->GetCount(); k++)
{
info.iIndex = (int)k;
info.iInstance = playlist->at(k);
info.iInstance->errorCode = BURNERITEM_ABORTED;
info.iInstance->itemStatus = BURNERITEM_ABORTED;
OnItemDecode(info.iInstance, playlist, notifyCode, info.iInstance->errorCode);
}
break;
}
}
}
// release decoderAPI
waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(decodeFileGUID);
factory->releaseInterface(playlist->manager.GetDecodeAPI());
playlist->manager.SetDecodeAPI(NULL);
if (playlist->hThread)
{
CloseHandle(playlist->hThread);
playlist->hThread = NULL;
}
playlist->statusCode = BURNERPLAYLIST_DECODEFINISHED;
if (playlist->GetCount() == 0) playlist->errorCode = BURNERPLAYLIST_NOFILES;
else if (BURNERITEM_ABORTED == itemError) playlist->errorCode = BURNERPLAYLIST_ABORTED;
else if (BURNERITEM_SUCCESS == itemError) playlist->errorCode = BURNERPLAYLIST_SUCCESS;
else playlist->errorCode = BURNERPLAYLIST_FAILED;
playlist->OnNotify(playlist->statusCode , playlist->errorCode, (ULONG_PTR)playlist->activeDecode);
playlist->activeDecode = NULL;
return playlist->statusCode;
}
DWORD WINAPI BurnerPlaylist::BurnerWorker(void* param)
{
DWORD primoCode;
BurnerPlaylist *playlist = (BurnerPlaylist*)param;
WABURNSTRUCT bs;
playlist->statusCode = BURNERPLAYLIST_BURNSTARTING;
playlist->errorCode = BURNERPLAYLIST_BEGINBURN;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, 0);
primoCode = BeginBurn(playlist->primoSDK, playlist->drive, &bs);
bs.eject = TRUE;
DWORD leadin = 0;
BPLRUNSTATUS burnStatus;
ZeroMemory(&burnStatus, sizeof(BPLRUNSTATUS));
burnStatus.iIndex = -1;
BOOL canceled = FALSE;
DWORD itemSector = 0;
BOOL cp1 = FALSE;
if (PRIMOSDK_OK != primoCode)
{
playlist->errorCode = BURNERPLAYLIST_BEGINBURNFAILED;
}
else
{
playlist->statusCode = BURNERPLAYLIST_BURNPROGRESS;
primoCode = playlist->primoSDK->WriteAudioEx(playlist->burnFlags, playlist->maxspeed, 0x00);
if (PRIMOSDK_OK == primoCode)
{
DWORD waitResult;
while(BURNERPLAYLIST_BURNPROGRESS == playlist->statusCode && WAIT_TIMEOUT == (waitResult = WaitForSingleObject(playlist->evntCancel, 500)))
{
primoCode = playlist->primoSDK->RunningStatus(PRIMOSDK_GETSTATUS, &burnStatus.sCurrent, &burnStatus.sTotal);
if (PRIMOSDK_RUNNING == primoCode)
{
playlist->statusCode = BURNERPLAYLIST_BURNPROGRESS;
if (burnStatus.sCurrent == 0)
{
if (cp1) continue; // do not send anymore
playlist->errorCode = BURNERPLAYLIST_WRITELEADIN; //BURNERPLAYLIST_DISCOPEN
cp1 = TRUE;
}
else if (burnStatus.sCurrent > 0 && (!leadin || leadin == burnStatus.sCurrent))
{
if (!leadin)
{
leadin = burnStatus.sCurrent;
playlist->errorCode = BURNERPLAYLIST_WRITELEADIN; // unreachable :)
}
continue;
}
else if (burnStatus.sCurrent == burnStatus.sTotal)
{
if (burnStatus.iIndex >= 0 && BURNERITEM_BURNING == playlist->at(burnStatus.iIndex)->itemStatus)
{
playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_BURNED;
playlist->at(burnStatus.iIndex)->errorCode = BURNERITEM_SUCCESS;
playlist->at(burnStatus.iIndex)->percentCompleted = 100;
playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMEND, (ULONG_PTR)&burnStatus);
}
if (burnStatus.iIndex == -1) continue;
playlist->errorCode = BURNERPLAYLIST_WRITELEADOUT;
burnStatus.iIndex = -1;
burnStatus.iInstance = NULL;
}
else
{
playlist->errorCode = BURNERPLAYLIST_WRITEDATA;
while (itemSector < burnStatus.sCurrent && burnStatus.iIndex < (int)playlist->size())
{ if (burnStatus.iIndex >= 0 && BURNERITEM_BURNING == playlist->at(burnStatus.iIndex)->itemStatus)
{
playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_BURNED;
playlist->at(burnStatus.iIndex)->errorCode = BURNERITEM_SUCCESS;
playlist->at(burnStatus.iIndex)->percentCompleted = 100;
playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMEND, (ULONG_PTR)&burnStatus);
}
while (++burnStatus.iIndex < (int)playlist->size() && BURNERITEM_READY != playlist->at(burnStatus.iIndex)->itemStatus);
if (burnStatus.iIndex < (int)playlist->size()) itemSector += playlist->at(burnStatus.iIndex)->GetSizeInSectors();
}
if ( burnStatus.iIndex >= 0 && burnStatus.iIndex < (int)playlist->size())
{
BurnerItem *bi = playlist->at(burnStatus.iIndex);
burnStatus.iInstance = bi;
if (BURNERITEM_READY == bi->itemStatus)
{
bi->itemStatus = BURNERITEM_BURNING;
bi->percentCompleted = 0;
playlist->OnNotify(playlist->statusCode, BURNERPLAYLIST_WRITEITEMBEGIN, (ULONG_PTR)&burnStatus);
}
if (BURNERITEM_SUCCESS == bi->errorCode)
{
DWORD is = bi->GetSizeInSectors();
bi->itemStatus = BURNERITEM_BURNING;
bi->percentCompleted = (is - (itemSector - burnStatus.sCurrent))*100 / is;
}
else
{
bi->itemStatus = BURNERITEM_BURNED;
bi->errorCode = BURNERITEM_SUCCESS;
bi->percentCompleted = 100;
}
}
}
playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
}
else
{
playlist->errorCode = BURNERPLAYLIST_WRITEAUDIOFAILED;
break;
}
}
if (WAIT_OBJECT_0 == waitResult)
{ // aborting
canceled = TRUE;
playlist->statusCode = BURNERPLAYLIST_BURNCANCELING;
playlist->errorCode = BURNERPLAYLIST_ABORTED;
playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_CANCELING;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
DWORD test = playlist->primoSDK->RunningStatus(PRIMOSDK_ABORT, &burnStatus.sCurrent, &burnStatus.sTotal);
do
{
Sleep(1000);
primoCode = playlist->primoSDK->RunningStatus(PRIMOSDK_GETSTATUS, &burnStatus.sCurrent, &burnStatus.sTotal);
}while(PRIMOSDK_RUNNING == primoCode);
for (size_t i = 0; i < playlist->GetCount(); i++)
{
burnStatus.iIndex = (int)i;
DWORD cs = playlist->at(burnStatus.iIndex)->itemStatus;
if (BURNERITEM_BURNING != cs && BURNERITEM_READY != cs && BURNERITEM_CANCELING != cs) continue;
playlist->at(burnStatus.iIndex)->itemStatus = BURNERITEM_ABORTED;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, (ULONG_PTR)&burnStatus);
}
}
}
else
{
playlist->errorCode = BURNERPLAYLIST_WRITEAUDIOFAILED;
}
}
if (PRIMOSDK_USERABORT == primoCode) playlist->errorCode = BURNERPLAYLIST_ABORTED;
else if (PRIMOSDK_OK == primoCode) playlist->errorCode = BURNERPLAYLIST_SUCCESS;
playlist->statusCode = BURNERPLAYLIST_BURNFINISHING;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, 0);
// check unit status and notify later
DWORD statCode, cmd(0), sense(0), asc(0), ascq(0);
statCode = playlist->primoSDK->UnitStatus(&bs.drive, &cmd, &sense, &asc, &ascq);
bs.eject = playlist->ejectDone;
primoCode = EndBurn(&bs);
if (PRIMOSDK_OK != primoCode) playlist->errorCode = BURNERPLAYLIST_ENDBURNFAILED;
playlist->primoSDK->CloseAudio();
if (playlist->hThread)
{
CloseHandle(playlist->hThread);
playlist->hThread = NULL;
}
primoCode = (0xFF000000 & (statCode << 24)) | (0x00FF0000 & (sense << 16)) | (0x0000FF00 & (asc << 8)) | (0x000000FF & ascq);
if (BURNERPLAYLIST_SUCCESS == playlist->errorCode && statCode != PRIMOSDK_OK) playlist->errorCode = BURNERPLAYLIST_FAILED;
if (BURNERPLAYLIST_SUCCESS == playlist->errorCode && (PRIMOSDK_WRITE == (playlist->burnFlags&PRIMOSDK_WRITE)))
{
playlist->manager.BurnFinished();
}
else
{
playlist->manager.CancelBurn();
}
playlist->statusCode = BURNERPLAYLIST_BURNFINISHED;
playlist->OnNotify(playlist->statusCode, playlist->errorCode, primoCode);
return playlist->statusCode;
}
DWORD BurnerPlaylist::OnNotify(DWORD notifyCode, DWORD errorCode, ULONG_PTR param)
{
DWORD retCode = (notifyCB) ? notifyCB(this, userparam, notifyCode, errorCode, param) : BURNERPLAYLIST_CONTINUE;
if ( BURNERPLAYLIST_STOP == retCode && evntCancel) SetEvent(evntCancel);
return retCode;
}
void BurnerPlaylist::OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
{
if (NULL == filename) return;
BurnerItem *item = new BurnerItem();
item->Create(filename,title, lengthInMS);
length += lengthInMS;
push_back(item);
}
DWORD WINAPI BurnerPlaylist::OnItemDecode(void* sender, void *param, DWORD notifyCode, DWORD errorCode)
{
BurnerPlaylist *pl = (BurnerPlaylist*)param;
pl->activeDecode->iNotifyCode = notifyCode;
pl->activeDecode->iErrorCode = errorCode;
pl->activeDecode->percentCompleted += pl->percentStep;
pl->statusCode = BURNERPLAYLIST_DECODEPROGRESS;
pl->errorCode = BURNERPLAYLIST_DECODEITEM;
DWORD retCode = pl->OnNotify(pl->statusCode , pl->errorCode , (ULONG_PTR)pl->activeDecode);
return (BURNERPLAYLIST_STOP == retCode) ? BURNERITEM_STOP : BURNERITEM_CONTINUE;
}
void BurnerPlaylist::OnLicenseCallback(size_t numFiles, WRESULT *results)
{
statusCode = BURNERPLAYLIST_LICENSINGPROGRESS;
DWORD errorCode = BURNERPLAYLIST_SUCCESS;
size_t realCount = 0;
size_t allowed = 0;
for (size_t i = 0; i < BurnerVector::size(); i++)
{
if (BURNERITEM_LICENSING == BurnerVector::at(i)->itemStatus)
{
if (realCount == numFiles)
{
statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
errorCode = BURNERPLAYLIST_WRONGFILECOUNT;
break;
}
BurnerVector::at(i)->itemStatus = BURNERITEM_LICENSED;
BurnerVector::at(i)->errorCode = results[realCount];
OnNotify(statusCode, results[realCount], (LPARAM)i);
if (BURN_OK != results[realCount]) errorCode = BURNERPLAYLIST_FILENOTLICENSED;
else allowed++;
realCount++;
}
}
statusCode = BURNERPLAYLIST_LICENSINGFINISHED;
OnNotify(statusCode, errorCode, allowed);
}
#define CBCLASS BurnerPlaylist
START_DISPATCH;
VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
END_DISPATCH;
#undef CBCLASS