#include "./playlist.h" #include "../Agave/DecodeFile/ifc_audiostream.h" #include #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(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